0% found this document useful (0 votes)
10 views114 pages

Data Types and Variables-: Int Int Int Sizeof

The document provides an overview of data types, variables, and basic programming concepts in C++, including integer representation, type casting, and logical operations. It covers various programming constructs such as loops, functions, and array manipulations, along with examples of common algorithms like Fibonacci series and searching techniques. Additionally, it discusses bitwise operations, input/output handling, and specific coding challenges related to arrays and integers.

Uploaded by

vodnala srujana
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views114 pages

Data Types and Variables-: Int Int Int Sizeof

The document provides an overview of data types, variables, and basic programming concepts in C++, including integer representation, type casting, and logical operations. It covers various programming constructs such as loops, functions, and array manipulations, along with examples of common algorithms like Fibonacci series and searching techniques. Additionally, it discusses bitwise operations, input/output handling, and specific coding challenges related to arrays and integers.

Uploaded by

vodnala srujana
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 114

Data Types and Variables-

Integer - 4 Bytes, 32 Bits (Max value: 231 - 1)


Character - 1 Byte, 8 Bits (Max value: 27 - 1)
Bool - 0.125 Bytes, 1 Bit
Float - 8 Bytes, 64 Bits (7 decimal digits)
Double - 8 Bytes, 64 Bits (15 decimal digits)

Checking the Size of a Data Type-

int main() {
int a = 123;
int size = sizeof(a);
cout << "Size of a: " << size << endl;
}

How Data is stored-

int a = 5;
In this case, 5 in binary is “101” which is 3 bits but, the total space of an int is 32 bits.
As a result, the first 29 bits are stored as 0.

5=00000000000000000000000000000101

In case of a character like ‘a’, we consider the binary value of the ASCII code, in this
case, ‘97’. Thus, ‘a’ = 0 1 1 0 0 0 0 1 as ‘97’ = 1 1 0 0 0 0 1.

Type Casting- Converting a data type from one to another.

int main() {
int a = 'a';
cout << a << endl; //Output: 97 (ASCII Code)

char ch = 98;
cout << ch << endl; //Output: b (ASCII Value)
}

Storing Negative Numbers- Positive number starts with 0 whereas a negative


number starts with 1.

1. Ignore the negative sign.


2. Convert into binary representation.
3. Take 2’s complement and store.

1’s Complement- Switch the bits, 0 to 1 and 1 to 0.


2’s Complement- Add 1 to the 1’s complement.
Signed Integer- Positive and Negative integers
UnSigned Integer- Positive Integer Only
Opeator Note-
1. int/int = integer (no decimal)
2. float/int = float
3. double/int = double

Logical Operator-
1. &&- And
2. || - Or
3. ! - Reverse

Taking Input from User-

int main() {
//Normal integer input
int a,b;
cin >> a >> b;

//Gives ASCII value of output


a = cin.get();
}

While Loop-

int main() {
int n;
cin >> n;

int i = 1;
int sum = 0;

while(i<=n) {
sum = sum + i;
i = i + 1;
}

cout << "Sum: " << sum << endl;


}

Pattern Problems-

Simple Star Pattern Problems


Solved Using For and While Loop
/*

****
****
****
****

*/

#include<iostream>
using namespace std;

int main() {
int n;
cin >> n;

int i = 1;

while(i<=n) {
int j = 1;
while(j<=n) {
cout << "*";
j++;
}
cout << endl;
i++;
}
}

/*

1 1 1
2 2 2
3 3 3

*/

#include<iostream>
using namespace std;

int main() {
int n;
cin >> n;

int i = 1;

while(i<=n) {
int j = 1;
while(j<=n) {
cout << i;
j++;
}
cout << endl;
i++;
}
}

/*

1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4

*/

#include<iostream>
using namespace std;

int main() {
int n;
cin >> n;

int i = 1;

while(i<=n) {
int j = 1;
while(j<=n) {
cout << j;
j++;
}
cout << endl;
i++;
}
}

/*

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

*/

#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;

int i = 1;
int count = 1;

while(i<=n) {
int j = 1;
while(j<=n) {
cout << count << " ";
count++;
j++;
}
cout << endl;
i++;
}
}

/*

*
**
***
****

*/

#include<iostream>
using namespace std;

int main() {
int n = 4;

int row = 1;

while(row<=n) {
int col = 1;
while(col<=row) {
cout << "*";
col++;
}
cout << endl;
row++;
}
}

Bitwise Operator-
AND (&)

X Y Result

0 0 0

0 1 0

1 0 0

1 1 1

OR (|)

X Y Result

0 0 0

0 1 1

1 0 1

1 1 1

XOR (^)

X Y Result

0 0 0

0 1 1

1 0 1

1 1 0

NOT (~)- Invert the Bit

Left Shift- Shift the binary to the left and add 0 at the end.
Right Shift- Shift the binary to the right and add 0 at the start.

i++: Post Increment ++i: Pre Increment

For Loop-

int main() {
int n;
cout << "Enter N: " << endl;
cin >> n;

int sum = 0;

for(int i=1; i<=n; i++) {


sum += i;
}

cout << sum << endl;


}

Fibonacci Series-

#include<iostream>
using namespace std;

int main() {
int n = 10;

int a = 0;
int b = 1;

cout << a << " " << b << " ";

for(int i=1; i<=n; i++) {


int nextNumber = a+b;
cout << nextNumber << " ";

a = b;
b = nextNumber;

}
}

(Q1) Count the number of 1 bits of an unsigned integer (Hamming Weigth).

class Solution {
public:
int hammingWeight(uint32_t_n) {
int count = 0;
while(n!=0) {
//checking the last bit
if(n&1) {
count++;
}
//right shift till n=0
n = n>>1;
}
return count;
}
}

(Q2) Subtract the Product and the Sum of Digits of an Integer.

class Solution {
public:
int subtractProductAndSum(int n) {
int prod = 1;
int sum = 0;

while(n!=0) {
int digit = n%10;
prod *= digit;
sum += digit;

n /= 10;
}
int answer = prod - sum;
return answer;
}
};

Decimal to Binary-
1. Divide by 2
2. Store remainder
3. Repeat the above 2 steps until n!=0
4. Reverse the remainder list

#include<iostream>
#include<math.h>
using namespace std;

int main() {
int n;
cin >> n;

int ans = 0;
int i = 0;

while(n!=0) {
int bit = n&1;
ans = (bit * pow(10,i)) + ans; //(10^0 x digit) + answer
n = n>>1; //isse divide by 2 ho jata hai
i++;
}
cout << "Answer: " << ans << endl;
}

Binary to Decimal-
1. If the bit is 1 then add 2place to the final answer
2. If the bit is 0 then ignore

#include<iostream>
#include<math.h>
using namespace std;

int main() {
int n=110;

int i = 0, ans = 0;

while(n!=0) {
int digit = n%10;

if(digit == 1) {
ans += pow(2, i);
}
n /= 10;
i++;
}
cout << ans << endl;
}

(Q3) Given a 32-bit integer x, return x with its digits reversed. If reversing x
causes the value to go outside the signed 32-bit integer range, then return 0.

class Solution {
public:
int reverse(int x) {

int ans = 0;
while(x!=0) {
int digit = x%10;

if((ans > INT_MAX/10) || (ans < INT_MIN/10)) {


return 0;
}

ans = (ans*10) + digit; //number reversing formula


x = x/10;
}
return ans;
}
}

(Q4) Complement of Base 10 Integer, when you flip all the 0 to 1 and all the 1 to
0 in its binary representation.

class Solution {
public:
int bitwiseComplement(int n) {
int m = n;
int mask = 0;

//edge case
if(n==0) {
return 1;
}

while(m!=0) {
mask = (mask<<1) | 1;
m = m >> 1;
}
int ans = (~n) & mask;
return ans;
}
}

(Q5) Power of Two, return True if the number is a power of two. Otherwise,
false.

class Solution {
public:
bool isPowerofTwo(int n) {
int ans = 1;

for(int i=0; i<=30; i++) {


if(ans == n) {
return true;
}
if(ans < INT_MAX/2) {
ans = ans * 2;
}
}
return false;
}
};

Switch-

int main() {
char ch = '1';
cout << endl;

switch(ch) {
case 1: cout << "First" << endl;
cout << "First Again" << endl;
break;

case '1': cout << "Character One" << endl;


break;

default: cout << "Default Case" << endl;


}
}

Function-

//Power Function
int power(int a, int b) {
long long int ans = 1;

for(int i=1; i<=b; i++) {


ans = ans * a;
}

return ans;
}

int main() {
int a, b;
cin >> a >> b;

long long int answer = power(a, b);


cout << "Answer: " << answer << endl;
}
//Even or Odd

bool isEven(int n) {
if(n&1) { //if "and" is true then the number is odd
return 0;
}
return 1;
}

int main() {
int num;
cin >> num;

if(isEven(num)) {
cout << "Even" << endl;
}
else {
cout << "Odd" << endl;
}

cout << num;


return 0;
}

Function Call Stack- First In Last Out

Passing in Function-
1. Pass by Value- Copy is created (not in case of Arrays)
2. Pass by Reference- Original is sent

Arrays - Similar type of items, they are stored in contiguous locations (101, 102, 103
and so on). They are indexed.

#include <iostream>
using namespace std;

//Print function for an array


void printArray(int arr[], int size) {
cout << "Printing: " << endl;
for(int i=0; i<size; i++) {
cout << arr[i] << " ";
}
cout << "DONE!" << endl;
}

int main() {
//Array name "arr" with 10 blocks having garbage value
int arr[10];
printArray(arr, 10);

//Accessing 5th location


arr[4];

//Initialising an Array
int number[3] = {5, 7, 11};
int array[10000] = {0}; //not possible as = {1}

//Size of array- output will be length not no. of elements


int fifthSize = sizeof(fifth)/sizeof(int);
cout << "Size: " << fifthSize << endl;
}

Finding Minimum/Maximum Value of an Array-

#include <iostream>
using namespace std;

//Finding minimum value


int getMin(int num[], int n) {
int mini = INT_MAX;

for(int i=0; i<n; i++) {


//maxi = min(mini, num[i]);
if(num[i] < mini) {
mini = num[i];
}
}

//returning min value


return mini;
}

int main() {
cout << "Min Value: " << getMin(num, size) << endl;
}

Linear Search in Arrays-

bool search(int arr[], int size, int key) {


for(int i=0; i<size; i++) {
if(arr[i] == key) {
return 1;
}
}
return 0;
}

Reversing an Array-

void reverse(int arr[], int n) {


int start = 0;
int end = n-1;

while(start<=end) {
swap(arr[start], arr[end]);
start++;
end--:
}
}

