DSA Notepad
DSA Notepad
DSA Notepad
—------------------------------------------------------------------------------------
2. Linked list cycle: fast and slow pointers, in case of a cycle, the fast pointer meets the
slow pointer, but if there is no cycle, then the fast pointer ends its journey. Always take care of
the base condition (head == NULL).
3. Linked list cycle 2 (detect the starting point of the cycle in the linked list): use slow
and fast pointer to check whether they are meeting or not, if NO, then there is no cycle, if YES,
then take start = head and the slow pointer, do start = start -> next and slow = slow -> next,
wherever they will meet, that node will be the starting point of the cycle.
We can also use hashmap for this (but this will require O(N) space.
4. Intersection of 2 linked lists: we can use a brute force algorithm, we can also use the
hashmap (but it takes extra space complexity)
More optimized approach is using the 2 pointer method: count length1 and length2, now
do (length2 - length1), move the pointer of length2 by the distance length2 - length1, now
simultaneously , move both the pointers, wherever they meet, is the intersection of the
linked lists.
5. Deleting the kth node from the end: Take 2 pointers, progress the first one by k
distance, and then progress both the pointers simultaneously till the second pointer reaches
NULL or is pointing to NULL.
6. Reverse linked list: Iterative approach , O(n) method, take 2-3 pointers and then it will
be easy.
7. Palindrome Linked list: first find out the midpoint of the list by using slow pointers and
fast pointers -> when fast -> next == NULL OR fast -> next -> next == NULL, then stop the
interaction ,and the position of the slow pointer will be the mid point. Break the list from the
midpoint, reverse the second half of the list and check the palindrome by traversing through the
first half and the second reversed half.
8. Flatten the doubly linked list: using 3 pointers: *ptr, *runner, *temp, we can solve this
problem beautifully in O(n) time.
https://leetcode.com/explore/learn/card/linked-list/213/conclusion/1225/
https://leetcode.com/explore/learn/card/queue-stack/232/practical-application-stack/1389
10. Binary tree inorder traversal (Iterative approach): use stack to do it.
https://leetcode.com/explore/learn/card/queue-stack/232/practical-application-stack/1383/
If the character is ‘[‘, then push curr_str to the stack1 and cur_num to stack2, reinitialize
curr_str = “” and curr_num = 0;
If the character is ‘]’, then pop prev_num and prev_str, apply the formula curr_str =
prev_str + prev_num* curr_str.
https://leetcode.com/submissions/detail/696712028/ (preorder)
While (root || !s.empty()) : always start with this.
Preorder: if root is not NULL , we push root into the vector, now if root -> right is not
null, we push it into the stack and make root = root -> left.
Inorder: do root -> left until root is NULL, then take the topmost node in the stack, push
its value in the vector, then do root = s.top() -> right and s.pop() and continue the same
process.
https://leetcode.com/submissions/detail/696711265/
Postorder: do root -> left until root is NULL, now take the topmost element of the stack
and check its right, if its right is not NULL, then assign root = s.top() -> right and
continue the process. But if the s.top() -> right == NULL, then we take temp = s.top();
s.pop(), push the value of temp in the vector and now run a while loop :
https://leetcode.com/submissions/detail/696725964/
14. Symmetric Tree: we use 2 queues here, one condition to check is that if both left and
right are NULL, we do continue, if one of them is NULL, we return false, and rest toh we can do
it easily by using q1 and q2.
15. Construct the binary tree from inorder and postorder, inorder and preorder: we
can do it easily using recursion by considering 4 pointers: is, ie, ps, pe.
If (is > ie) return NULL;
}
temp -> next -> next = NULL;
head = dummy -> next;
temp -> next = dummy;
}
18. Lowest Common ancestor in a binary tree: very simple recursive solution can be
written. Call on left , call on right. If left and right , both are NULL, return NULL, if any one of
them is NULL, return the not NULL value, if both of them are not NULL, return the root.
if (prev != NULL && root -> val <= prev -> val) {
return false;
}
prev = root;
return isValidBST (root -> right);
}
We use the concept of the inorder traversal being sorted of a binary search tree. We just
check the current root’s value with the prev value.
20. Search in BST: a very simple implementation, if the value is less than the root’s value,
call on the left side, otherwise call on the right side.
21. Insert in BST: if the value to be inserted is less than the root’s value, call on the left hand
side, otherwise call on the right hand side.
23. Kth largest /smallest element in a stream: always use a priority queue, (max and min,
you can decide easily).
24. Is Balanced binary tree: we just add 2 lines of code in the famous find_height_of_tree
function. We say that if left_height || right_height is -1 , return -1, OR difference between them is
more than 1, then also return -1.
Beautifully done in O(N) time.
25. Convert sorted array into a BST: just use the concept of inorder traversal being sorted
in case of a binary search tree.
26. Find Duplicate Subtrees: if root == NULL, return an empty string, call on the left and
right side of the root.
String s = to_string(root -> val) + ‘x’ + left_string + ‘x’ + right_string;
Map[s] ++;
If (map[s] == 2) { pushback root in the vector}
return s;
27. Top K frequent elements using bucket sort: very beautifully implemented this
question:
https://leetcode.com/problems/top-k-frequent-elements/
28. Binary search : simple binary search (we have 3 templates), do remember.
30. Find the peak element using binary search: we assume nums[-1] and nums[n] =
negative infinity, and then we can easily do this question using binary search.
32. Find the min element in a rotated sorted array containing duplicates:
Similar to the previous question.
If the nums[mid] < nums[end] , means that right half is sorted, call on the left half
If the nums[mid] > nums[end], right half is unsorted, so call on the right half
If nums[mid] == nums[end], r - - ;
33. Find the first and last position of the element in a sorted array
Use 2 functions:
First to calculate the first position of the element in the array
Second to calculate the last position of the element in the array
while (!q.empty()) {
int front = q.front();
q.pop();
for (auto x: m[front]) {
if (x == k) continue;
visited[x] = 1;
if (time[front] + m2[{front, x}] < time[x]) {
time[x] = time[front] + m2[{front, x}];
q.push(x);
}
}
}
We use the two pointer technique to find the number of pairs whose difference is less
than equal to mid, if this count >= k, I call on the left hand side, otherwise I call on the
right hand side of the range.
Initial range is [0, nums[n-1] - nums[0]] provided I have sorted the array nums in
ascending order.
—---------------------------------------------------------------------------------------------------------------
DP Starts here
—---------------------------------------------------------------------------------------------------------------
39. Longest Increasing Subsequence:
3 approaches : first one is using the index and the prev index (coordinate change is also
done here). Index goes from n - 1 to 0, and previndex goes from index -1 to -1.
Dp[index][previndex] represents the length of the LIS ending at index with previndex
Next approach is the famous 1d DP approach, where dp[i] represents the length of the
LIS ending at i.
Time : O(n^2), Space: O(n)
The famous binary search approach. Do the lower bound for each element, if it is equal to
the end of the array, then push back the element, otherwise replace the element with the
found index by the lower bound function.
https://leetcode.com/submissions/detail/700501077/
41. Maximum product Subarray: curr_product and the max_product : 2 variables will be
there. As soon as we encounter a 0, we reinitialize curr_product to 1.
We do the same thing by traversing in the reverse order to take care of the odd number of
negative integers.
https://leetcode.com/problems/maximum-product-subarray/
42. Zeroes and Ones (0/1 knapsack): a good question. I used 3d dp to do this. A must revise
question. https://leetcode.com/problems/ones-and-zeroes/. Pick not pick technique
43. Coin change: Pick not pick technique and you will easily solve this question
47. House robber and House robber 2 : pick not pick technique. Space optimization can
also be done in these types of questions.
https://leetcode.com/problems/house-robber/
https://leetcode.com/submissions/detail/701297355/
48. Unique paths : without and with obstacles, famous grid questions.
51. Egg drop with 2 eggs and N floors: code is self explanatory
https://leetcode.com/problems/egg-drop-with-2-eggs-and-n-floors/
53. Subarray sum equals k: use prefix sum and a map to solve this question.
54. Coin change 2 problem: the pick not pick technique, unbounded knapsack
https://leetcode.com/problems/coin-change-2/
Just make the dp array of the longest common subsequence, and then do something on dp
to get the desired string. 1 based indexing should be done.
60. Buy and sell stock 2: dp[0][1] tells us about the maximum profit we can get by starting
from the 0th index provided we are allowed to buy it. https://leetcode.com/problems/best-time-
to-buy-and-sell-stock-ii/
63. Largest divisible subset: similar concept to that of the longest increasing subsequence,
but here, we also need to print the subset. For that we use the hash array and do the stuff as
explained by striver. https://leetcode.com/problems/largest-divisible-subset/
64. Longest string chain: similar concept as the longest increasing subsequence. Sort the
array of strings on the basis of length and then do the stuff asked in the question.
https://leetcode.com/problems/longest-string-chain/
https://leetcode.com/problems/number-of-longest-increasing-subsequence/
66. Burst balloons: Partition dp, a superb question, we have to do it the reverse order.
https://leetcode.com/submissions/detail/704005840/
69. Largest Rectangle in a histogram: solved using 4 stacks, first 2 stacks for finding the
next right smaller element, and the rest 2 stacks for finding the next left smaller element.
https://leetcode.com/problems/largest-rectangle-in-histogram/
70. Palindromic substrings: dp[0][n-1] tells whether this is a palindrome or not, if dp[0] ==
dp[n-1] then call on dp[1][n-2] and so on.
https://leetcode.com/problems/palindromic-substrings/
72. Partition a set into 2 subsets such that the absolute difference between them is
minimum: we just calculate the total_sum of the array and now we have the dp which says 0/1
for every j = 0 -> total_sum. Traversing the last row of the dp, we can calculate the desired ans.
link
74. 0/1 knapsack (values and weights, maxweight): link, base case is important.
78. Longest bitonic subsequence: similar concept as the longest increasing subsequence.
Link
81. Longest Valid Parentheses: a very good question which uses both stacks and dp
(remembering the past). https://leetcode.com/problems/longest-valid-parentheses/
—------------------------------------------------------------------------------------------------------------------
Graph Starts here
—------------------------------------------------------------------------------------------------------------------
85. Bipartite check using dfs and bfs: bipartite using bfs, bipartite using dfs
Graph is bipartite if we can color all the vertices with blue and green provided that no two
adjacent vertices have the same color.
90. Russian Doll envelopes : a nice small variation of the LIS problem.
https://leetcode.com/problems/russian-doll-envelopes/
91. Shortest path in an undirected graph (with unit weights) with a source vertex: link
We can do this using simple BFS, by taking a normal level array, initialize the array with
infinity.
92. Shortest path in a directed acyclic graph with weights: First, we find the topological sort,
store it in the stack, then we take the distance array initialized with infinity, dist[src] = 0, now we
take the topmost element of the stack and do some stuff, and get the resultant distance array
which stores the shortest distance between the src and the vertex.
Link
while (!pq.empty()) {
pair<int, int> front = pq.top();
pq.pop();
int u = front.second;
mst[u] = true;
for (auto x: adj[u]) {
int v = x[0];
int weight = x[1];
if (mst[v] == false && key[v] > weight) {
key[v] = weight;
parent[v] = u;
pq.push({key[v], v});
}
}
}
95. DSU:
Time complexity for finding the parent is almost constant. So for ‘m’ union operations, we
require O(m) time. In the above code, find parent function is written in a way such that it uses
path compression.
Link7 Link8
Link12 (revise this question, similar concept to that of the hamiltonian path, visit and unvisit
concept)
Link13
Link14 (Revise good question)
Link9
Link11
Link12 (Tarjan’s algorithm for finding the strongly connected components)
Link13 (a must revise question, visited and unvisited concept used again)
—------------------------------------------------------------------------------------------------------------------
Binary Trees and BST Starts here
—-------------------------------------------------------------------------------------------------
Basic Definitions:
Full binary tree: A binary tree in which each node has either 0/2 children.
Complete binary tree: a binary tree in which every level is completely filled except for the last
level and the nodes in the last level are filled from the left most side.
Perfect binary tree: All the leaf nodes are at the same level.
Degenerate binary tree: It is basically a skew tree. A linear tree resembling a linked list
Representation of the Binary tree:
Struct Node {
Int data;
Struct Node *left;
Struct Node *right;
}
1. Diameter of a Tree (the same height function, but with that, pass a variable maxi with
reference where maxi = max (maxi, left + right + 1)
2. Maximum path sum : Similar to the concept of the diameter of the tree.
I calculate the max path sum for each node by doing the following:
maxi = max (maxi, node -> val + left sum + right sum);
return node -> val + max(left sum , right sum);
3. same tree
4. Zig Zag traversal
5. Boundary traversal : First do the left boundary traversal, as soon as we encounter a leaf
node, stop it.
Then print all the leaf nodes using the preorder / inorder traversal…and then take the right
boundary (reverse it and then print it).
9. Right view of the BT: same concept as the bottom view, the only difference is that here,
we deal in row instead of col as was the case in bottom view
10. Print the path from the root to the node: A good question, do revise.
2. Print all nodes at distance k from a target node: We store the parent of each node in a
hashmap. Then we do the dfs traversal (on the left, on the right, on the parent). We also keep a
visited hashmap so that the dfs does not visit the already visited node.
3. Time taken to burn the tree: Similar concept as the previous question, you need to store
the parent in a hashmap.
4. Count nodes in a complete BT: If the left and the right height is the same, then we just
return pow(2,h) - 1. Otherwise we return 1 + count(left) + count (right).
4. Construct binary tree from preorder traversal: 2 approaches: 1 is to make the binary
search tree from preorder and inorder traversal (O(nlogn) time).
Another O(n) approach could be to use the upper bound. Initially the bound is
INT_MAX. If the counter == n, return NULL, OR, if preorder[counter] > bound, return
NULL.
While calling on left, bound is updated to the root value
While calling on the right, the bound remains the same.
Pass the counter i by reference.
6. BST iterator: This can be done using a stack and in O(h) space complexity
7. Two sum in a BST: We use the next and before concept here. For next, we go to the left
left left and store it in the stack. Now we take the topmost element of the stack and call the same
function for (s.top() -> right).
For before, we go to right right right and store it in the stack, then we take the topmost
element and call the same function for s.top() -> left.
8. Recover BInary search tree: We have done the O(n) time complexity and O(1) space
complexity. Here, while we are doing the inorder traversal, we take care of the adjacent
elements, 2 cases are there : 1 violation or 2 violations.
2. Array to BST
5. kth largest element in a BST: We don't need to always store the inorder traversal in an
array, instead we can maintain a counter. This question is an example of that implementation, do
revise.
6. Check if a subtree: We use the famous strings method here, left + “X” + root->val + “X”
+ right
7. Single valued subtree: Used the method told by sanskar (using map)
8. Unique BST's
10. Preorder traversal and BST: A must revise question, done using stacks.
First initialize the root = INT_MIN, now run a for loop over the preorder array, while
stack is not empty and the preorder[i] > the topmost element, make the root equal to the
topmost element and pop, else if pre order[i] < root, then return false, else push(pre
order[i]) into the stack.
12. Minimum distance between 2 given nodes of a binary tree: Used the LCA concept, the
beautiful concept of parent and visited was giving runtime error on last test cases, I don't know
why.
13. Maximum sum from root to leaf
15. Ancestors in a BT
16. Remove BST's outside given range: I used the iterative inorder traversal as it takes lesser
time as compared to the recursive method.
17. Sum Tree: Again used the method of map , told by sanskar
19. BST to max heap: The post order traversal of the max heap is sorted.
20. Clone a binary tree: I take a map from tree to new tree and solve this question.
21. Maximum sum of non-adjacent nodes: I use the map thing again, told by sanskar
23. Connect nodes at same level: same as populating next right pointers (memorize this, very
important).
25. Sorted Linked List to BST: Used the technique of slow and fast pointers to find out the
middle element, beautifully implemented.
To do list :
2. K-sum paths: a must revise question, we use a hashmap, initially m[0] = 1, now we take
the curr_sum and the target as parameters in the function call,
3. Number of turns in binary tree: First find the LCA, then assign each node a column, then
find the path from LCA to p and q, now according to the path, find the number of changes in the
direction.
4. Merge two BST's: First find the inorder of both the BST’s, and then merge them into the
resultant array.
—------------------------------------------------------------------------------------------------------------------
SDE Sheet remaining Questions starts here
---------------------------------------------------------------------------------------------------------------------
Check out the to do list in the sheet itself as well as on leetcode (there are a few problems which
I have to do)
2. Next permutation: For every element, find the minimum element which is greater than it
on the right hand side.
4. Merge intervals: Used the custom sort to sort the given array and then the logic was
simple
5. Merge sorted array: I traverse from the back side, and compare the last elements , as the 2
given arrays are sorted.
6. Repeating and missing number: Here, we apply the formula of summation N and
summation N square.
7. Count inversions: Used the concept of merge sort here, a very good question.
8. Majority element: Application of Moore's voting algorithm, please see the intuition
behind this also in the striver video. Link\
9. Majority element (> N/3 times): Boyre Moore’s voting algorithm, here we take num1,
num2, count1, count2. At last we have 2 numbers num1 and num2 but we are not sure about
them being the majority element , so we traverse the array and find their count, if it is more than
N/3, then I push_back it into the resultant array.
10. Inverse pairs (nums[i] > 2*nums[j]): A very good question, again using the concept of
merge sort.
Today's Task (05/06/2022)
1. 4sum problem: We can do the O(n^3) method plus using the hashset (using the two
pointer method), but this takes O(n) space complexity. To reduce the space complexity,
we can maintain previous elements.
2. Longest consecutive sequence: Brute approach is to sort and then a linear traversal will
give you the answer.
The second optimized approach is to use the unordered_map, for every element in the array, if
element - 1 exists in the map, do nothing, if it doesn't, then check till how far the elements exist
in the map by incrementing the value.
3. Count subarrays with given XOR: we know the xor till index i, before i , we have stored
all the xor’s in a hashmap, now if till index i , the xor is xor, then we will check if there exists a
xor with the value = (xor ^ x), if yes, then update the answer with the frequency of it in the
hashmap.
4. Flattening a linked list: First merge the last 2 linked lists using the striver method of
merging, very easy.
Merger last two, then again last two, and continue doing so, can be done easily using
recursion.
Better approach is to use the two pointer method -> O(1) space and O(n) time
Int left = 0; int right = n - 1; int leftmax = 0; int rightmax = 0;
3. N meetings in one room: sort the vector pair according to the second element, and then
observe that we will always consider the first meeting and then apply greedy, a very simple one
4. Minimum platforms: Use of a multiset here (O(nlogn) time + O(n) space).
First of all, sort both the arrays, now take two pointers i and j
While (i < n), if the arrival[i] <= departure[j], increment platforms
Else decrement platforms.
5. Nth root of m: Here, we do a binary search having a search space from [1, m].
If the mid^n > m, r = mid, otherwise l = mid, do it till (r - l) > -1e6.
6. Matrix median: Binary search over the search space (1, 1e5), if the number of elements
less than equal to mid is less than (n*m)/2, call on the left side, otherwise call on the right side.
While (l < r) return l;
If (left1 <= right2 && left2 <= right1) return max(left1, left2)
9. Allocate books: Similar question as the famous binary search problem of subarrays <= m
Today's Task (07/06/2022)
1. Kth largest element in an array: Whenever kth largest comes, always use a minimum
priority queue, takes Nlogk time.
2. find median from data stream: Done using 2 priority queues (min and max).
3. merge k sorted arrays: use of priority queue here, make a triplet (element, array index,
index) and u can solve it easily.
5. Implement queue using stacks : We will have to do it by using 2 stacks, amortized O(1)
method, push into s1,
If s2 is not empty, then the top most element of s2 is the top, otherwise pop all elements
from s1 and push it into s2, and now whichever is the topmost element on the stack s2,
that is the answer.
6. Next greater element: If the question is asked for a circular array, u dont have to do
anything, just simply append the elements of the array to the right, and find the next greater
element for each index, no need to make extra space for appending the array, you can traverse
your i from 0 to 2n - 1, and then apply the formula i % n.
8. LRU cache: A must do question, used hashmaps and the doubly linked list.
9. Largest rectangle in a histogram: previously I had solved using 4 stacks, now did it using
2 stacks (each being a pair <int, int>).
1. Sliding window maximum: Used deque here, it allows push_back, push_front, pop_back,
pop_front. Done in O(n) time and O(k) space.
For even length, there will be two centers, so we will have to check for that.
1. The Rabin carp algorithm: A very important algorithm for string matching using hashing
2. Longest prefix suffix: find the lps array for the string s of length n. This is the famous
KMP alogirthm’s first part where we find the lps for the string s.
3. Min characters to be added at front to make the string palindrome: This is nothing but to
find the lps of the string s + string (rev(s)).
Edge case: if the string is already a palindrome, just return 0, no need to find the lps.
Today’s Task (10/06/2022)
1. Job sequencing problem: we sort the array in the descending order based on the profit,
and we also make a deadline array initialized with -1, and then we can apply some greedy
technique and solve the problem using 2 for loops.
4. Find the duplicate number: used the concept of the slow and fast pointer, first we found
out the collision node, by moving the slow pointer by one step and the fast pointer by two
steps.Now we take the starting node and keep the slow pointer in tact, and then move both the
pointers simultaneously, wherever they will meet, will be the required answer (the starting of the
loop)
1. Toppers of the class: You should know how to sort an object of a class/structure.
2. Magnets problem : Use binary search here, we are taking double, so whenever, absolute
value of left sum - right sum is less than 1e-6, return mid.
3. binary search ka subarrays ka question: do check the condition for l + 1 == r, very very
important.
4. Maximum sum rectangle: Do using the kedane’s algorithm and the prefix sum. Time :
O(n^3). We need to calculate the prefix sum column vise and then apply the kedan’s algorithm.
5. Longest increasing path in a matrix: a good question done on my own, do revise this
6. Minimum operations to reduce X to zero: we make a prefix array, we make a suffix array,
we invert the suffix array, and now we first of all find the x in prefix and suffix array by binary
search, after that I find the x - pref[i] in the suffix array accordingly.,
7. Count the number of substrings : the answer will be atmost (s, k) - atmost (s, k - 1).
Here utmost(s, k) will count the number of substrings having distinct characters at most k
using the sliding window technique, use 26 valued vector as it doesnt give TLE.
8. Check mirror in n - ary tree: A very simple question, can be done using map of stacks.
First iterate through the first array, push the nodes into the stack and then iterate through
the second array and check if the top most element of the stack is equal or not, if yes,
then pop and continue the same process.
9. Magic triplets: So here for every index i, I take a dp[i][1], dp[i][2], dp[i][3].
Here, dp[i][1] will be equal to 1 always,
We use the concept of the longest increasing subsequence length.
If (nums[i] > nums[j]) dp[i][2] ++;
Dp[i][3] += dp[j][2]
1. Stock and buy sell: Valley and hill question, valley is a valley when arr[i] <= arr[i+1] &&
arr[i] < arr[i-1].
A hill is a hill when arr[i] >= arr[i-1] && arr[i] > arr[i+1].
2. Find missing and repeating number: First we find the repeating number by using the
property that all the numbers remainder with n will be the indices of the array (0 to n - 1).
Now, we take a variable x and assign it to the xor of all the elements of the array.
Again take xor of x with each element form 1 to n.
Now x ^ repeat will give us the missing number.
2. Minimum number of jumps: We can always do the O(n^2) approach by using greedy.
But the optimized solution is to use O(n) time and O(1) space.
Use 3 variables: steps , jumps, maxreach
Initialize steps = arr[0] = maxreach, jumps = 1;
For (i = 0 -> n) {
Maxreach = max (maxreach , i + arr[i])
Steps –;
If (steps == 0) {
Jumps ++;
If (i >= maxreach) return -1;
Steps = maxreach - i;
}
}
3. Maximum number of zeroes and ones in a binary string: Just kadan’s algorithm (was
hidden inside)
4. count subsequences of type a^i, b^j, c^k: take three variables a = 0, ab = 0, abc = 0;
Now starting from the first occurrence of a, traverse the string, and perform the
following:
If you detect a, then a = 2*a + 1;
If you detect b, then ab = 2*ab + a;
If you detect c, then abc = 2*abc + ab;
Return abc;
2. Count digit groupings of a number: Written a recursive memoization solution, you should
know how to write these memoized solutions, very important.
In this question, there are two states, index and the sum, and then we have solved this
question.
We calculate the total sum of the array first, now we recursively find out the maximum
score that player 1 can get. If it is his chance, then return max(take first element or take
the last element) , if it is player 2’s chance, then return min (take first ele or take last ele)
While chance == 1, we add the nums[first] or nums[end], because we want to find the
score of player 1, but when chance == 2, we don't add anything.
5. Box stacking: First make triplets of (l,w,h) and push that into a new vector, now sort the
vector in the decreasing order of their base area, and then simply apply the concept of the LIS.
While making the vector, take l > w always for simplicity
6. Array partition: dp[i] says that whether we can have the ith element as the last element of
a partition or not. First sort the array, now for index i, find l = lower_bound(arr[i] - m), and h = i
- k; Now traversing between l and h, dp[i] = dp[i] | dp[j], if dp[i] is 1 , just break
7. Longest zig-zag subsequence: first take all the unique elements of the vector, and then
just find all the valleys and hills, the sum of them will be the answer
1. Print all permutations: A simple recursive backtracking question in which u need to swap
the elements and call for recursion.
2. N-Queen problem: first of all , create a board, and then try to place the queen for each
row and col, make a function if we can place the queen or not, if we can place, call recursion,
after recursion ends, remove the queen from there and continue forward.
3. Sudoku solver: you just have to return one solution, take care of that, otherwise the
solution will give TLE.
4. optimal strategy for a game: Understand it carefully, I take the first or the last element
and I take the minimum of the rest 2 recursive calls as the opponent is also playing optimally.
And after than I take the maximum of the first element picked answer and the last element
picked answer.
5. number of flowers in full bloom: simple upper bound and lower bound on start and end
array respectively.
6. Maximum trailing zeroes in a cornered path: We just have to find the power of 5 and
power of 2 in the product, and take the minimum of them, we can use the prefix sum technique
for this.
7. Longest path with different adjacent characters: For a particular node, the answer can be
the maximum size of the substrees or the sz[subtree(i)] + sz[substree(j)] + 1 provided both these
subtrees’s root don't share the same character with the node.
1. Product of array except self: We can do the changes in the output array itself, but first
calculating the prefix product and then taking a variable suffix_product and changing the
output array accordingly.
2. Container with most water: Use the two pointer method, and solve the question easily
3. Basic calculator: We use a stack here, and for calculating the number, use the famous
formula of curr_num = curr_num * 10 + the digit.
If the operation is ‘+’, simply add the curr_num to the stack.
If the operation is ‘-’, then add -1*curr_num to the stack.
If the operation is ‘*’, then multiply the top most ele and the curr_num and then push the
result in the stack. Same goes for the divide operation.
4. Minimum window substring: Use the sliding window approach, and use vector to store
the frequency, don't use map , it gives TLE.
1. search in a 2d matrix
2. kth smallest element in a sorted matrix: always use int mid = l + (r - l)/2, because it
doesnt give errors when using negative numbers.
This question involved doing the binary search over the range of numbers and for each
number we have to calculate the rank of the number.
1. Implement trie (prefix tree): Use of classes here, do revise this, very very important
implementation, asked in DE Shaw interviews.
2. Flatten nested list iterator: Use of recursion here, if the list[j] is integer, then just
push_back it into the answer vector, else call recursion over the list[j] which is a list.
We make a new vector ,in which we store, start_pos, height, s… and end_pos, height, e.
We sort this vector by using the custom sort.
3 edges cases has been considered here, its there in the code, see that
Then we use a multiset, for start, we insert the height into the multiset, if the max_val
changes, then push_back the answer in the ans vector.
For end, we erase the height from the vector, if the max_val changes, then push_back the
answer in the ans vector.
4. Word search 2: A very good implementation of tries here. A must revise question. Time
complexity using trie is O(nm) * O(nm).
5. Remvoe invalid parenthesis: In this question, we first calculate the minimum amount of
parenthesis to be removed by using a stack to reduce the time complexity, then it is a simple
recursive problem.
Rest conditions you can see in the code, self explanatory, not that difficult to understand.
1. Prefix and suffix search: Logic is 100% correct, I dont know why it is giving TLE.
3. Count of small numbers after self: same concept as the inversion pairs in an array. Use
merge sort here
4. Maximum candies allocated to k children: A good binary question, I was not able to think
of the solution during the contest even after spending 45 minutes, binary search should not create
a problem bro. Do think of applying binary search on the answer as well.
1. Count pyramids in a grid: dp[i][j] = min(dp[i + 1][j -1], dp[i + 1][j], dp[i + 1][j +1]) + 1/0
accordingly.
—------------------------------------------------------------------------------------------------------------------
Google top interview questions starts here
—-------------------------------------------------------------------------------------------------
1. shortest unique prefix for each word: this is a simple trie question, you just have to create
another public member freq which stores the frequency of the prefixes. As soon as you
encounter a prefix with the frequency 1, you can say that this is gonna be the shortest
unique prefix for the particular word.
2. find the element occuring once when all other are appearing thrice: we have to do it using
bit manipulation, check each bit (0 to 31) for each number, and update their count based on the
setness of the bit (1 or 0). Finally, if we get a position of the bit, whose count is 3k + 1 and is set,
then we can add it to our final answer.
3. Generate binary string: A good recursive question, always try to understand what is
happening inside the recursive calls.
4. Number following a string: use a stack here, whenever we see a decreasing sign, push the
count into the stack and increase the count.
Whenever we see a increasing sign, push the count into the stack, print the stack and
empty it, count ++
After the while loop gets completed, you again need to push the count into the stack and
print it and empty it.
5. Minimum operations to convert array A into B: We just take out the elements from A
which are a part of B, and find the length of the LIS using the lower_bound approach, this LIS
will be the LCS between array A and B. and then, the problem is solved
6. Longest repeating subsequence: same as the LCS problem, just one more condition is
added , that, i != j when s1[i] == s2[j].
7. Non repeating numbers: do xor of all the elements, check the rightmost set bit, and now
distribute all the elements into 2 groups on the basis of them having this particular bit set or not
set. Beautifully done in O(n) time and O(1) space.
8. Modular exponentiation for large numbers: n -> n/2 -> n/4 and so on…..does it in
O(logn) time
9. Word Break (Trie): a good trie question, have to check each and every prefix of the given
string in the trie, a type of recursive solution
10. Maximum index: we store the prefix minimum and the suff maximum, and we can easily
solve this question in O(n) time.
TC : O(n) and Space: O(n)
11. Largest number in K swaps: simple backtracking question, try all swaps
12. kth smallest element in an array: The array contains distinct elements, I have used the
quick select algorithm from youtube only, the logic and code is 100% correct, I don't know why
it shows runtime error on test case 157.
13. check if 2 strings are k anagrams or not: counter array of size 26, string1 ++, string2 - -
And then , just a simple logic and you are done
14. Nth natural number: Here we have to find the answer from the numbers having base 9.
Base 9 means that the numbers will comprise of digits (0 - 8). For this we just have to follow the
same method of finding a binary representation of a number (that is base 2). Here it is base
9. The answer will be the reverse of the representation obtained.
15. circular tour: use two pointers here, i and j, for any index, if we get a balance to be
negative, then start from the very next index, and continue to do so until we get the
vis == n or count < 2*n. Because every index will be visited at most twice in cases where
we don't get any answer.