void printArray(int arr[], int n) {


for(int i=0; i<n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}

int main() {
int arr[6] = {1, 4, 0, 5, -2, 15};
int brr[5] = {2, 6, 3, 9, 4};

reverse(arr, 6);
reverse(brr, 5);

printArray(arr, 6);
printArray(brr, 5);

return 0;
}

(Q6) Swap Alternative Elements of an Array.

#include<iostream>
using namespace std;

void printArray(int arr[], int n) {


for(int i=0; i<n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}

void swapAlternative(int arr[], int size) {


for(int i=0; i<size; i+=2) {
if(i+1 < size) {
swap(arr[i], arr[i+1]);
}
}
}

int main() {
int even[8] = {5, 2, 9, 4, 7, 6, 1, 0};
int odd[5] = {11, 33, 9, 76, 43};

swapAlternative(even, 8);
printArray(even, 8);

return 0;
}

(Q7) One element is unique and all other elements are 2 in number, find the
unique element in the array.

int main() {
int ans = 0;
for(int i=0; i<size; i++) {
ans = ans^arr[i]; //XOR(^): a^a = 0
}
return ans;
}

(Q8) Given an array of integers arr, return true if the number of occurrences of
each value in the array is unique or false otherwise.

class Solution {
public:
bool uniqueOccurrences(vector<int>& arr) {
vector<int> ans;
int size = arr.size();
int i = 0;
sort(arr.begin(), arr.end());
while(i < size){
int count = 1;
for(int j =i+1; j<size; j++){
if(arr[i] == arr[j]){
count++;
}
else{
break;
}
}
ans.push_back(count);
i = i+count;
}
size = ans.size();
sort(ans.begin(),ans.end());
for(int i = 0; i<size-1; i++){
if(ans[i] == ans[i+1]){
return false;
}
}
return true;
}
};

(Q9) Find the one duplicate element in an array.

int findDuplicate(vector<int> &arr) {


int ans = 0;

//XORing all array elements


for(int i=0; i<arr.size(); i++) {
ans = ans^arr[i];
}

//XOR [1, n-1]


for(int i=1; i<arr.size(); i++) {
ans = ans^i;
}
return ans;
}

/*
4 2 1 3 1
0 ^ 4 ^ 2 ^ 1 ^ 3 ^ 1 ^ 1 ^ 2 ^ 3 ^ 4
*/

(Q10) Find All Duplicates in an Array. Given an integer array nums of length n
where all the integers of nums are in the range [1, n] and each integer appears
once or twice, return an array of all the integers that appear twice.
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
vector<int> ans;
int n = nums.size();

for(int i=0; i<n; i++) {


int val = abs(nums[i]);
if(nums[val-1]<0) ans.push_back(val);
else nums[val-1] *= -1;
}
return ans;
}
};

(Q11) Intersection of 2 Arrays.

//TLE
int main() {
vector<int> ans;

for(int i=0; i<n; i++) {


int element = arr1[i];

for(int j=0; j<m; j++) {


if(element == arr2[j]) {
ans.push_back(element);
arr2[j] = INT_MIN;
break;
}
}
}
return ans;
}

//Again TLE
int main() {
vector<int> ans;
for(int i=0; i<n; i++) {
int element = arr1[i];

for(int j=0; j<m; j++) {


if(element < arr2[j]) {
break;
}

if(element == arr2[j]) {
ans.push_back(element);
arr2[j] = INT_MIN;
break;
}
}
}
return ans;
}

//Perfect
int main() {
int i=0, j=0;
vector<int> ans;

while(i<n && j<m) {


if(arr1[i] == arr2[j]) {
ans.push_back(arr[i]);
i++;
j++;
}
else if (arr1[i] < arr2[j]) {
i++;
}
else{
j++;
}
}
return ans;
}

(Q12) Pair Sum.

int main() {
vector<vector<int>> ans;

for(int i=0; i<arr.size(); i++) {


for(int j=i+1; j<arr.size(); j++) {
if(arr[i] + arr[j] == s) {
vector<int> temp;
temp.push_back(min(arr[i], arr[j]));
temp.push_back(max(arr[i], arr[j]));
ans.push_back(temp);
}
}
}
sort(ans.begin(), ans.end());
return ans;
}
(Q13) Puts 0s on the left side and 1s on the right side.

void printArray(int arr[], int n) {


for(int i=0; i<n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}

void sortOne(int arr[], int n) {


int left = 0, right = n-1;

while(left < right) {


while(arr[left] == 0 && left < right) {
left++;
}
while(arr[right] == 1 && left < right) {
right--;
}
if(left < right) {
swap(arr[left], arr[right]);
left++;
right--;
}
}
}

int main() {
int arr[8] = {1, 1, 0, 0, 0, 0, 1, 0};

sortOne(arr, 8);
printArray(arr, 8);
}

Time Complexity-
1. Big O Notation- Upper Bound
2. Theta- For average case complexity
3. Omega- Lower Bound

Types of Time Complexity-


1. Constant Time- O(1)
2. Linear Time- O(n)
3. Logarithmic Time- O(log n)
4. Quadratic Time- O(n2)
5. Cubic Time- O(n3)

Levels- O(1) < O(LogN) < O(N) < O(NlogN) < O(N2) < O(N3) < O(2n) < O(N!)

Binary Search-
Time Complexity- O(Log n)
Space Complexity- O(1)

#include<iostream>
using namespace std;

int binarySearch(int arr[], int size, int key) {


int start = 0;
int end = size-1;

int mid = start + (end-start)/2;

while(start<=end) {
if(arr[mid] == key) {
return mid;
}

if(key > arr[mid]) {


start = mid + 1;
}
else{
end = mid - 1;
}
mid = start + (end-start)/2;
}
return -1;
}

int main() {
int even[6] = {2, 4, 6, 8, 12, 18};
int odd[5] = {3, 8, 11, 14, 16};

int evenIndex = binarySearch(even, 6, 20);


cout << evenIndex << endl;

int oddIndex = binarySearch(odd, 5, 20);


cout << oddIndex << endl;
}

(Q14) First and Last Position of an Element in Sorted Array.

#include<iostream>
using namespace std;

int firstOcc(int arr[], int n, int key) {


int s = 0; e = n-1;
int mid = s + (e-s)/2;
int ans = -1;
while(s<=e) {
if(arr[mid] == key) {
ans = mid;
e = mid - 1;
}
else if(key > arr[mid]) {
s = mid + 1;
}
else if(key < arr[mid]) {
e = mid - 1;
}

mid = s + (e-s)/2;
}
}

int lastOcc(int arr[], int n, int key) {


int s = 0; e = n-1;
int mid = s + (e-s)/2;
int ans = -1;

while(s<=e) {
if(arr[mid] == key) {
ans = mid;
s = mid + 1;
}
else if(key > arr[mid]) {
s = mid + 1;
}
else if(key < arr[mid]) {
e = mid - 1;
}

mid = s + (e-s)/2;
}
}

int main() {
int even[5] = {1, 2, 3, 3, 5};
cout << "First Occurance of 3: " << firstOcc(arr, 5, 3) <<
endl;
cout << "Last Occurance of 3: " << lastOcc(arr, 5, 3) << endl;

return 0;
}

(Q15) Peak Element in a Mountain Array.


int main() {
int s = 0;
int e = arr.size() - 1;

int mid = s + (e-s)/2;

while(s<e) {
if(arr[mid] < arr[mid+1]) {
s = mid + 1;
}
else{
e = mid;
}
mid = s + (e-s)/2;
}
return s;
}

(Q19) Find Pivot in an Array.

#include<iostream>
using namespace std;

int getPivot(int arr[], int n) {


int s = 0;
int e = n-1;
int mid = s + (e-s)/2;

while(s<e) {
if(arr[mid] >= arr[0]) {
s = mid+1;
}
else{
e = mid;
}
mid = s + (e-s)/2;
}
return s; //return e; also works
}

int main() {
int arr[5] = {8, 10, 17, 1, 3};
cout << "Pivot: " << getPivot(arr, 5) << endl;
}

(Q20) Square Root using Binary Search.


int binarySearch(int n) {
int s = 0;
int e = n;
long long int mid = s + (e-s)/2;

long long int ans = -1;


while(s<=e) {
long long int square = mid*mid;

if(square == n) {
return mid;
}
if(square < n) {
ans = mid;
s = mid+1;
}
else{
e = mid-1;
}
mid = s + (e-s)/2;
}
return ans;
}

int mySqrt(int x) {
return binarySearch(x);
}

Selection Sort-
Time Complexity- O(n2)
Space Complexity- O(1)

We select the first element and compare it with all the other elements, if any of the
following elements is smaller than the selected element then we swap them. This
goes on till all the elements are sorted. It works on small-size arrays and vectors if
there is a memory constraint.

int main() {
for(int i=0; i<n-1; i++) {
int minIndex = i;

for(int j=i+1; j<n; j++) {


if(arr[j] < arr[minIndex]) {
minIndex = j;
}
}
swap(arr[minIndex], arr[i]);
}
}

Bubble Sort-
Time Complexity- O(n2), O(n) if the array is sorted
Space Complexity- O(1)

We start at the first element and compare the first two elements, if the first element is
greater than the second element, we swap them. Contnue the process, by the end
the greatest element should be on the right end. Repeat all the steps but exclude the
last element in the next iteration. Keep repeating till the list is sorted.

void bubbleSort(vector<int> & arr, int n) {


for(int i=0; i<n; i++) {
bool swapped = false;

for(int j=0; j<n-i; j++) {


if(arr[j] > arr[j+1]) {
swap(arr[j], arr[j+1]);
swapped = true;
}
}
if(swapped == false) {
break;
}
}
}

Insertion Sort-
Time Complexity- O(n2), O(n) in the best case
Space Complexity- O(1)

We start with the first element and then compare every next element with the first
element in the new array to decide whether the element should be placed on the
right or left side.

void insertion_sort(int arr[], int n) {


for(int i=0; i<=n-1; i++) {
int j = i;
while(j>0 && arr[j-1] > arr[j]) {
int temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;

j--;
}
}
}

(Q21) Reverse an Array.

void reverseArray(vector<int> &arr, int m) {


int s = 0;
int e = v.size()-1;

while(s<=e) {
swap(v[s], v[e]);
s++;
e--;
}
return v;
}

(Q22) Merge 2 Sorted Arrays.

void merge(int arr1[], int n, int arr2[], int m, int arr3[]) {


int i=0, j=0, k=0;

while(i<n && j<m) {


if(arr1[i] < arr2[j]) {
arr3[k++] = arr1[i++];
}
else {
arr3[k++] = arr2[j++];
}
}

while(i<n) {
arr3[k++] = arr1[i++];
}

while(j<m) {
arr2[k++] = arr2[j++];
}
}

void print(int ans[], int n) {


for(int i=0; i<n; i++) {
cout << ans[i] << " ";
}
cout << endl;
}
int main() {
int arr1[5] = {1, 3, 5, 7, 9};
int arr2[3] = {2, 4, 6};
int arr3[8] = {0};

merge(arr1, 5, arr2, 3, arr3);


print(arr3, 8);
}

(Q23) Merge Sorted Array, No Extra Space.

class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int
n) {
for(int i=0; i<n; i++){
nums1[m+i] = nums2[i];
}
sort(nums1.begin(), nums1.end());
}
};

(Q24) Move Zeroes to the right.

class Solution{
public:
void moveZeroes(vector<int>& nums) {
int i=0;

for(int j=0; j<nums.size(); j++) {


if(nums[j] != 0) {
swap(nums[j], nums[i]);
i++;
}
}
}
};

(Q25) Rotate Array by K Steps.

class Solution{
public:
void rotate(vector<int>& nums, int k) {
vector<int> temp(nums.size());
for(int i=0; i<nums.size(); i++) {
temp[(i+k)%nums.size()] = nums[i];
}
nums = temp;
}
};

(Q26) Check if Sorted and Rotated.

class Solution{
public:
bool check(vector<int>& nums) {
int count = 0;
int n = nums.size();

for(int i=1; i<n; i++){


if(nums[i-1] > nums[i]) {
count++;
}
}

if(nums[n-1] > nums[0]) {


count++;
}

return count<=1;
}
}

Character Array- Last is null \0 character

int getLength(char name[]) {


int count = 0;
for(int i=0; name[i] != '\0'; i++) {
count++;
}
return count;
}

//reverse string
void reverse(char name[], int n) {
int s=0;
int e = n-1;

while(s<e) {
swap(name[s++], name[e--]);
}
}

int main() {
char name[20];
cout << "Enter Name: " << endl;
cin >> name;
}

(Q27) Check if the String is Palindrome.

char toLowerCase(char ch) {


if(ch >= 'a' && ch <= 'z') {
return ch;
}
else {
char temp = ch - 'A' + 'a';
return temp;
}
}

bool checkPalindrome(char a[], int n) {


int s = 0;
int e = n-1;

while(s<=e) {
if(toLowerCase(a[s]) != toLowerCase(a[e])) {
return 0;
}
else{
s++;
e--;
}
}
return 1;
}

(Q28) Valid Palindrome.

class Solution {
public:
bool isPalindrome(string s) {
int i = 0;
int n = s.length();
int j = n-1;

while (i<j){
if (!isalnum(s[i])){
i++;
continue;
}
if (!isalnum(s[j])){
j--;
continue;
}
if (tolower(s[i]) != tolower(s[j])) return false;
else {
i++;
j--;
}
}
return true;
}
};

(Q29) Maximum Occurring Element.

char getMaxOccCharacter(string s) {
int arr[26] = {0};

//create an array of count of characters


for(int i=0; i<s.length(); i++) {
char ch = s[i];

//add count in arr[26]


int number = 0;
number = ch - 'a';
arr[number]++;
}

//find the maximum occurring character


int maxi = -1, ans = 0;
for(int i=0; i<26; i++) {
if(maxi < arr[i]) {
ans = i;
maxi = arr[i];
}
}

char finalAns = 'a' + ans;


return finalAns;
}

Basic String InBuilt Functions-


//length of string
int len = str.len(name);

//compare: equal = 0, not equal != 0


strcmp(s1, s2);

//copy
strcpy(dest, src);

(Q30) Replace spaces with @.

string replaceSpaces(string &str) {


string temp = " ";

for(int i=0; i<str.length(); i++) {


if(str[i] == ' ') {
temp.push_back('@');
}
else{
temp.push_back(s[i]);
}
}
}

(Q31) Remove All Occurrences of a SubString.

class Solution {
public:
string removeOccurance(string s, string part) {
while(s.length()!=0 && s.find(part) < s.length()) {
s.erase(s.find(part), part.length());
}
return s;
}
}

(Q32) Permutation in a String, check if s1 is in s2 (any order).

class Solution {
private:
bool checkEqual(int a[26], int b[26]) {
for(int i=0; i<26; i++) {
if(a[i] != b[i]) {
return 0;
}
return 1;
}
}

public:
bool checkInclusion(string s1, string s2) {

//character count array


int count1[26] = {0};

for(int i=0; i<s.length(); i++) {


int index = s1[i] - 'a';
count1[index]++;
}

//traverse s2 string in the window of size of s1 length


int i=0;
int windowSize = s1.length();
int count2[26] = {0};

//running for the first window


while(i<windowSize && i<s2.length()) {
int index = s2[i] - 'a';
count2[index]++;
i++;
}

if(checkEqual(count1, count2)) {
return 1;
}

//Aage window process karo


while(i<s2.length()) {
char newChar = s2[i];
int index = newChar - 'a';
count2[index]++;

char oldChar = s2[i-windowSize];


index = oldChar - 'a';
count2[index]--;

i++;

if(checkEqual(count1, count2)) {
return 1;
}
}
return 0;
}
}

(Q33) Remove Adjacent Duplicates.

class Solution {
public:
string removeDuplicates(string s) {
string ans;
ans.push_back(s[0]);

for(int i=1; i<s.length(); i++){

if(!ans.empty() && s[i] == ans.back()) {


ans.pop_back();
}

else{
ans.push_back(s[i]);
}

}
return ans;
}
};

(Q34) Store String Characters in the form of {a, 2, b, 4} et cetera.

class Solution {
public:
int compress(vector<char>& chars) {
int i=0;
int ansIndex = 0;
int n = chars.size();

while(i<n) {
int j = i+1;
while(j<n && chars[i] == chars[j]) {
j++;
}

//ya toh vector poora traverse ho gya


//ya phir new character encounter kia hai

//store oldchar
chars[ansIndex++] = chars[i];
int count = j-i;

if(count>1) {
string cnt = to_string(count);
for(char ch: cnt) {
chars[ansIndex++] = ch;
}
}
//moving to a new character
i=j;
}
return ansIndex;
}
}

Sieve of Erastosthenes-

class Solution {
public:
int countPrimes(int n) {

int cnt = 0;
vector<bool> prime(n+1, true);

prime[0] = prime[1] = false;

for(int i=2; i<n; i++) {


if(prime[i]) {
cnt++;

for (int j=2*i; j<n; j=j+i) {


prime[j] = 0;
}
}
}
return cnt;

}
};

2D Arrays-

//creating 2d array - row, col


int arr[3][4];
//input - hard code
int arr[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

//input - row wise


for(int i=0; i<3; i++) {
for(int j=0; j<4; j++) {
cin >> arr[i][j];
}
}

//input - col wise


for(int i=0; i<4; i++) {
for(int j=0; j<3; j++) {
cin >> arr[i][j];
}
}

//output
for(int i=0; i<3; i++) {
for(int j=0; j<4; j++) {
cout << arr[i][j];
}
cout << endl;
}

//searching in 2d array
bool isPresent(int arr[][4], int target, int row, int col) {
for(int i=0; i<3; i++) {
for(int j=0; j<4; j++) {
if(arr[i][j] == target) {
return 1;
}
}
}
return 0;
}

int target;
cin >> target;

if(isPresent(arr, target, 3, 4)) {


cout << "Element Found" << endl;
}
else{
cout << "Not Found" << endl;
}
(Q35) Row Wise Sum in a 2D Array.

//row - 3, column - 4
void printSum(int arr[][4], int row, int col) {
for(int row=0; row<3; row++) {
int sum = 0;
for(int col=0; col<4; col++) {
sum += arr[row][col];
}
cout << sum << " ";
}
}

(Q36) Tell the row with the largest sum.

int largestRowSum(int arr[][3], int row, int col) {


int maxi = INT_MIN;
int rowIndex = -1;

for(int i=0; i<3; i++) {


sum = 0;
for(int j=0; j<3; j++) {
sum += arr[row][col];
}
if (sum > maxi) {
maxi = sum;
rowIndex = row;
}
}
cout << "Max Sum: " << maxi << endl;
return rowIndex;
}

int ansIndex = largestRowSum(arr, 3, 3);


cout << "Max Row Sum: " << ansIndex << endl;

(Q37) Print in Wave Order.

vector<int> wavePrint(vector<vector<int>> arr, int nRows, int


mCols){

vector<int> ans;

for(int col=0; col<mCols; col++){


if(col&1) {
//odd index - Bottom to top
for(int row = nRows-1; row>=0; row--) {
ans.push_back[arr[row][col]];
}
}
else{
//0 or even index - Top to bottom
for(int row = 0; row<nRows; row++) {
ans.push_back[arr[row][col]];
}
}
}

(Q38) Spiral Print.

vector<int> spiralMatrix(vector<vector<int>> &mat) {


int n = mat.size();
int m = mat[0].size();

int left = 0, right = m-1;


int top = 0; bottom = n-1;
vector<int> ans;

while(top <= bottom && left <= right) {


for(int i = left; i<=right; i++) {
ans.push_back(mat[top][i]);
}
top++;

for(int i = top; i<=bottom; i++) {


ans.push_back(mat[i][right]);
}
right--;

if(top <= bottom) {


for(int i = right; i>=left; i--) {
ans.push_back(mat[bottom][i]);
}
bottom--;
}

if(left <= right) {


for(int i = bottom; i>=top; i++) {
ans.push_back(mat[i][left]);
}
left++;
}
}
}

Binary Search in 2D Array-

bool searchMatrix(vector<vector<int>> & matrix, int target) {


int row = matrix.size();
int col = matrix[0].size();

int start = 0;
int end = row*col - 1;

int mid = start + (end-start)/2;

while(start<=end) {
int element = matrix[mid/col][mid%col];

if(element == target) {
return 1;
}

if(element < target) {


start = mid+1;
}

else{
end = mid-1;
}
mid = start + (end-start)/2;
}
return 0;
}

(Q40) Search in a 2D Matrix II- Integers are sorted top to bottom and left to
right

Reference- https://leetcode.com/problems/search-a-2d-matrix-ii/
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int row = 0;
int col = matrix[0].size() - 1;

while(row < matrix.size() && col >= 0)


{
if(matrix[row][col] == target)
return true;
if(matrix[row][col] < target)
++row;

else
--col;

}
return false;

}
};

Symbol Table- Data structure created and maintained by the compiler in order to
keep track of the semantics of variables, it stores information about the scope and
binding information.

Pointers-

int num = 5;
Here the value of “5” has an address, for example, “120”. The integer “num” is
associated with this address.

In the case of cout << num; the address (120) is assessed, the value (5) is obtained
and then it is printed.

int main() {
int num = 5;

cout << num << endl;

//address of operator - &


cout << "Address of Num: " << &num << endl;

//pointer stores the address, *p stores the value


int *p = &num;

//adding 1 to the value of num


num = num + 1;
(*p)++;
return 0;
}

int main() {
int num = 5;
int *ptr = &num;

cout << "Value: " << *ptr << endl;


cout << "Address: " << ptr << endl;

cout << "Size of Integer: " << sizeof(num); //4


cout << "Pointer: " << sizeof(ptr); //8 (every case)

int *p; //pointer with garbage value - Bad practice


}

int main() {
int i = 5;

//method 1
int *p = 0;
p = &i;

//method 2
int *q = &i;
}

#include <iostream>
using namespace std;

int main() {
int num = 5;

int a = num;
cout << "Before: " << num << endl; //5
a++;
cout << "After: " << num << endl; //5

int *p = &num;
cout << "Before: " << num << endl; //5
(*p)++;
cout << "After: " << num << endl; //6

//copying a pointer to another pointer


int *q = p;
cout << p << " - " << q << endl; //same output
cout << *p << " - " << *q << endl; //same output

//important concept
int i = 3;
int *t = &i;

cout << "Before: " << *t << endl; //3


*t = *t + 1;
cout << "After: " << *t << endl; //4
cout << "Before: " << t << endl; //100 (example)
t = t + 1;
cout << "After: " << t << endl; //104 (example)

return 0;
}

NOTE: arr[i] == i[arr] and *(arr + i) == *(i + arr)

Pointers in Arrays-

int main() {

int arr[10];

cout << "Address of 1st Block: " << arr << endl;
cout << arr[0] << endl;
cout << "Address of 1st Block: " << &arr[0] << endl;

cout << "Value of 1st Block: " << *arr


cout << "Value of 1st Block + 1: " << *arr + 1
cout << "Value of 2nd Block: " << *(arr + 1)

return 0;

int main() {
int a[20] = {1, 2, 3, 5};
cout << &a[0] << endl; //same
cout << &a << endl; //output
cout << a << endl; //hoga
}

int main2() {
int *p = &a[0];
cout << p << endl; //same
cout << *p << endl; //value at a[0]
cout << &p << endl; //address of p not a
}

int main() {
//arr = arr + 1 (error)

int *ptr = &arr[0];


cout << ptr << endl;
ptr = ptr + 1; //address- 710 -> 714
cout << ptr << endl;
}

Pointers in Character-

int main() {

int arr[5] = {1, 2, 3, 4, 5};


char ch[5] = "abcde";

cout << arr << endl; //address printed


cout << ch << endl; //value printed

//different for integer and character array


char *c = &ch[0];
cout << c << endl; //prints entire value

char temp = 'z';


char *p = &temp;
cout << p << endl; //z7281yeudj - till null ch

return 0;
}

Functions in Pointers-

void print(int *p) {


cout << *p << endl;
}

void update(int *p) {


p = p + 1;
cout << "Inside: " << p << endl; //updated

*p = *p + 1 //value will update


}

int getSum(int arr[], int n) {


cout << sizeof(arr) << endl; //8, pointer pass

int sum = 0;
for(int i=0; i<n; i++) {
sum += i[arr];
}
return sum;
}

int main() {
int value = 5;
int *p = &value;

print(p);

cout << "Before: " << p << endl; //same, 5


update(p);
cout << "After: " << p << endl; //same, 5

int arr[5] = {1, 2, 3, 4, 5};


cout << "Sum: " << getSum(arr, 5) << endl;

return 0;
}

Double Pointers-

#include <iostream>
using namespace std;

int main() {
int i = 5;
int *p = &i;
int **p2 = &p;

cout << "Printing p: " << p << endl; //same


cout << *p2 << endl; //same

cout << i << endl; //5


cout << *p << endl; //5
cout << **p2 << endl; //5

cout << &i << endl; //same


cout << p << endl; //same
cout << *p2 << endl; //same

cout << &p << endl; //same


cout << p2 << endl; //same
}

Functions in Double Pointers-

#include <iostream>
using namespace std;
void update(int **p) {
p2 = p2 + 1; //no change

*p2 = *p2 + 1; //p value change

**p2 = **p2 + 1; //i value change


}

int main() {
int i = 5;
int *p = &i;
int **p2 = &p;

cout << "Printing p: " << p << endl; //same


cout << *p2 << endl; //same

cout << i << endl; //5


cout << *p << endl; //5
cout << **p2 << endl; //5

cout << &i << endl; //same


cout << p << endl; //same
cout << *p2 << endl; //same

cout << &p << endl; //same


cout << p2 << endl; //same
}

Reference Variable- Same memory, different names, pass by reference

int main() {
int i = 5;
int &j = i;

i++; //becomes 6
j++; //also becomes 6
}

Pass by Value VS Pass by Reference- Never return using reference variable and
pointer

void update1(int n) { //Pass by Value - copy banege


n++;
}

void update2(int &n) { //Pass by Reference - memory same, name


alag
n++;
}

int main() {
int n = 5;

cout << "Before: " << n << endl; //5


update1(n);
cout << "After: " << n << endl; //5

cout << "Before: " << n << endl; //5


update2(n);
cout << "After: " << n << endl; //6
}

Bad Practice- Never take array size during runtime, you should input the size during
compilation as the memory is stored in the stack which requires the memory
beforehand.

Stack Memory (Static Allocation)- All the fixed memory, for example, int i = 5; int
arr[50]; char ch. Memory cleans itself.

Heap Memory (Dynamic Memory Allocation)- Variable Memory, memory needs to


be cleaned manually.

int main() {
new char;
char *ch = new char; //8 bytes + 1 bytes = 9 bytes

new int;
int *i = new int; //8 bytes + 4 bytes = 12 bytes
//stack //heap
}

Array in Heap Memory-

int getSum(int *arr) {


int sum = 0;
for(int i=0; i<n; i++) {
sum += arr[i];
}
return sum;
}

int main() {
int n;
cin >> n;

//variable size ka array


int *arr = new int[n];

//taking input in the array


for(int i=0; i<n; i++) {
cin >> arr[i];
}

int ans = getSum(arr, n);


cout << "Sum: " << ans << endl;

delete []arr;

return 0;
}

2D Dynamic Array-

int main() {
//bad practice - wrong
int m, n;
cin >> m >> n;
int arr[m][n];
}

//arr[n][n]
int main() {
int n;
cin >> n;

//creating a 2d array
int **arr = new int *[n];
for(int i=0; i<n; i++) {
arr[i] = new int[n];
}

//taking input
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
cin >> arr[i][j];
}
}

//taking output
cout << endl;
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
}

//arr[n][m]
int main() {
int row;
cin >> row;

int col;
cin >> col;

//creating a 2d array
int **arr = new int *[row];
for(int i=0; i<row; i++) {
arr[i] = new int[col];
}

//taking input
for(int i=0; i<row; i++) {
for(int j=0; j<col; j++) {
cin >> arr[i][j];
}
}

//taking output
cout << endl;
for(int i=0; i<row; i++) {
for(int j=0; j<col; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}

//releasing memory
for(int i=0; i<row; i++) {
delete [] arr[i];
}

delete [] arr;
}

Macros-
#include <iostream>
using namespace std;

#define PI 3.14 //PI is a macro here

int main() {
int r = 5;
double area = PI * r * r;
cout << "Area: " << area << endl;

return 0;
}

Global Variable- We can share values from one function to another using reference
variable, the global variable is a second method, which you should never use.

int score = 15 //global variable - never use this

void a(int &i) {


cout << score << endl;
}

void b(int &i) {


cout << score << endl;
}

int main() {
cout << score << endl;
}

Tertiary Operator- Short form of conditional statement (in a particular case).

int main() {

int a = 1; b = 2; ans = 0;

//long way
if(a>b) {
ans = a;
}
else{
ans = b;
}

//tertiary operator way


ans = (a>b) ? a : b;
return 0;
}

Inline Function- If the function is of 1 line then it will become a Inline Function, in
case of up to 3 lines, it might become an inline function. In case of more than 3 lines,
no chance.

inline int getMax(int &a, int &b) {


ans = (a>b) ? a : b;
}

int main() {
int a = 1; b = 2; ans = 0;
ans = getMax(a, b); //bts: ans = (a>b) ? a : b;

a = a + 1;
b = b + 1;

ans = getMax(a, b); //bts: ans = (a>b) ? a : b;


return 0;
}

Default Arguments-

//"start" is the default argument


//Start from rightmost variable, int n = 0 with start = 0 is wrong

void print(int arr[], int n, int start = 0) {


for(int i = start; i<n; i++) {
cout << arr[i] << endl;
}
}

int main() {
int arr[5] = {1, 4, 7, 8, 9};
int size = 5;

print(arr, size);
}

Recursion- When a function calls itself. When the solution of a bigger problem
depends on the solution of a smaller problem, then it can be solved using recursion.

//Factorial
int factorial(int n) {
if(n==0) {
return 1;
}
return n * factorial(n-1);
}

int main() {
int n;
cin >> n;

int ans = factorial(n);


cout << ans << endl;

return 0;
}

Tail Recursion- Recursive relation at the bottom, below the processing part.
Head Recursion- Recursive relation in the centre, above the processing part.

//Power of 2
#include <iostream>
using namespace std;

int twoPower(int n) {
if(n==0) {
return 1;
}

return 2 * twoPower(n-1);
}

int main() {
int n;
n = 8;

int ans = twoPower(n);


cout << ans << endl;

return 0;
}

//Print number, n = 8 then, 8 7 6 5 4 3 2 1


#include <iostream>
using namespace std;

void print(int n) {
//base case
if(n==0) {
return;
}

cout << n << endl;

//recursive call
print(n-1);
}

int main() {
int n;
n = 8;

print(n);

return 0;
}

(Q41) Fibonacci Series

class Solution{
public:
int fib(int n) {
if(n<=1) return n;
return fib(n-1)+fib(n-2);
}
};

(Q42) Ways to Reach Nth Stairs by stepping 1 or 2 stairs at a time.

//Use DP in this case, this is just an example of recursion


int countStairs(long long nStairs) {
//base case
if(nStairs < 0)
return 0;

if(nStairs == 0)
return 1;

//recursive call
int ans = countStairs(n-1) + countStairs(n-2);

return ans;
}
(Q42) Say Digits, 412- Four One Two.

void sayDigit(int n, string arr[]) {


//base case
if(n==0)
return;

//processing
int digit = n%10;
n = n/10;

//recursive call
sayDigit(n, arr);
cout << arr[digit] << " ";
}

int main() {
string arr[10] = {"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"};

int n;
cin >> n;

cout << endl << endl << endl;


sayDigit(n, arr);
cout << endl << endl << endl;
}

(Q43) Check if an Array is Sorted.

#include<iostream>
using namespace std;

bool isSorted(int arr[], int size) {


//base case
if(size==0 || size==1) {
return true;
}

if(arr[0] > arr[1]) {


return false;
}
else{
bool ans_final = isSorted(arr+1, size-1);
return ans_final;
}
}
int main() {
int arr[5] = {2, 4, 6, 8, 9};
int size = 5;

bool ans = isSorted(arr, size);


if(ans){
cout << "Sorted" << endl;
}
}

(Q44) Find Sum of all elements in an Array.

#include<iostream>
using namespace std;

int findSum(int *arr, int size) {


//base case
if(size == 0) {
return 0;
}
if(size == 1) {
return arr[0];
}
else{
int sum = arr[0] + findSum(arr+1, size-1);
return sum;
}
}

int main() {
int arr[3] = {2, 4, 6};
int size = 3;

int ans = findSum(arr, size);


cout << "Sum: " << ans << endl;

return 0;
}

Linear Search Using Recursion-

#include<iostream>
using namespace std;

bool linearSearch(int arr[], int size, int k) {


if(size == 0){
return false;
}

if(arr[0] == k) {
return true;
}

else{
bool remainingPart = linearSearch(arr+1, size-1, k);
return remainingPart;
}
}

int main() {
int arr[5] = {3, 5, 1, 2, 6};
int size = 5;
int key = 2;

bool ans = linearSearch(arr, size, key);

if(ans) {
cout << "Present" << endl;
}
else{
cout << "Absent" << endl;
}
}

Binary Search Using Recursion-

bool binarySearch(int *arr, int s, int e, int k) {


//base case
if(s>e) {
return false;
}

int mid = s + (e-s)/2;

if(arr[mid] == k) {
return true;
}
if(arr[mid] < k) {
return binarySearch(arr, mid+1, e, k);
}
else{
return binarySearch(arr, s, mid-1, k);
}
}
int main() {
int arr[6] = {2, 4, 6, 10, 14, 18};
int size = 6;
int key = 18;

cout << binarySearch(arr, 0, 5, key);

return 0;
}

(Q45) Reverse string using recursion.

#include <iostream>
using namespace std;

void reverse(string &str, int i, int j) {


//base case
if(i>j) {
return;
}
swap(str[i], str[j]);
i++;
j--;

//recursive call
reverse(str, i, j);
}

int main() {
string name = "akshat pandey";

reverse(name, 0, name.length()-1);
cout << name << endl;

return 0;
}

(Q46) Check Palindrome using recursion.

#include <iostream>
using namespace std;

bool checkPalindrome(string str, int i, int j) {


//base case
if(i>j) {
return true;
}
if(str[i] != str[j]) {
return false;
}
else{
//recursive call
return checkPalindrome(str, i+1, j-1);
}
}

int main() {
string name = "abcba";

bool isPalindrome = checkPalindrome(name, 0, name.length()-1);

if(isPalindrome) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}

return 0;
}

(Q47) Find Power using Recursion.

#include <iostream>
using namespace std;

int power(int a, int b) {


//base case
if(b == 0) {
return 1;
}
if(b == 1) {
return a;
}

//recursive call
int ans = power(a, b/2);

//if b is even
if(b%2 == 0) {
return ans * ans;
}
else{
//if b is odd
return a * ans * ans;
}
}

int main() {
int a = 2;
int b = 3;

int ans = power(a, b);

cout << "Answer: " << ans << endl;

return 0;
}

(Q48) Do Bubble Sort using Recursion.

//Bubble sort
void sortArray(int *arr, int n) {
//base case
if(n == 0 || n == 1) {
return;
}

//1 case solve kardia - largest element ko end me rakh diya


for(int i=0; i<n-1; i++) {
if(arr[i] > arr[i+1]) {
swap(arr[i], arr[i+1]);
}
}
sortArray(arr, n-1);
}

int main() {
int arr[5] = {2, 5, 1, 6, 9};
sortArray(arr, 5);

for(int i=0; i<5; i++) {


cout << arr[i] << " ";
}

return 0;
}
Merge Sort- Fastest Sorting Algorithm

Space Complexity: O(n)


Time Complexity: O(nlogn)

#include <iostream>
using namespace std;

void merge(int *arr, int s, int mid, int e) {


int len1 = mid - s + 1;
int len2 = e - mid;

int *first = new int[len1];


int *second = new int[len2];

//copy values
int k = s;
for (int i = 0; i < len1; i++) {
first[i] = arr[k++];
}

k = mid + 1;
for (int i = 0; i < len2; i++) {
second[i] = arr[k++];
}

//merge 2 sorted arrays


int index1 = 0;
int index2 = 0;
k = s;

while (index1 < len1 && index2 < len2) {


if (first[index1] < second[index2]) {
arr[k++] = first[index1++];
} else {
arr[k++] = second[index2++];
}
}

while (index1 < len1) {


arr[k++] = first[index1++];
}

while (index2 < len2) {


arr[k++] = second[index2++];
}
}

void mergeSort(int *arr, int s, int e) {


if (s >= e) {
return;
}

int mid = (s + e) / 2;

//sort left part


mergeSort(arr, s, mid);

//sort right part


mergeSort(arr, mid + 1, e);

//merge
merge(arr, s, mid, e);
}

int main() {
int arr[5] = {2, 5, 1, 6, 9};
int n = 5;

mergeSort(arr, 0, n - 1);

for (int i = 0; i < n; i++) {


cout << arr[i] << " ";
}
cout << endl;

return 0;
}

Easy Merge Sort-

void merge(int arr[], int l, int mid, int r) {


int n1 = mid-l+1;
int n2 = r-mid;

int a[n1];
int b[n2];

for(int i=0; i<n1; i++) {


a[i] = arr[l+i];
}

for(int i=0; i<n2; i++) {


b[i] = arr[mid+1+i];
}
//phir merge karde
}

void mergeSort(int arr[], int l, int r) {


if(l<r) {
int mid = (l+r)/2;
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);

merge(arr, l, mid, r);


}
}

Quick Sort-

Space Complexity: O(n)


Time Complexity: O(n logn), worst case is O(n2)

#include<iostream>
using namespace std;

int partition(int *arr, int s, int e) {

int pivot = arr[s];

int cnt = 0;
for(int i = s+1; i<=e; i++) {
if(arr[i] <= pivot) {
cnt++;
}
}

//place pivot at right position


int pivotIndex = s + cnt;
swap(arr[pivotIndex], arr[s]);

//left and right wala part


int i = s, j = e;

while(i < pivotIndex && j > pivotIndex) {


while(arr[i] <= pivot) {
i++;
}
while(arr[j] > pivot) {
j--;
}
if(i < pivotIndex && j > pivotIndex) {
swap(arr[i++], arr[j--]);
}
}
return pivotIndex;

void quickSort(int *arr, int s, int e) {

//base case
if(s >= e) {
return;
}

//partition karenge
int p = partition(arr, s, e);

//left part sort karo


quickSort(arr, s, p-1);

//right part sort karo


quickSort(arr, p+1, e);

int main() {
int arr[5] = {2, 4, 1, 6, 9};
int n = 5;

quickSort(arr, 0, n-1);

for(int i=0; i<n; i++) {


cout << arr[i] << " ";
} cout << endl;

return 0;
}

(Q49) Find all Subsets.

class Solution {

private:
void solve(vector<int> nums, vector<int> output, int index,
vector<vector<int>> &ans) {
//base case
if(index >= nums.size()) {
ans.push_back(output);
return;
}

//exclude
solve(nums, output, index+1, ans);

//include
int element = nums[index];
output.push_back(element);
solve(nums, output, index+1, ans);
}

public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ans;
vector<int> output;
int index = 0;
solve(nums, output, index, ans);
return ans;
}
};

(Q50) Phone Keypad Problem.

class Solution{
private:
void solve(string digit, string output, int index,
vector<string> &ans, string mapping[]) {
//base case
if(index >= digit.length()) {
ans.push_back(output);
return;
}

int number = digit[index] - '0';


string value = mapping[index];

for(int i=0; i<value.length(); i++) {


output.push_back(value[i]);
solve(digit, output, index+1, ans, mapping);
output.pop_back();
}
}

public:
vector<string> letterCombination(string digits) {
vector<string> ans;

if(digits.length() == 0) {
return ans;
}

string output = "";


int index = 0;

string mapping[10] = {};

solve(digits, output, index, ans, mapping);


return ans;
}
}

(Q51) Permutation in a string.

class Solution {
private:
void solve(vector<int> nums, vector<vector<int>> &ans, int
index){
//base case
if(index >= nums.size()) {
ans.push_back(nums);
return;
}

for(int j = index; j<nums.size(); j++) {


swap(nums[index], nums[j]);
solve(nums, ans, index+1);
//backtrack
swap(nums[index], nums[j]);
}
}

public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> ans;
int index = 0;
solve(nums, ans, index);
return ans;
}
};

(Q52) Rat in a Maze Problem.


class Solution {
private:
bool isSafe(int x, int y, int n, vector<vector<int>> visited,
vector<vector<int>> &m) {

if ((x>=0 && x=n) && (y==0 && y<n) && visited[x][y] == 0


&& m[x][y] == 1) {
return true;
}
else{
false;
}

void solve(vector<vector<int>> &m, int n, vector<string> &ans,


int x, int y, vector<vector<int>> visited, string path) {

//you have reached x,y inside this function

//base case
if(x == n-1 && y == n-1) {
ans.push_back(path);
return;
}

visited[x][y] = 1;

//4 choices - D, L, R, U

//down
int newx = x+1;
int newy = y;
if(isSafe(newx, newy, n, visited, m)) {
path.push_back('D');
solve(m, n, ans, newx, newy, visited, path);
path.pop_back();
}

//left
newx = x;
newy = y-1;
if(isSafe(newx, newy, n, visited, m)) {
path.push_back('L');
solve(m, n, ans, newx, newy, visited, path);
path.pop_back();
}

//right
int newx = x;
int newy = y+1;
if(isSafe(newx, newy, n, visited, m)) {
path.push_back('R');
solve(m, n, ans, newx, newy, visited, path);
path.pop_back();
}

//up
int newx = x-1;
int newy = y;
if(isSafe(newx, newy, n, visited, m)) {
path.push_back('U');
solve(m, n, ans, newx, newy, visited, path);
path.pop_back();
}

visited[x][y] = 0;

public:
vector<string> findPath(vector<vector<int>> &m, int n) {
vector <string> ans;

if(m[0][0] == 0) {
return ans;
}

int srcx = 0;
int srcy = 0;

vector<vector<int>> visited = m;
//initialising "visited" with 0
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
visited[i][j] = 0;
}
}

string path = "";


solve(m, n, ans, srcx, srcy, visited, path);
sort(ans.begin(), ans.end());
return ans;
}
}

Class- User Defined data types

#include <iostream>
#include "Hero.cpp"
using namespace std;

class Hero {
//properties
int health;
};

int main() {

//creation of an object
Hero h1;
cout << "Size: " << sizeof(h1) << endl; //empty 1

return 0;
}

Access Modifiers-

class Hero {
public: //accessible everywhere
int health;

private: //accessible only in class


char level;
}

Getter and Setter-

class Hero {
//properties
private:
int health;

public:
char level;

int getHealth() {
return health;
}

char getLevel() {
return level;
}

void setHealth(int h) {
health = h;
}

void setLevel(char ch) {


level = ch;
}
}

int main() {
//creation of object
Hero ramesh;
cout << "Health: " << ramesh.getHealth() << endl; //1

//use setter
ramesh.setHealth(70); //private
ramesh.level = 'A'; //public

cout << "Health: " << ramesh.getHealth() << endl; //70


cout << "Level: " << ramesh.level() << endl; //A

return 0;
}

Padding- It is the insertion of empty bytes of memory between data members in a


structure or class. This is done to align the data members on specific memory
boundaries, typically the size of the data type or the smallest common multiple of the
data types. It generally has a 4-byte boundary.

Greedy Alignment- It is a technique for ordering the data members of a structure or


class in decreasing order of size. This ensures that the largest data members are
placed first in the class, minimising the amount of padding required to align the
subsequent data members.

Static VS Dynamic-

int main() {

//static allocation
Hero a;

a.setHealth(80);
a.setLevel('B');

cout << "Level: " << a.level << endl;


cout << "Health: " << a.getHealth() << endl;

//dynamically
Hero *b = new Hero;

b->setLevel('A');
b->setHealth(70);

cout << "Level: " << (*b).level << endl;


cout << "Health: " << (*b).getHealth() << endl;

cout << "Level: " << b->level << endl;


cout << "Health: " << b->getHealth() << endl;

Constructor- When we make an object, for example, “Hero ramesh;”, then behind
the scenes, the code is executing “ramesh.Hero();” function. This is done by default.

class Hero {
Hero() {
cout << "Construction Called" << endl;
}
};

int main() {
//object created statically
cout << "Hi!" << endl;
Hero ramesh;
cout << "Hello!" << endl;

//dynamically
Hero *h = new Hero; //Hero()
}

Parameter Constructor-

class Hero {
Hero() { //dead, due to parameter constructor
cout << "Constructor Called" << endl;
}

Hero(int health) {
this -> health = health;
}

Hero(int health, char level) {


this -> level = level;
this -> health = health;
}
};

int main() {

Hero ramesh(10); //"this" is ramesh, called object


ramesh.print();
ramesh.getHealth();

//dynamically
Hero *h = new Hero(11);
h -> print();
Hero temp(22, 'B');
temp.print();

Copy Constructor- Default does shallow copy

class Hero {
//copy constructor
Hero(Hero &temp) {
this->health = temp.health;
this->level = temp.level;
}
};

int main() {

Hero suresh(70, 'C');

//copy constructor- inbuilt


Hero ritesh(suresh);
//ritesh.health = suresh.health;
//ritesh.level = suresh.level;

Shallow and Deep Copying-

class Hero {
//properties
private:
int health;

public:
char *name;
char level;

Hero() {
cout << "Simple Constructor Called" << endl;
name = new char[100];
}
void setName(char name[]) {
strcpy(this->name, name);
}

//deep copy
Hero(Hero &temp) {
char *ch = new char[strlen(temp.name) + 1];
strcpy(ch, temp.name);
this->name = ch;

cout << "Copy Construction Called" << endl;


this->health = temp.health;
this->level = temp.level;
}
};

int main() {
Hero hero1;

hero1.setHealth(12);
hero1.setLevel('D');
char name[7] = "Babbar";
hero1.setName(name);

hero1.print();

//shallow copy
Hero hero2(hero1);
hero2.print();

hero1.name[0] = 'G';
hero1.print();
}

Assignment Operator-

hero1 = hero2;

Destructure- It is used to de-allocate memory, it is made by default in a class.

class Hero {
//destructor
~Hero() {
cout << "Destructor Called" << endl;
}
};

int main() {
//static- destructor automatically called
Hero a;

//dynamic- destructor manually called


Hero *b = new Hero();
//manual call
delete b;

return 0;
}

Static Keyword- It creates a data member that belongs to the class, you don’t need
to make an object to access this.

class Hero {
private:
int health;

public:
char *name;
char level;
static int timetoComplete;
};

//:: = Scope Resolution Operator


int Hero::timetoComplete = 5;

int main() {
cout << Hero::timetoComplete << endl;
return 0;
}

Static Function- No need to make an object, they don’t have the “this->” keyword.
They can only access static members.

class Hero {
private:
int health;

public:
char *name;
char level;
static int timetoComplete;

static int random() {


return timetoComplete;
}
}

//:: = Scope Resolution Operator


int Hero::timetoComplete = 5;

int main() {
cout << Hero::random() << endl;
return 0;
}

Encapsulation- We create a class in the form of a capsule which includes data


member (properties/state) and functions (methods/behaviour).
Fully Encapsulated Class- All the data members are private. We can use them only
in the same class.

Why Encapsulation- Information hiding by putting the data member private. If we


want, we can make class read only. Code reusability gets better. Unit testing
becomes easier.

#include <iostream>
using namespace std;

class Student {
private:
string name;
int age;
int height;

public:
int getAge() {
return this->age;
}
};

int main() {
Student first;

return 0;
}

Inheritance- Parent/Super Class gives properties to Sub/Child Class.

Base Class AM Public Protected Private

Public Public Protected Private

Protected Protected Protected Private

Private NA NA NA

#include <iostream>
using namespace std;

class Human {
public:
int height;
int weight;
int age;

public:
int getAge() {
return this->age;
}
void setWeight(int w) {
this->weight = w;
}
};

class Male: public Human {


public:
string color;

void sleep() {
cout << "Sleeping" << endl;
}
};

int main() {
Male object1;
cout << object1.age << endl;
}

Types of Inheritance-
1. Single- One class inherit from one class.
class Animal {
public:
int age;
int weight;

public:
void speak() {
cout << "Speaking" << endl;
}
};

class Dog: public Animal {

};

int main() {
Dog d;
d.speak();
cout << d.age << endl;
}

2. Multi Level- One class inherit from one class and another class inherit from
the second class.
class Animal {
public:
int age;
int weight;

public:
void speak() {
cout << "Speaking" << endl;
}
};

class Dog: public Animal {

};

class GermanShepher: public Dog {

};

int main() {
GermanShepher g;
g.speak();
}

3. Multiple Inheritance- One class inherit from multiple classes.


class Animal {
public:
int age;
int weight;

public:
void bark() {
cout << "Barking" << endl;
}
};

class Human {
public:
string color:

public:
void speak() {
cout << "Speaking" << endl;
}
}

//multiple inheritance
class Hybrid: public Animal, public Human {
};

int main() {
Hybrid obj1;
obj1.speak();
obj1.bark();

return 0;
}

4. Hierarchical- One class serve as Parent class for more than 1 class.
class A {
public:
void func1() {
cout << "Inside Function 1" << endl;
}
};

class B: public A {
public:
void func2() {
cout << "Insid Function 2" << endl;
}
};

class C: public A {
public:
void func3() {
cout << "Inside Function 3" << endl;
}
};

int main() {
A object1;
object1.func1();

B object2;
object2.func1();
object2.func2();
C object3;
object3.func1();
object3.func2(); //error
object3.func3();

return 0;
}

5. Hybrid Inheritance- Combination of more than 1 type of inheritance.

Inheritance Ambiguity- If C inherits from A and B and they have two same function
names, then ambiguity solves the problem.

class A {
public:
void func1() {
cout << "Inside Function 1" << endl;
}
};

class B: public A {
public:
void func2() {
cout << "Inside Function 2" << endl;
}
};

class C: public A {
public:
void func3() {
cout << "Inside Function 3" << endl;
}
};

int main() {
A object1;
object1.func1();

B object2;
object2.func1();
object2.func2();
C object3;
object3.func1();
object3.func2(); //error
object3.func3();

return 0;
}

Polymorphism- When a single thing exist in multiple forms. It is of two types,


compile time and run time.

Compile Time (Static)-


1. Function Overloading-
class A {
public:
void sayHello() {
cout << "Hello!" << endl;
}

int sayHello(char name) {


cout << "Hello!" << endl;
return 1;
}

void sayHello(string name) {


cout << "Hello " << name << endl;
}
}

2. Operation Overloading-
class B {
void operator+ (B &obj) {
int value1 = this->a;
int value2 = obj.a;
cout << "Output: " << value2 - value1 << endl;
}
};

int main() {
B obj1, obj2;
obj1.a = 4;
obj2.a = 7;

obj1 + obj2;
}

Run Time (Dynamic)- Method Overriding

class Animal {
public:
void speak() {
cout << "Speaking" << endl;
}
};

class Dog: public Animal {


public:
void speak() {
cout << "Barking" << endl;
}
};

int main() {
Dog obj;
obj.speak(); //Barking
}

Abstraction- Implementation Hiding (showing only essential information)

Linked List- It is a linear data structure which is made by collection of nodes. A


node has data and a address of the next node. It is a dynamic data structure with no
memory wastage.

Why- It is not possible to change the size of array during run time, in case of vector
the size doubles which is not a optimal case.
#include <iostream>
using namespace std;

class Node {

public:
int data;
Node *next;

Node(int data) {
this -> data = data;
this -> next = NULL;
}

};

int main() {
Node *node1 = new Node(10);
cout << node1 -> data << endl;
cout << node1 -> next << endl;

return 0;
}

Singly Linked List-

#include <iostream>
using namespace std;

class Node {
public:
int data;
Node *next;

//constructor
Node(int data) {
this -> data = data;
this -> next = NULL;
}

//destructor
~Node() {
int value = this -> data;
//memory free
if(this -> next != NULL) {
delete next;
this -> next = NULL;
}
}

};

void InsertAtHead(Node *&head, int d) {


//new node created
Node *temp = new Node(d);
temp -> next = head;
head = temp;
}

void InsertAtTail(Node *&tail, int d) {


//new node created
Node *temp = new Node(d);
tail -> next = temp;
tail = tail -> next;
}

void InsertAtPosition(Node *&tail, Node *&head, int position, int


d) {
Node *temp = head;
int cnt = 1;

//insert at start
if(position == 1) {
insertAtHead(head, d);
return;
}

while(cnt < position-1) {


temp = temp -> next;
cnt++;
}

///insert at last
if(temp -> next == NULL) {
insertAtTail(tail, d);
return;
}

//creating a node for d


Node *nodetoInsert = new Node(d);
nodetoInsert -> next = temp -> next;
temp -> next = nodetoInsert;
}

void deleteNode(int position, Node *&head) {


//deleting first node
if(position == 1) {
Node *temp = head;
head = head -> next;
//memory free
temp -> next = NULL;
delete temp;
}
else {
//deleting any middle or last node
Node *curr = head;
Node *prev = NULL;

int cnt = 1;
while(cnt < position) {
prev = curr;
curr = curr -> next;
cnt++;
}

prev -> next = curr -> next;


curr -> next = NULL;
delete curr;
}
}

void print(Node *&head) {


Node *temp = head;

while(temp != NULL) {
cout << temp -> data << " ";
temp = temp -> next; //temp
}
cout << endl;
}

int main() {
//created a new node
Node *node1 = new Node(10);
cout << node1 -> data << endl;
cout << node1 -> next << endl;

//head pointed to node1


Node *head = node1;
Node *tail = node1;

print(head);

InsertAtTail(tail, 12);
print(head);

InsertAtPosition(tail, head, 4, 22);


print(head);

deleteNode(4, head);
print(head);

return 0;
}

Doubly Linked List- It has 3 properties, data, previous and next.

#include <iostream>
using namespace std;

class Node {
public:
int data;
Node *prev;
Node *next;
//constructor
Node(int d) {
this -> data = d;
this -> prev = NULL;
this -> next = NULL:
}
};

//finding length of linked list


int getLength(Node *head) {
int len = 0;
Node *temp = head;

while(temp != NULL) {
len++;
temp = temp -> next;
}
}

//traversing a linked list


void print(Node *head) {
Node *temp = head;

while(temp != NULL) {
cout << temp -> data;
temp = temp -> next;
}
return len;
}

void InsertAtHead(Node *&tail, Node *&head, int d) {


//empty list
if(head == NULL) {
Node *temp = new Node(d);
head = temp;
tail = temp;
}
else{
Node *temp = new Node(d);
temp -> next = head;
head -> prev = temp;
head = temp;
}
}

void InsertAtTail(Node *&tail, Node *&head, int d) {


if(head == NULL) {
Node *temp = new Node(d);
tail = temp;
head = temp;
}
else{
Node *temp = new Node(d);
tail -> next = temp;
temp -> prev = tail;
tail = temp;
}
}

void InsertAtPosition(Node *&tail, Node *&head, int position, int


d) {

//insert at start
if(position == 1) {
InsertAtHead(head, d);
return;
}

Node *temp = head;


int cnt = 1;

while(cnt < position-1) {


temp = temp -> next;
cnt++;
}

//inserting at last position


if(temp -> next == NULL) {
InsertAtTail(tail, d);
return;
}

//creating a node for d


Node *nodeToInsert = new Node(d);
nodeToInsert -> next = temp -> next;
temp -> next -> prev = nodeToInsert;
temp -> next = nodeToInsert;
nodeToInsert -> prev = temp;

void deleteNode(int position, Node *&head) {


//deleting first or last node
if(position == 1) {
Node *temp = head;
temp -> next -> prev = NULL;
head = temp -> next;
temp -> next = NULL;
delete temp;
}
else {
//deleting any middle or last node
Node *curr = head;
Node *prev = NULL;

int cnt = 1;
while(cnt < position) {
prev = curr;
curr = curr -> next;
cnt++;
}

curr -> prev = NULL;


prev -> next = curr -> next;
curr -> next = NULL;

delete curr;
}
}

int main() {

Node *node1 = new Node(10);


Node *head = node1;

print(head);
cout << getLength(head) << endl;

InsertAtHead(head, 11);
print(head);

InsertAtTail(head, 25);
print(head);

return 0;
}

Circular Linked List-

#include <iostream>
using namespace std;

class Node {
public:
int data;
Node *next;

//constructor
Node(int d) {
this -> data = d;
this -> next = NULL;
}

~Node() {
int value = this -> data;
if(this -> next != NULL) {
delete next;
next = NULL;
}
}
};

void insertNode(Node *&tail, int element, int d) {


//assuming that the element is present in the list

//empty list
if(tail == NULL) {
Node *newNode = new Node(d);
tail = newNode;
newNode -> next = newNode;
}
else{
//non-empty list
Node *curr = tail;

while(curr -> data != element) {


curr = curr -> next;
}

//element found -> curr represent element node


Node *temp = new Node(d);
temp -> next = curr -> next;
curr -> next = temp;
}
}

void print(Node *tail) {


Node *temp = tail;

//empty list
if(tail == NULL) {
cout << "List is Empty!" << endl;
return;
}

do {
cout << tail -> data << " ";
tail = tail -> next;
} while(tail != temp);
}

void deleteNode(Node *&tail, int value) {


//empty list
if(tail == NULL) {
cout << "List is Empty!" << endl;
return;
}
else{
//non-empty
//assuming value is present
Node *prev = tail;
Node *curr = prev -> next;

while(curr -> data != value) {


prev = curr;
curr = curr -> next;
}

prev -> next = curr -> next;

//1 Node Linked List


if(curr == prev) {
tail = NULL;
}

//>=2 Node Linked List


else if(tail == curr) {
tail = prev;
}

curr -> next = NULL:


delete curr;
}
}

int main() {
Node *tail = NULL;

//empty list me insert krre hai


insertNode(tail, 5, 3);
print(tail);

return 0;
}

(Q52) Reverse a Linked List.

#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node(int data) {
this -> data = data;
this -> next = NULL;
}
};

//iterative
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *curr = head;
ListNode *prev = NULL;

while(curr != NULL) {
ListNode *temp = curr -> next;
curr -> next = prev;
prev = curr;
curr = temp;
}

return prev;
}
};

//recursive
Node reverse(Node *head){
if(head == NULL || head -> next == NULL) {
return head;
}

Node newHead = reverse(head -> next);


Node headNext = head -> next;
headNext -> next = head;
head -> next = NULL;
return newHead;
}

(Q53) Find Middle of Linked List.


class Solution {
public:
ListNode *middleNode(ListNode *head) {
int n=0;
ListNode *slow = head, *fast = head;

while(fast != NULL && fast -> next != NULL) {


slow = slow -> next;
fast = fast -> next -> next;
}
return slow;
}
};

(Q54) Check if Linked List is Circular or Not.

bool isCircular(Node *head) {


//empty list
if(head == NULL) {
return head;
}

Node *temp = head -> next;


while(temp != NULL && temp != head) {
temp = temp -> next;
}

if(temp == head) {
return true;
}

return false;
}

(Q55) Reverse Lineked List is Group of K Nodes.

Node *kReverse(Node *head, int k) {


//base call
if(head == NULL) {
return NULL;
}

//Step 1: Reverse first K nodes


Node *next = NULL;
Node *curr = head;
Node *prev = NULL;

count = 0;
while(curr != NULL && count < k) {
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}

//Step 2: Recursion dekh lega aage


if(next != NULL) {
head -> next = kReverse(next, k);
}

//Step 3: Return head of the linked list


return prev;
}

(Q56) Remove Duplicate from a Sorted Linked List.

class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
//empty list
if(head == nullptr) {
return nullptr;
}

//non-empty list
ListNode *curr = head;

while(curr != NULL) {
if(curr -> next != NULL & curr -> data == curr -> next
-> data) {
ListNode *next_next = curr -> next -> next;
ListNode *nodeToDelete = curr -> next;
delete(nodeToDelete);
curr -> next = next_next;
}
else{ //not equal
curr = curr -> next;
}
}
return head;
}
};

(Q57) Detect and Remove Loop from a Linked List.

//using map<Node*, bool>


bool detectLoop(Node *head) {
if(head == NULL) {
return false;
}

map<Node *bool, bool> visited;

Node *temp = head;

while(temp != NULL) {
if(visited[temp] == true) {
return true;
}

visited[temp] = true;
temp = temp -> next;
}

return false;
}

//Floyd's Cycle Detection Algorithm


Node *floydDetectLoop(Node *head) {
if(head == NULL) {
return false;
}
Node *slow = head;
Node *fast = head;

while(slow != NULL && fast != NULL) {


fast = fast -> next;

if(fast != NULL){
fast = fast -> next;
}

slow = slow -> next;

if(slow == fast) {
return 1;
}
}
return false;
}

(Q58) Find Starting Node of the Cycle.

Node *getStartingNode(Node *head) {


if(head == NULL) {
return NULL;
}

Node *intersection = floydDetectLoop(head);


Node *slow = head;

while(slow != intersection) {
slow = slow -> next;
intersection = intersection -> next;
}

return slow;
}

(Q59) Remove Loop form Linked List.

void *removeLoop(Node *head) {


if(head == NULL) {
return;
}

Node *startOfLoop = getStartingNode(head);


Node *temp = startOfLoop;

while(temp -> next != startOfLoop) {


temp = temp -> next;
}

temp -> next = NULL;


}

(Q60) Check if Linked List is Palindrome.

//approach 1
class Solution {
private:
bool checkPalindrome(vector<int> arr) {
int n = arr.size();
int s = 0;
int e = n-1;

while(s<=e) {
if(arr[s] != arr[e]) {
return false;
}
s++;
e--;
}
return true;
}

public:
bool isPalindrome(ListNode* head) {
vector<int> arr;
ListNode *temp = head;
while(temp != NULL) {
arr.push_back(temp -> val);
temp = temp -> next;
}
return checkPalindrome(arr);
}
};

//approach 2
class Solution{
private:
Node *getMid(Node *head) {
Node *slow = head;
Node *fast = head -> next;

while(fast != NULL && fast -> next != NULL) {


fast = fast -> next -> next;
slow = slow -> next;
}
return slow;
}

Node *reverse(Node *head) {


Node *curr = head;
Node *prev = NULL;
Node *next = NULL;

while(curr != NULL) {
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
return prev;
}

public:
bool isPalindrome(Node *head) {
if(head -> next == NULL) {
return true;
}

//step 1: find middle


Node *middle = getMid(head);
//step 2: reverse list after middle
Node *temp = middle -> next;
middle -> next = reverse(temp);

//step 3: compare both halves


Node *head1 = head;
Node *head2 = middle -> next;

while(head2 != NULL) {
if(head1 -> data != head2 -> data) {
return false;
}
head1 = head1 -> next;
head2 = head2 -> next;
}

//step 4: make LL normal again (Optional)


temp = middle -> next;
middle -> next = reverse(temp);

return true;
}
};

(Q61) Sort 0, 1 and 2 in a Linked List.

//Approach 1
Node *sortList(Node *head) {
int zeroCount = 0;
int oneCount = 0;
int twoCount = 0;

Node *temp = head;


while(temp != NULL) {
if(temp -> data == 0) {
zeroCount++;
}
else if(temp -> data == 1) {
oneCount++;
}
else if(temp -> data == 2) {
twoCount++;
}
temp = temp -> next;
}

temp = head;
while(temp != NULL) {
if(zeroCount != 0) {
temp -> data = 0;
zeroCount--;
}
else if(oneCount != 0) {
temp -> data = 1;
oneCount--;
}
else if(twoCount != 0) {
temp -> data = 2;
twoCount--;
}
temp = temp -> next;
}

return head;
}

//Approach 2
void insertAtTail(Node *&tail, Node *curr) {
tail -> next = curr;
tail = curr;
}

Node *sortList(Node *head) {

Node *zeroHead = new Node(-1);


Node *zeroTail = zeroHead;
Node *oneHead = new Node(-1);
Node *oneTail = oneHead;
Node *twoHead = new Node(-1);
Node *twoTail = twoHead;

Node *curr = head;


//separate LL for 0, 1 and 2
while(curr != NULL) {
int value = curr -> data;
if(value == 0){
insertAtTail(zeroTail, curr);
}
else if(value == 1) {
insertAtTail(oneTail, curr);
}
else if(value == 2) {
insertAtTail(twoTail, curr);
}
curr = curr -> next;
}

//merge 3 sublist
if(oneHead -> next != NULL) {
zeroTail -> next = oneHead -> next;
}
else{
//1s list is empty
zeroTail -> next = twoHead -> next;
}

oneTail -> next = twoHead -> next;


twoTail -> next = NULL;

//setup head
head = zeroHead -> next;

//delete dummy nodes


delete zeroHead;
delete oneHead;
delete twoHead;

return head;

(Q62) Merge Sort in Linked List.


node *merge(node *left, node *right) {
if(left == NULL) {
return right;
}

if(right == NULL) {
return left;
}

node *ans = new node(-1);


node *temp = ans;

while(left != NULL && right != NULL) {


if(left -> data < right -> data) {
temp -> next = left;
temp = left;
left = left -> next;
}
else{
temp -> next = right;
temp = right;
right = right -> next;
}
}

while(left != NULL) {
temp -> next = left;
temp = left;
left = left -> next;
}

while(right != NULL) {
temp -> next = right;
temp = right;
right = right -> next;
}

ans = ans -> next;


return ans;
}

node *mergeSort(node *head) {


//base case
if(head == NULL || head -> next == NULL) {
return head;
}

//break linked list into 2 halves


Node *mid = findMid(head);

Node *left = head;


Node *right = mid -> next;
mid -> next = NULL;

//recursive call to sort both halves


left = mergeSort(left);
right = mergeSort(right);

//merge both left and right halves


Node *result = merge(left, right);

return result;
}

Stack- LIFO (Last in First out)

#include<iostream>
#include<stack>
using namespace std;

int main() {
//creation of stack
stack<int> s;

//basic operations
s.push(2);
s.push(3);

s.pop();

s.top();

if(s.empty()) {
cout << "Stack is Empty!" << endl;
}

else{
cout << "Stack is not Empty!" << endl;
}

s.size();

return 0;
}

Implementing Stack Class-

#include<iostream>
#include<stack>
using namespace std;

class Stack {
//properties
public:
int *arr;
int top;
int size;

//behaviour
Stack(int size) {
this -> size = size;
arr = new int(size);
top = -1;
}

void push(int element) {


if(size - top > 1) {
top++;
arr[top] = element;
}

else{
cout << "Stack OverFlow" << endl;
}
}

void pop() {
if(top >= 0) {
top--;
}
else{
cout << "Stack OverFlow" << endl;
}
}

int peek() {
if(top >= 0) {
return arr[top];
}
else{
cout << "Stack is Empty!" << endl;
return -1;
}
}

bool isEmpty() {
if(top == -1) {
return true;
}
else{
return false;
}
}
}

int main() {

(Q63) Minimum Stack

class MinStack {
public:
stack <int> st, s2;
MinStack() {

void push(int val) {


if(s2.empty() || val <= s2.top()) {
s2.push(val);
}

st.push(val);
}

void pop() {
if(st.top() == s2.top()) {
s2.pop();
}

st.pop();
}

int top() {
return st.top();
}

int getMin() {
return s2.top();
}
};

(Q64) Reverse a string using Stack.

int main() {
string str = "Akshat";

stack<char> s;

for(int i=0; i<str.length(); i++) {


char ch = str[i];
s.push(ch);
}
string ans = "";

while(!s.empty()) {
char ch = s.top();
ans.push_back(ch);

s.pop();
}

cout << "Reversed String: " << ans << endl;

return 0;
}

(Q65) Delete Middle Element of Stack.

void solve(stack<int> &inputStack, int count, int size) {


//base case
if(count == size/2) {
inputStack.pop();
return;
}

int num = inputStack.top();


inputStack.top();

//recursive call
solve(inputStack, count+1, size);

inputStack.push(num);
}

void deleteMiddle(stack<int> &inputStack, int N) {


int count = 0;
solve(inputStack, count, N);
}

(Q66) Valid Parentheis

bool isValidP(string expression) {


stack<char> s;
for(int i=0; i<expression.length(); i++) {
char ch = expression[i];

//if opening bracket, stack push


//if closing bracket, stack pop

if(ch == '(' || ch == '[' || ch == '{') {


s.push();
}

else{
//for closing bracket
if(!s.empty()) {
char top = s.top();
if(matches(top, ch)) {
s.pop();
}
else{
return false;
}
}
else{
return false;
}
}
}

if(s.empty()) {
return true;
}

else{
return false;
}
}

(Q67) Insert an Element at its Bottom in a Given Stack.

void solve(stack<int> &s, int x) {


//base case
if(s.empty()) {
s.push(x);
return;
}

int num = s.top();


s.pop();

//recursive call
solve(stack, x);

s.push(num);
}

stack<int> pushAtBottom(stack<int> &s, int x) {


solve(myStack, x);
return myStack;
}

(Q68) Reverse Stack Using Recursion.

void insertAtBottom(stack<int> &s, int element) {


//base case
if(s.empty()) {
s.push(element);
return;
}

int num = s.top();


s.pop();

//recursive call
solve(s, x);
s.push(num);
}

void reverseStack(stack<int> &stack) {


//base case
if(stack.empty()) {
return;
}
int num = stack.top();
stack.pop();

//recursive call
reverseStack(stack);

insertAtBottom(stack, num);
}

(Q69) Sort a Stack Without a Loop.

void sortedInsert(stack<int> &stack, int num) {


//base case
if(stack.empty() || (!stack.empty() && stack.top() < num)) {
stack.push(num);
return;
}

int n = stack.top();
stack.pop();

//recursive call
sortedInsert(stack, num);
stack.push(n);
}

void sortStack(stack<int> &stack) {


//base case
if(stack.empty()) {
return;
}

int num = stack.top();


stack.pop();

//recursive call
sortStack(stack);

sortedInsert(stack, num);
}
(Q70) Stack Discount Problem.

class Solution {
public:
vector<int> finalPrices(vector<int>& prices) {

stack<int> s;

for(int i=prices.size()-1; i>=0; i--)


{

while(!s.empty() && s.top() > prices[i]) {


s.pop();
}

int x = prices[i];

if(!s.empty() && s.top() <= prices[i]) {


prices[i] = prices[i] - s.top();
}

s.push(x);

return prices;
}
};

(Q71) Next Smaller Element Using Stack.

vector<int> nextSmallerElement(vector<int> &arr, int n) {

stack<int> s;
s.push(-1);
vector<int> ans;

for(int i=n-1; i>=0; i--) {


int curr = arr[i];
while(s.top() >= curr) {
s.pop();
}

//ans is stack ka top


ans[i] = s.top();
s.push(curr);
}
return ans;
}

(Q72) Largest Rectangle in Histogram.

class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
vector<int> left(n);
vector<int> right(n);
stack<pair<int, int>> st;

for (int i = n - 1; i >= 0; i--){


while (!st.empty() && st.top().first >= heights[i])
st.pop();
if (st.empty()) right[i] = n - 1;
else right[i] = st.top().second - 1;
st.push({heights[i], i});
}

st = {};

for (int i = 0; i < n; i++){


while (!st.empty() && st.top().first >=
heights[i])st.pop();
if (st.empty()) left[i] = 0;
else left[i] = st.top().second + 1;
st.push({heights[i], i});
}

int maxi = INT_MIN;


for (int i = 0; i < n; i++) maxi = max(heights[i] *
(right[i] - left[i] + 1), maxi);
return maxi;
}
};

(Q73) Stack Celebrity Problem.

bool knows(vector<vector<int>> &M, int a, int b, int n) {


if(M[a][b] == 1) {
return true;
}
else{
return false;
}
}

int celebrity(vector<vector<int>> &M, int n) {

stack<int> s;

//Step 1: Push all elements in stack


for(int i=0; i<n; i++) {
s.push(i);
}

//Step 2: Two elements nikal do, compare karo


while(s.size() > 1) {
int a = s.top();
s.pop();

int b = s.top();
s.pop();

if(knows(M, a, b, n)) {
s.push(b);
}
else{
s.push(a);
}
}

//Step 3: Akele bache candidate me potential hai


int candidate = s.top();

//row check
bool rowCheck = false;
int zeroCount = 0;
for(int i=0; i<n; i++) {
if(M[candidate][i] == 0) {
zeroCount++;
}
}

//all zeroes
if(zeroCount == n) {
rowCheck = true;
}

//column check
bool columnCheck = false;
int oneCount = 0;
for(int i=0; i<n; i++) {
if(M[i][candidate] == 1) {
oneCount++;
}
}

//all ones
if(oneCount == n-1) {
columnCheck = false;
}

//if both are true than s/he is a celebrity


}

You might also like