├── Day-01_Arrays ├── DNF_sort.cpp ├── README.md ├── duplicate_number.cpp ├── kadanes_algorithm.cpp ├── merge_intervals.cpp ├── merge_sorted_arrays.cpp └── missing_repeating.cpp ├── Day-02_Arrays ├── README.md ├── buy_sell_stock_once.cpp ├── count_inversions.cpp ├── merge_sort.cpp ├── merge_sort.exe ├── next_permutation.cpp ├── pascal_triangle.cpp ├── rotate_matrix.cpp └── set_matrix_zeros.cpp ├── Day-03_Arrays_Maths ├── README.md ├── binary_expo.cpp ├── grid_unique_paths.cpp ├── majority_element_N2.cpp ├── majority_element_N3.cpp ├── reverse_pairs.cpp ├── search_2D_rowColSorted.cpp └── search_2D_snake.cpp ├── Day-04_Hashing ├── Four_sum.cpp ├── LongestConsecutiveSequence.cpp ├── README.md ├── Two_sum.cpp ├── repeated_chars.cpp ├── subarray_zero_sum.cpp ├── subarrays_xor.cpp └── subarrays_xor.exe ├── Day-05_LinkedList ├── README.md ├── add_2_numbers.cpp ├── delete_without_head.cpp ├── merge_sorted_list.cpp ├── middle_list.cpp ├── remove_nth_node.cpp └── reverse_list_iterative.cpp ├── Day-06_LinkedList ├── README.md ├── cycle_start.cpp ├── detect_cycle_list.cpp ├── flattening_list.cpp ├── intersection_Y.cpp ├── palindrome_list.cpp ├── reverse_groups_k.cpp └── rotate_list.cpp ├── Day-07_Two_Pointers ├── README.md ├── Three_sum.cpp ├── clone_list.cpp ├── max_consecutive_ones.cpp ├── remove_duplicates_sorted.cpp └── trapping_rainwater.cpp ├── Day-08_Greedy ├── N_meeting_one_room.cpp ├── README.md ├── activity_selection.cpp ├── coin_change.cpp ├── fractional_knapsack.cpp ├── job_sequencing.cpp └── min_platforms_railway.cpp ├── Day-09_Recursion ├── README.md ├── combination_sum.cpp ├── combination_sum_without_rep.cpp ├── generate_Subsequences_bitMasking.cpp ├── kth_permutation.cpp ├── palindrome_partitioning.cpp ├── subset_sum_duplicates.cpp └── subset_sums.cpp ├── Day-10_Backtracking ├── M_coloring.cpp ├── N_Queens.cpp ├── README.md ├── print_permutations.cpp ├── rat_maze.cpp ├── sudoku_solver.cpp └── word_break.cpp ├── Day-11_Binary_Search ├── README.md ├── aggressive_cows.cpp ├── allocate_min_pages.cpp ├── kth_2_sortedArrays.cpp ├── median_2_sortedArrays.cpp ├── median_row_sorted.cpp ├── nth_root.cpp ├── search_rotated.cpp └── single_element.cpp ├── Day-12_Bit_Manipulation ├── README.md ├── count_total_set_bits.cpp ├── countingBits.cpp ├── divide_numbers.cpp ├── find_MSB.cpp ├── powerOf2.cpp ├── power_set_bit.cpp ├── power_set_recursion.cpp ├── power_set_vector.cpp └── square_bit.cpp ├── Day-13_Stacks_Queues ├── README.md ├── balanced_parenthesis.cpp ├── next_greater_element_1.cpp ├── next_greater_element_2.cpp ├── queue_array.cpp ├── queue_using_stack.cpp ├── stack_array.cpp └── stack_using_queue.cpp ├── Day-14_Stacks ├── LRU_cache.cpp ├── README.md ├── get_min_pop.cpp ├── largest_rectangle_histogram_1.cpp ├── largest_rectangle_histogram_2.cpp ├── min_stack.cpp ├── nearest_smaller_element.cpp ├── rotten_oranges.cpp └── sliding_window_max.cpp ├── Day-15_Strings ├── README.md ├── integer_to_roman.cpp ├── longest_palindromic_substring.cpp ├── reverse_words.cpp └── roman_to_integer.cpp ├── Day-17_Binary_Tree ├── README.md ├── bottom_view.cpp ├── inorder_traversal.cpp ├── left_view.cpp ├── postorder_traversal.cpp ├── preorder_traversal.cpp ├── right_view.cpp └── top_view.cpp ├── Day-18_Binary_Tree ├── LCA.cpp ├── README.md ├── diameter.cpp ├── height_balanced.cpp ├── height_tree.cpp ├── identical_trees.cpp ├── levelorder.cpp └── levelorder_spiral.cpp ├── Day-19_Binary_Tree ├── README.md ├── check_mirror.cpp ├── flatten_tree_list.cpp ├── max_path_sum.cpp ├── mirror_n_ary.cpp ├── tree_in_postorder.cpp └── tree_in_preorder.cpp ├── Day-20_Binary_Search_Tree ├── LCA_BST.cpp ├── README.md ├── bst_array.cpp ├── check_BST_iterative.cpp ├── check_BST_range.cpp ├── inorder_pre_suc.cpp ├── inorder_successor.cpp ├── populate_next_pointers.cpp └── search_BST.cpp ├── Day-21_Binary_Search_Tree ├── README.md ├── bst_iterator.cpp ├── ceil_BST.cpp ├── floor_BST.cpp ├── kth_largest.cpp ├── kth_smallest.cpp ├── largest_BST.cpp ├── pair_sum.cpp └── serial_deserial.cpp ├── Day-22_Mixed_Questions ├── README.md ├── count_distinct_window.cpp ├── flood_fill.cpp ├── kth_largest.cpp ├── kth_largest_stream.cpp ├── median_stream.cpp └── tree_to_DLL.cpp ├── Day-23_Graph ├── README.md ├── bfs_graph.cpp ├── bipartite_bfs.cpp ├── bipartite_dfs.cpp ├── clone_undirected.cpp ├── cycle_directed.cpp ├── cycle_directed_bfs.cpp ├── cycle_undirected.cpp ├── cycle_undirected_dfs.cpp ├── dfs_graph.cpp ├── number_islands.cpp ├── topo_sort.cpp └── topo_sort_dfs.cpp ├── Day-24_Graph ├── README.md ├── SCC_kosaraju.cpp └── dijkstra_all_shortest_path.cpp └── README.md /Day-01_Arrays/DNF_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | problem link: https://leetcode.com/problems/sort-colors/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | void sortColors(vector& nums) { 8 | // use DNF sort 9 | // region of 0s{0, low}, region of 1s{low, mid}, region of 2s{high, n - 1} 10 | // uncertain region or unsorted region{mid, high}. 11 | // we need to shrink this region{mid, high}. 12 | int n = nums.size(); 13 | int low = 0, mid = 0, high = n - 1; 14 | while(mid <= high) { 15 | if(nums[mid] == 0) 16 | swap(nums[mid++], nums[low++]); 17 | else if(nums[mid] == 1) 18 | mid++; 19 | else 20 | swap(nums[mid], nums[high--]); 21 | } 22 | } 23 | }; -------------------------------------------------------------------------------- /Day-01_Arrays/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | DNF Sort | 3 pointer partitioning | [view](DNF_sort.cpp) 6 | 2 | Finding Missing and Repeating | repeating xor {1 to n} | [view](missing_repeating.cpp) 7 | 3 | Kadane's Algorithm | Max Subarray Sum | [view](kadanes_algorithm.cpp) 8 | 4 | Duplicate Number | Cycle Detection Linked List {index -> element} | [view](duplicate_number.cpp) 9 | 5 | Merge Intervals | sort, condition of merging | [view](merge_intervals.cpp) 10 | 6 | Merge Sorted Space in O(1) Space | Gap Method: Shear Sort | [view](merge_sorted_arrays.cpp) -------------------------------------------------------------------------------- /Day-01_Arrays/duplicate_number.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/find-the-duplicate-number/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // tortoise and hare approach to cycle detection 8 | int findDuplicate(vector& nums) { 9 | int slow = nums[0], fast = nums[0]; 10 | do { 11 | slow = nums[slow]; // 1 step 12 | fast = nums[nums[fast]]; // 2 steps 13 | }while(slow != fast); 14 | // cycle is detected: move fast to the head 15 | fast = nums[0]; 16 | // move 1 step each 17 | while(slow != fast) { 18 | slow = nums[slow]; 19 | fast = nums[fast]; 20 | } 21 | // value where cycle occurs: duplicate element 22 | return slow; 23 | } 24 | }; -------------------------------------------------------------------------------- /Day-01_Arrays/kadanes_algorithm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/maximum-subarray/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | int maxSubArray(vector& nums) { 8 | // kadane's algo 9 | int cur_sum = 0, max_sum = INT_MIN; 10 | for(const int x : nums) { 11 | cur_sum += x; 12 | max_sum = max(max_sum, cur_sum); 13 | if(cur_sum < 0) 14 | cur_sum = 0; 15 | } 16 | return max_sum; 17 | } 18 | }; -------------------------------------------------------------------------------- /Day-01_Arrays/merge_intervals.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/merge-intervals/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | vector> merge(vector>& intervals) { 8 | vector> results; 9 | // sort on the basis of the start value 10 | sort(intervals.begin(), intervals.end()); 11 | 12 | for(auto &interval : intervals) { 13 | // no common point: add the interval without merging 14 | if(results.empty() || interval[0] > results.back()[1]) 15 | results.push_back(interval); 16 | else 17 | // interval can be merged, update the ending value of the latest added interval 18 | results.back()[1] = max(results.back()[1], interval[1]); 19 | } 20 | return results; 21 | } 22 | }; -------------------------------------------------------------------------------- /Day-01_Arrays/merge_sorted_arrays.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Solution{ 5 | public: 6 | int nextStep(int n) { 7 | // stop the process when cycle of gap 1 is completed. 8 | if(n <= 1) 9 | return 0; 10 | 11 | return ceil(n / 2.0); 12 | } 13 | 14 | //Function to merge the arrays. 15 | void merge(long long arr1[], long long arr2[], int n, int m) { 16 | int gap_step = nextStep(n + m); 17 | 18 | while(gap_step > 0) { 19 | int i, j; 20 | // compare the elements in the first array 21 | for(i = 0; i + gap_step < n; i++) { 22 | if(arr1[i] > arr1[i + gap_step]) 23 | swap(arr1[i], arr1[i + gap_step]); 24 | } 25 | // compare the elements in both the arrays: cross arrays 26 | j = gap_step > n ? gap_step - n : 0; 27 | for(; i < n && j < m; i++, j++) { 28 | if(arr1[i] > arr2[j]) 29 | swap(arr1[i], arr2[j]); 30 | } 31 | // compare the elements in the second array 32 | if(j < m) { 33 | for(int j = 0; j + gap_step < m; j++) { 34 | if(arr2[j] > arr2[j + gap_step]) 35 | swap(arr2[j], arr2[j + gap_step]); 36 | } 37 | } 38 | // get the gap step for next iteration 39 | gap_step = nextStep(gap_step); 40 | } 41 | } 42 | }; 43 | 44 | int main() 45 | { 46 | 47 | int T; 48 | cin >> T; 49 | 50 | while(T--){ 51 | int n, m; 52 | cin >> n >> m; 53 | 54 | long long arr1[n], arr2[m]; 55 | 56 | for(int i = 0;i> arr1[i]; 58 | } 59 | 60 | for(int i = 0;i> arr2[i]; 62 | } 63 | Solution ob; 64 | ob.merge(arr1, arr2, n, m); 65 | 66 | for (int i = 0; i < n; i++) 67 | cout< 6 | using namespace std; 7 | 8 | class Solution{ 9 | public: 10 | int *findTwoElement(int *arr, int n) { 11 | // code here 12 | int result = 0; 13 | for(int i = 0; i < n; i++) 14 | result ^= arr[i]; 15 | 16 | // take xor with 1,2,3...n 17 | for(int i = 1; i <= n; i++) 18 | result ^= i; 19 | 20 | // result = missing ^ repeating 21 | 22 | int rsb_mask = result & -result; 23 | int missing = 0, repeating = 0; 24 | // partition elements into 2 sets 25 | for(int i = 0; i < n; i++) { 26 | if(rsb_mask & arr[i]) 27 | repeating ^= arr[i]; 28 | else 29 | missing ^= arr[i]; 30 | } 31 | for(int i = 1; i <= n; i++) { 32 | if(rsb_mask & i) 33 | repeating ^= i; 34 | else 35 | missing ^= i; 36 | } 37 | 38 | // find the exact values of missing and repeating 39 | for(int i = 0; i < n; i++) { 40 | if(arr[i] == missing) { 41 | swap(missing, repeating); 42 | break; 43 | } 44 | } 45 | int *ans = new int[2]; 46 | ans[0] = repeating; 47 | ans[1] = missing; 48 | 49 | return ans; 50 | 51 | } 52 | }; 53 | 54 | 55 | int main() { 56 | int t; 57 | cin >> t; 58 | while (t--) { 59 | int n; 60 | cin >> n; 61 | int a[n]; 62 | for (int i = 0; i < n; i++) { 63 | cin >> a[i]; 64 | } 65 | Solution ob; 66 | auto ans = ob.findTwoElement(a, n); 67 | cout << ans[0] << " " << ans[1] << "\n"; 68 | } 69 | return 0; 70 | } -------------------------------------------------------------------------------- /Day-02_Arrays/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Buy and Sell Stock: One transaction | buy on min_val and find the max profit | [view](buy_sell_stock_once.cpp) 6 | 2 | Rotate Matrix Clockwise | transpose, reverse each row | [view](rotate_matrix.cpp) 7 | 3 | Next Permutation | swap, reverse | [view](next_permutation.cpp) 8 | 4 | Set Matrix Zeros | in place, bottom to top, right to left | [view](set_matrix_zeros.cpp) 9 | 5 | Merge Sort | divide and conquer, recursion | [view](merge_sort.cpp) 10 | 6 | Inversion Count | merge sort | [view](count_inversions.cpp) 11 | 7 | Pascal Triangle | Dynamic Programming | [view](pascal_triangle.cpp) -------------------------------------------------------------------------------- /Day-02_Arrays/buy_sell_stock_once.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // maintain the min value of stock so far and find max profit if sold today 8 | int maxProfit(vector &prices) { 9 | int max_profit = 0, min_val = prices[0]; 10 | int n = prices.size(); // the number of days 11 | 12 | for(int i = 1; i < n; i++) { 13 | // buy the stock: available for lower price 14 | if(prices[i] < min_val) 15 | min_val = prices[i]; 16 | else 17 | // sell the stock 18 | max_profit = max(max_profit, prices[i] - min_val); 19 | } 20 | return max_profit; 21 | }; 22 | } -------------------------------------------------------------------------------- /Day-02_Arrays/count_inversions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/inversion-of-array-1587115620/1 3 | */ 4 | 5 | int merge(vector &arr, int start, int mid, int end) { 6 | int n1 = mid - start + 1; // mid is included 7 | int n2 = end - mid; 8 | // create 2 arrays for the left and right part 9 | int left[n1], right[n2]; 10 | for(int i = 0; i < n1; i++) 11 | left[i] = arr[start + i]; 12 | for(int i = 0; i < n2; i++) 13 | right[i] = arr[mid + i + 1]; 14 | // 3 pointers 15 | int i = 0, j = 0, k = start; 16 | int count = 0; 17 | while(i < n1 && j < n2) { 18 | if(left[i] <= right[j]) 19 | arr[k++] = left[i++]; 20 | else { 21 | // count inversions 22 | count += (n1 - i); 23 | arr[k++] = right[j++]; 24 | } 25 | } 26 | // add the remaining elements 27 | while(i < n1) 28 | arr[k++] = left[i++]; 29 | while(j < n2) 30 | arr[k++] = right[j++]; 31 | 32 | return count; 33 | } 34 | 35 | int inversion_helper(vector &arr, int start, int end) { 36 | // base case 37 | if(start >= end) 38 | return 0; 39 | 40 | // recursivec calls: merge sort 41 | int result = 0, mid = start + (end - start) / 2; 42 | result += inversion_helper(arr, start, mid); 43 | result += inversion_helper(arr, mid + 1, end); 44 | // cross-inversions 45 | result += merge(arr, start, mid, end); 46 | 47 | return result; 48 | } 49 | 50 | int Solution::countInversions(vector &A) { 51 | return inversion_helper(A, 0, A.size() - 1); 52 | } 53 | -------------------------------------------------------------------------------- /Day-02_Arrays/merge_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Merge sort is a divide and conquer algorithm. 3 | It divides the input array into 2 halves and then merges the 2 sorted halves. 4 | Time complexity = O(nlogn) 5 | */ 6 | #include 7 | using namespace std; 8 | 9 | // helper function to merge 2 sorted arrays 10 | void merge(int *arr, int start, int mid, int end) { 11 | int n1 = mid - start + 1; // mid is included 12 | int n2 = end - mid; 13 | 14 | // temp arrays 15 | int left[n1], right[n2]; 16 | for(int i = 0; i < n1; i++) 17 | left[i] = arr[start + i]; 18 | for(int i = 0; i < n1; i++) 19 | right[i] = arr[mid + i + 1]; 20 | 21 | int i = 0, j = 0, k = start; 22 | while(i < n1 && j < n2) { 23 | if(left[i] <= right[j]) 24 | arr[k++] = left[i++]; 25 | else 26 | arr[k++] = right[j++]; 27 | } 28 | // copy the remaining elements 29 | while(i < n1) 30 | arr[k++] = left[i++]; 31 | while(j < n2) 32 | arr[k++] = right[j++]; 33 | } 34 | 35 | // recursive function for merge sort 36 | void mergeSort(int *arr, int start, int end) { 37 | // base case 38 | if(start >= end) 39 | return; 40 | 41 | int mid = start + (end - start) / 2; 42 | // recursive calls 43 | mergeSort(arr, start, mid); 44 | mergeSort(arr, mid + 1, end); 45 | // merge the 2 sorted halves 46 | merge(arr, start, mid, end); 47 | } 48 | 49 | // helper function to print the array 50 | void printArray(int *arr, int n) { 51 | for(int i = 0; i < n; i++) 52 | cout << arr[i] << " "; 53 | } 54 | 55 | int main() { 56 | 57 | int n; 58 | cin >> n; 59 | 60 | int arr[n]; 61 | for(int i = 0; i < n; i++) 62 | cin >> arr[i]; 63 | 64 | mergeSort(arr, 0, n - 1); 65 | printArray(arr, n); 66 | 67 | return 0; 68 | } -------------------------------------------------------------------------------- /Day-02_Arrays/merge_sort.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vineethm1627/SDE_Sheet_Striver/ba935a20d4d72fe0421401a0423326260690c37f/Day-02_Arrays/merge_sort.exe -------------------------------------------------------------------------------- /Day-02_Arrays/next_permutation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/next-permutation/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | vector nextPermutation(vector &arr) { 8 | int i, n = arr.size(); 9 | // from the back, find the first element: arr[i] < arr[i + 1] 10 | for(i = n - 2; i >= 0; i--) { 11 | if(arr[i] < arr[i + 1]) 12 | break; 13 | } 14 | // reverse the entire sequence: 5 4 3 2 1 --> 1 2 3 4 5 15 | if(i < 0) { 16 | reverse(arr.begin(), arr.end()); 17 | return arr; 18 | } 19 | // from the back, find the first element: arr[j] > arr[i] 20 | for(int j = n - 1; j > i; j--) { 21 | if(arr[j] > arr[i]) { 22 | swap(arr[i], arr[j]); 23 | break; 24 | } 25 | } 26 | // reverse the part from i+1 till end 27 | reverse(arr.begin() + i + 1, arr.end()); 28 | return arr; 29 | } 30 | 31 | }; -------------------------------------------------------------------------------- /Day-02_Arrays/pascal_triangle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/pascals-triangle/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | vector> generate(int numRows) { 8 | vector> pt(numRows); 9 | 10 | for(int i = 0; i < numRows; i++) { 11 | pt[i].resize(i + 1); 12 | pt[i][0] = pt[i][i] = 1; // first and last values are always 1 13 | 14 | for(int j = 1; j < i; j++) 15 | pt[i][j] = pt[i - 1][j - 1] + pt[i - 1][j]; 16 | } 17 | return pt; 18 | } 19 | }; -------------------------------------------------------------------------------- /Day-02_Arrays/rotate_matrix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/rotate-image/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | void rotate(vector>& matrix) { 8 | // transpose 9 | int n = matrix.size(); 10 | for(int i = 0; i < n; i++) { 11 | for(int j = 0; j < i; j++) 12 | swap(matrix[i][j], matrix[j][i]); 13 | } 14 | 15 | // reverse every row 16 | for(int i = 0; i < n; i++) 17 | reverse(matrix[i].begin(), matrix[i].end()); 18 | } 19 | }; -------------------------------------------------------------------------------- /Day-02_Arrays/set_matrix_zeros.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/set-matrix-zeroes/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | void setZeroes(vector>& matrix) { 8 | const int rows = matrix.size(), cols = matrix[0].size(); 9 | bool fillFirstCol = false; 10 | // matrix[0][0] = 0, implies fill the first row with 0s 11 | // we are considering aux arrays as the first row and first col 12 | for(int i = 0; i < rows; i++) { 13 | // first col should be set to 0 14 | if(matrix[i][0] == 0) 15 | fillFirstCol = true; 16 | for(int j = 1; j < cols; j++) { 17 | // mark 0 in the corresponding row and col 18 | if(matrix[i][j] == 0) 19 | matrix[i][0] = matrix[0][j] = 0; 20 | } 21 | } 22 | // set matrix elements to 0s 23 | // traverse from bottom right to top; from right to left 24 | for(int i = rows - 1; i >= 0; i--) { 25 | // exclude the first col 26 | for(int j = cols - 1; j >= 1; j--) { 27 | // check for the marking in the aux first row / col array 28 | if(matrix[i][0] == 0 || matrix[0][j] == 0) 29 | matrix[i][j] = 0; 30 | } 31 | // set the first col elements to 0 if required 32 | if(fillFirstCol) 33 | matrix[i][0] = 0; 34 | } 35 | } 36 | }; -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Search in a 2D Matrix | binary search; unravel:treat as 1D array | [view](search_2D_snake.cpp) 6 | 2 | Search in row col sorted Matrix | staircase search | [view](search_2D_rowColSorted.cpp) 7 | 3 | Power(x, n) | binary exponentiation | [view](binary_expo.cpp) 8 | 4 | Majority Element > floor(n/2) | Moore Voting Algo | [view](majority_element_N2.cpp) 9 | 5 | Majority Element > floor(n/3) | Moore Voting Algo 2 variables | [view](majority_element_N3.cpp) 10 | 6 | Reverse Pairs | count inversions using merge sort | [view](reverse_pairs.cpp) 11 | 7 | Grid Unique Paths | DP, memoization | [view](grid_unique_paths.cpp) -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/binary_expo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/powx-n/ 3 | */ 4 | 5 | #define lli long long int 6 | lli M = 1e9 + 7; 7 | 8 | long long int binary_expo(long long base, long long p) { 9 | if(p == 0) 10 | return 1; 11 | 12 | if(p < 0) 13 | return 1 / binary_expo(base, -p); 14 | 15 | long long int result = 1; 16 | base %= M; 17 | 18 | while(p) { 19 | if(p & 1) 20 | result = result * base % M; 21 | base = base * base % M; 22 | p >>= 1; 23 | } 24 | return result; 25 | } -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/grid_unique_paths.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/unique-paths/ 3 | */ 4 | 5 | // Recursion with Memoization 6 | 7 | int countPaths(int sr, int sc, int dr, int dc, vector> &memo) { 8 | // base case: the bottom right destination is reached 9 | if(sr == dr && sc == dc) 10 | return 1; 11 | else if(sc > dc || sr > dr) 12 | return 0; 13 | 14 | // check for precomputed values 15 | if(memo[sr][sc] != -1) 16 | return memo[sr][sc]; 17 | // recursive calls 18 | int h = countPaths(sr, sc + 1, dr, dc, memo); // horizontal move 19 | int v = countPaths(sr + 1, sc, dr, dc, memo); // vertical move 20 | 21 | return memo[sr][sc] = h + v; 22 | } 23 | 24 | int uniquePaths(int m, int n) { 25 | 26 | vector> memo(m + 1, vector(n + 1, -1)); 27 | return countPaths(1, 1, m, n, memo); 28 | } 29 | 30 | // Dynamic Programming 31 | 32 | int uniquePaths(int m, int n) { 33 | // DP Solution 34 | // dp[i][j]: number of unique paths to arrive at the point (i, j) 35 | vector> dp(m, vector(n)); 36 | 37 | for(int i = 0; i < m; i++) { 38 | for(int j = 0; j < n; j++) { 39 | if(i == 0 || j == 0) 40 | dp[i][j] = 1; 41 | else 42 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 43 | } 44 | } 45 | return dp[m - 1][n - 1]; 46 | } -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/majority_element_N2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/majority-element/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // Moore Voting Algorithm 8 | int majorityElement(vector& nums) { 9 | int result = 0, count = 0; 10 | 11 | for(const int &x : nums) { 12 | // first occurrence of the number 13 | if(count == 0) { 14 | result = x; 15 | // reset count value 16 | count = 1; 17 | } 18 | else if(result == x) 19 | count++; 20 | else 21 | count--; 22 | } 23 | return result; 24 | } 25 | }; -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/majority_element_N3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/majority-element-ii/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // Boyer Moore Voting Algorithm 8 | vector majorityElement(vector& nums) { 9 | vector results; 10 | int num1 = -1, num2 = -1, count1 = 0, count2 = 0; 11 | for(int &x : nums) { 12 | if(x == num1) 13 | count1++; 14 | else if(x == num2) 15 | count2++; 16 | else if(count1 == 0) { 17 | // reset values 18 | num1 = x; 19 | count1 = 1; 20 | } 21 | else if(count2 == 0) { 22 | // reset values 23 | num2 = x; 24 | count2 = 1; 25 | } 26 | else { 27 | count1--; 28 | count2--; 29 | } 30 | } 31 | // process the results 32 | count1 = count2 = 0; 33 | int n = nums.size(); 34 | for(int &x : nums) { 35 | if(x == num1) 36 | count1++; 37 | else if(x == num2) 38 | count2++; 39 | } 40 | // condition checks 41 | if(count1 > n / 3) 42 | results.push_back(num1); 43 | if(count2 > n / 3) 44 | results.push_back(num2); 45 | 46 | return results; 47 | } 48 | }; -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/reverse_pairs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/reverse-pairs/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // similar to merge sort: count inversions 8 | 9 | // helper function to count inversions 10 | int merge(vector &nums, int start, int mid, int end) { 11 | int count = 0; 12 | int n1 = mid - start + 1; // mid is included 13 | int n2 = end - mid; 14 | // fill the values 15 | int left[n1], right[n2]; 16 | 17 | for(int i = 0; i < n1; i++) 18 | left[i] = nums[start + i]; 19 | for(int i = 0; i < n2; i++) 20 | right[i] = nums[mid + i + 1]; 21 | 22 | // count the required pairs 23 | // traverse the left part of the array 24 | int j = 0; 25 | for(int i = 0; i < n1; i++) { 26 | while(j < n2 && left[i] > 2LL * right[j]) 27 | j++; 28 | count += j; 29 | } 30 | 31 | // 3 pointers 32 | int i = 0, k = start; 33 | j = 0; 34 | while(i < n1 && j < n2) { 35 | if(left[i] <= right[j]) 36 | nums[k++] = left[i++]; 37 | else 38 | nums[k++] = right[j++]; 39 | } 40 | // add the remaining elements 41 | while(i < n1) 42 | nums[k++] = left[i++]; 43 | while(j < n2) 44 | nums[k++] = right[j++]; 45 | 46 | return count; 47 | } 48 | 49 | // recursive mergeSort function 50 | int mergeSort(vector &nums, int start, int end) { 51 | // base case 52 | if(start >= end) 53 | return 0; 54 | 55 | int mid = start + (end - start) / 2; 56 | int count = mergeSort(nums, start, mid); 57 | count += mergeSort(nums, mid + 1, end); 58 | // cross inversions 59 | count += merge(nums, start, mid, end); 60 | 61 | return count; 62 | } 63 | 64 | int reversePairs(vector& nums) { 65 | return mergeSort(nums, 0, nums.size() - 1); 66 | } 67 | }; -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/search_2D_rowColSorted.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/search-in-a-matrix17201720/1 3 | */ 4 | 5 | /* 6 | search for a given element in row wise and column wise sorted array. 7 | 8 | Steps: 9 | 1) Start from top right element 10 | 2) for loop compare this element e with x 11 | a) if they are equal then return its position 12 | b) e < x then go down 13 | c) e > x then go to left 14 | 3) return false if limits go out of bound. 15 | */ 16 | #include 17 | using namespace std; 18 | 19 | #define pii pair 20 | 21 | pii staircaseSearch(int *arr[], int m, int n, int key) { 22 | int row = 0, col = n - 1; 23 | pii p = make_pair(-1, -1); 24 | 25 | while(row < m and col >= 0) { 26 | if(arr[row][col] == key) { 27 | p = make_pair(row, col); 28 | return p; 29 | } 30 | else if(key < arr[row][col]) 31 | col--; 32 | else 33 | row++; 34 | } 35 | return p; 36 | } 37 | 38 | int main() { 39 | 40 | int r, c, key; 41 | cin >> r >> c >> key; 42 | 43 | int *arr[r]; 44 | for(int i = 0; i < r; i++) 45 | arr[i] = new int[c]; 46 | for(int i = 0; i < r; i++) { 47 | for(int j = 0; j < c; j++) 48 | cin >> arr[i][j]; 49 | } 50 | 51 | pii p = staircaseSearch(arr, r, c, key); 52 | if(p.first == -1) 53 | cout << "element not found"; 54 | else 55 | cout << "element found at index : " << p.first << " " << p.second; 56 | 57 | return 0; 58 | } -------------------------------------------------------------------------------- /Day-03_Arrays_Maths/search_2D_snake.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/search-a-2d-matrix/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | bool searchMatrix(vector> &matrix, int target) { 8 | int rows = matrix.size(), cols = matrix[0].size(); 9 | // binary search 10 | int start = 0, end = rows * cols - 1; 11 | int mid, r, c; 12 | 13 | while(start <= end) { 14 | mid = start + (end - start) / 2; 15 | // find the value of row and col of the mid element 16 | r = mid / cols; 17 | c = mid % cols; 18 | if(matrix[r][c] == target) 19 | return true; 20 | // narrow down the search space 21 | if(target < matrix[r][c]) 22 | end = mid - 1; 23 | else 24 | start = mid + 1; 25 | } 26 | return false; 27 | } 28 | }; -------------------------------------------------------------------------------- /Day-04_Hashing/Four_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/4sum/ 3 | */ 4 | 5 | vector> fourSum(vector &nums, int target) { 6 | vector> result; 7 | int n = nums.size(); 8 | // base case: min 4 elements should be there 9 | if(nums.size() < 4) 10 | return {}; 11 | // sort the vector 12 | sort(nums.begin(), nums.end()); 13 | 14 | for(int i = 0; i < n - 3; i++) { 15 | // avoid duplicates 16 | if(i > 0 && nums[i] == nums[i - 1]) 17 | continue; 18 | for(int j = i + 1; j < n - 2; j++) { 19 | // avoid duplicates 20 | if(j > i + 1 && nums[j] == nums[j - 1]) 21 | continue; 22 | // now apply pair sum 23 | int left = j + 1, right = n - 1; 24 | while(left < right) { 25 | int sum = nums[i] + nums[j] + nums[left] + nums[right]; 26 | if(sum == target) { 27 | result.push_back({nums[i], nums[j], nums[left], nums[right]}); 28 | left++; 29 | // avoid duplicates 30 | while(left < right && nums[left] == nums[left - 1]) 31 | left++; 32 | } 33 | else if(sum < target) 34 | left++; 35 | else 36 | right--; 37 | } 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Day-04_Hashing/LongestConsecutiveSequence.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/longest-consecutive-sequence/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | int longestConsecutive(vector& nums) { 8 | int max_len = 0; 9 | unordered_set s(nums.begin(), nums.end()); 10 | 11 | for(int x : s) { 12 | // x will be the first number of the sequence 13 | // if x - 1 exists then current x is already a part of the sequence. 14 | if(s.find(x - 1) != s.end()) 15 | continue; 16 | int cur_len = 1; 17 | while(s.find(++x) != s.end()) 18 | cur_len++; 19 | 20 | max_len = max(max_len, cur_len); 21 | } 22 | return max_len; 23 | } 24 | }; -------------------------------------------------------------------------------- /Day-04_Hashing/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Two Sum | Hashmap of elements | [view](Two_sum.cpp) 6 | 2 | Longest Consecutive Sequence | unordered set | [view](LongestConsecutiveSequence.cpp) 7 | 3 | Longest Substring without Repeating Chars | sliding window + hashmap | [view](repeated_chars.cpp) 8 | 4 | Largest Subarray with 0 sum | hashmap {cum_sum, i} | [view](subarray_zero_sum.cpp) 9 | 5 | Four Sum | sorting and two pointer approach | [view](Four_sum.cpp) 10 | 6 | Count of subarrays with given xor | hashing, prefix xor | [view](subarrays_xor.cpp) -------------------------------------------------------------------------------- /Day-04_Hashing/Two_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/two-sum/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | vector twoSum(vector& nums, int target) { 8 | unordered_map m {{nums[0], 0}}; // element, index of occurrence 9 | int n = nums.size(); 10 | for(int i = 1; i < n; i++) { 11 | int rem = target - nums[i]; 12 | if(m.find(rem) != m.end()) { 13 | // required element exists in the array so far 14 | return {m[rem], i}; 15 | } 16 | // update the current element in the map 17 | m.insert({nums[i], i}); 18 | } 19 | return {}; 20 | } 21 | }; -------------------------------------------------------------------------------- /Day-04_Hashing/repeated_chars.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/longest-substring-without-repeating-characters/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | int lengthOfLongestSubstring(string s) { 8 | // edge case 9 | if(s.empty()) 10 | return 0; 11 | 12 | int max_len = 1; 13 | // freq hashmap 14 | int visited[256] = {0}; 15 | // apply sliding window 16 | int left = 0, right = 0, n = s.size(); 17 | while(right < n) { 18 | // window expansion: take the current element into consideration 19 | visited[s[right]]++; 20 | // window contraction: if current char is duplicated in the current window 21 | while(visited[s[right]] > 1) { 22 | // remove the left most char from the window 23 | visited[s[left]]--; 24 | left++; 25 | } 26 | max_len = max(max_len, right - left + 1); 27 | right++; 28 | } 29 | return max_len; 30 | } 31 | }; -------------------------------------------------------------------------------- /Day-04_Hashing/subarray_zero_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/largest-subarray-with-0-sum/1 3 | */ 4 | 5 | int maxLen(int arr[], int n) { 6 | // hashmap of cumulative sum --> index 7 | unordered_map m; 8 | int max_len = 0, cur_sum = 0; 9 | 10 | for(int i = 0; i < n; i++) { 11 | cur_sum += arr[i]; 12 | if(cur_sum == 0) { 13 | max_len = i + 1; 14 | continue; 15 | } 16 | // look for cur_sum in the hashmap 17 | if(m.find(cur_sum) != m.end()) 18 | max_len = max(max_len, i - m[cur_sum]); 19 | else 20 | m[cur_sum] = i; 21 | } 22 | return max_len; 23 | } -------------------------------------------------------------------------------- /Day-04_Hashing/subarrays_xor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://www.geeksforgeeks.org/count-number-subarrays-given-xor/ 3 | */ 4 | /* 5 | Given an array of integers arr[] and a number m, count the number of subarrays having XOR of their elements as m. 6 | Examples: 7 | 8 | Input : arr[] = {4, 2, 2, 6, 4}, m = 6 9 | Output : 4 10 | Explanation : The subarrays having XOR of 11 | their elements as 6 are {4, 2}, 12 | {4, 2, 2, 6, 4}, {2, 2, 6}, 13 | and {6} 14 | 15 | Input : arr[] = {5, 6, 7, 8, 9}, m = 5 16 | Output : 2 17 | Explanation : The subarrays having XOR of 18 | their elements as 5 are {5} 19 | and {5, 6, 7, 8, 9} 20 | */ 21 | #include 22 | #include 23 | using namespace std; 24 | 25 | int countXOR(int *arr, int n, int m) { 26 | unordered_map freq; 27 | int count = 0, prefix_xor = 0; 28 | 29 | for(int i = 0; i < n; i++) { 30 | prefix_xor ^= arr[i]; 31 | if(prefix_xor == m) 32 | count++; 33 | 34 | if(freq.find(prefix_xor ^ m) != freq.end()) 35 | count += freq[prefix_xor ^ m]; 36 | 37 | // update value in the map 38 | freq[prefix_xor]++; 39 | } 40 | return count; 41 | } 42 | 43 | int main() { 44 | int n; 45 | cin >> n; 46 | 47 | int arr[n]; 48 | for(int i = 0; i < n; i++) 49 | cin >> arr[i]; 50 | 51 | int m; 52 | cin >> m; 53 | 54 | cout << countXOR(arr, n, m); 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /Day-04_Hashing/subarrays_xor.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vineethm1627/SDE_Sheet_Striver/ba935a20d4d72fe0421401a0423326260690c37f/Day-04_Hashing/subarrays_xor.exe -------------------------------------------------------------------------------- /Day-05_LinkedList/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Reverse a linked list (iterative) | 3 pointers{P,C,N} | [view](reverse_list_iterative.cpp) 6 | 2 | Middle of linked list | slow & fast pointers | [view](middle_list.cpp) 7 | 3 | Merge 2 Sorted linked lists | Recursion, in-place | [view](merge_sorted_list.cpp) 8 | 4 | Delete node without head pointer | O(1) swap and delete | [view](delete_without_head.cpp) 9 | 5 | Remove Nth node from End | 2 pointers, edge cases | [view](remove_nth_node.cpp) 10 | 6 | Add two numbers in reverse | elementary maths | [view](add_2_numbers.cpp) -------------------------------------------------------------------------------- /Day-05_LinkedList/add_2_numbers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/add-two-numbers/ 3 | */ 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode() : val(0), next(nullptr) {} 11 | * ListNode(int x) : val(x), next(nullptr) {} 12 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 13 | * }; 14 | */ 15 | 16 | ListNode* addTwoNumbers(Listnode* l1, ListNode *l2) { 17 | ListNode head; 18 | ListNode *curr = &head; 19 | int carry = 0; 20 | 21 | while(l1 || l2 || carry) { 22 | if(l1) { 23 | carry += l1->val; 24 | l1 = l1->next; 25 | } 26 | if(l2) { 27 | carry += l2->val; 28 | l2 = l2->next; 29 | } 30 | // create new node 31 | curr->next = new ListNode(carry % 10); 32 | carry /= 10; 33 | // move curr to the last node (new node added) 34 | curr = curr->next; 35 | } 36 | return head.next; 37 | } -------------------------------------------------------------------------------- /Day-05_LinkedList/delete_without_head.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/delete-node-in-a-linked-list/ 3 | */ 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode(int x) : val(x), next(NULL) {} 11 | * }; 12 | */ 13 | 14 | void deleteNode(ListNode *node) { 15 | // copy the value 16 | node->val = node->next->val; 17 | // delete the next node 18 | node->next = node->next->next; 19 | } -------------------------------------------------------------------------------- /Day-05_LinkedList/merge_sorted_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/merge-two-sorted-lists/ 3 | */ 4 | 5 | struct ListNode { 6 | int val; 7 | ListNode *next; 8 | 9 | ListNode(): val(0), next(NULL) {} 10 | ListNode(int x): val(x), next(NULL) {} 11 | ListNode(int x, ListNode *next): val(x), next(next) {} 12 | }; 13 | 14 | ListNode* mergeTwoLists(ListNode *l1, ListNode *l2) { 15 | // base cases 16 | if(!l1) 17 | return l2; 18 | else if(!l2) 19 | return l1; 20 | 21 | if(l1->val < l2->val) { 22 | l1->next = mergeTwoLists(l1->next, l2); 23 | return l1; 24 | } 25 | else { 26 | l2->next = mergeTwoLists(l1, l2->next); 27 | return l2; 28 | } 29 | } -------------------------------------------------------------------------------- /Day-05_LinkedList/middle_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/middle-of-the-linked-list/ 3 | */ 4 | 5 | struct ListNode { 6 | int val; 7 | ListNode *next; 8 | 9 | ListNode(): val(0), next(NULL) {} 10 | ListNode(int x): val(x), next(NULL) {} 11 | ListNode(int x, ListNode *next): val(x), next(next) {} 12 | }; 13 | 14 | ListNode *middleNode(ListNode *head) { 15 | ListNode *slow = head; 16 | ListNode *fast = head; 17 | // edge case: empty / 1 node 18 | if(head || head->next) 19 | return head; 20 | 21 | while(fast && fast->next) { 22 | slow = slow->next; // 1 step 23 | fast = fast->next->next; // 2 steps 24 | } 25 | return slow; 26 | } -------------------------------------------------------------------------------- /Day-05_LinkedList/remove_nth_node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/remove-nth-node-from-end-of-list/ 3 | */ 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode() : val(0), next(nullptr) {} 11 | * ListNode(int x) : val(x), next(nullptr) {} 12 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 13 | * }; 14 | */ 15 | 16 | ListNode* removeNthFromEnd(ListNode *head, int n) { 17 | ListNode *slow = head; 18 | ListNode *fast = head; 19 | // move fast pointer by n steps 20 | for(int i = 0; i < n; i++) 21 | fast = fast->next; 22 | // edge cases: head node is to be deleted 23 | if(!fast) 24 | return head->next; 25 | 26 | // while fast reaches the last node 27 | while(fast->next) { 28 | slow = slow->next; 29 | fast = fast->next; 30 | } 31 | // delete slow->next node 32 | slow->next = slow->next->next; 33 | return head; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Day-05_LinkedList/reverse_list_iterative.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/reverse-linked-list/ 3 | */ 4 | 5 | struct ListNode { 6 | int val; 7 | ListNode *next; 8 | 9 | ListNode(): val(0), next(NULL) {} 10 | ListNode(int x): val(x), next(NULL) {} 11 | ListNode(int x, ListNode *next): val(x), next(next) {} 12 | }; 13 | 14 | ListNode *reverseList(ListNode *head) { 15 | ListNode *P = NULL; 16 | ListNode *C = head; 17 | ListNode *N; 18 | 19 | while(C) { 20 | N = C->next; 21 | C->next = P; 22 | // update pointers 23 | P = C; 24 | C = N; 25 | } 26 | return P; 27 | } -------------------------------------------------------------------------------- /Day-06_LinkedList/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Detect cycle in Linkedlist | floyd cycle detection | [view](detect_cycle_list.cpp) 6 | 2 | Detect starting point of cycle | fast and slow pointers | [view](cycle_start.cpp) 7 | 3 | Check Palindrome | reverse from middle and check | [view](palindrome_list.cpp) 8 | 4 | Intersection in Y shaped List | cross traversal | [view](intersection_Y.cpp) 9 | 5 | Reverse in groups of K | addFirst, original, temp pointers | [view](reverse_groups_k.cpp) 10 | 6 | Flattening of List | merge 2 sorted lists, recursion | [view](flattening_list.cpp) 11 | 7 | Rotate List | connect loop and find break point | [view](rotate_list.cpp) -------------------------------------------------------------------------------- /Day-06_LinkedList/cycle_start.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/linked-list-cycle-ii/ 3 | */ 4 | 5 | // return the node where the cycle begins 6 | ListNode *detectCycle(ListNode *head) { 7 | ListNode *slow = head; 8 | ListNode *fast = head; 9 | 10 | while(fast && fast->next) { 11 | slow = slow->next; // 1 step 12 | fast = fast->next->next; // 2 steps 13 | 14 | // cycle detected 15 | if(slow == fast) { 16 | // move fast to the head 17 | fast = head; 18 | while(slow != fast) { 19 | slow = slow->next; 20 | fast = fast->next; 21 | } 22 | return slow; 23 | } 24 | } 25 | return NULL; 26 | } 27 | -------------------------------------------------------------------------------- /Day-06_LinkedList/detect_cycle_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/linked-list-cycle/ 3 | */ 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode(int x) : val(x), next(NULL) {} 11 | * }; 12 | */ 13 | 14 | bool hasCycle(ListNode *head) { 15 | ListNode *slow = head; 16 | ListNode *fast = head; 17 | 18 | while(fast && fast->next) { 19 | slow = slow->next; // 1 step 20 | fast = fast->next->next; // 2 steps 21 | 22 | if(slow == fast) 23 | return true; 24 | } 25 | return false; 26 | } -------------------------------------------------------------------------------- /Day-06_LinkedList/flattening_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/flattening-a-linked-list/1 3 | */ 4 | 5 | // helper function to merge 2 sorted lists 6 | Node *mergeLists(Node *l1, Node *l2) { 7 | // base cases 8 | if(!l1) 9 | return l2; 10 | if(!l2) 11 | return l1; 12 | // recursive calls 13 | if(l1->data <= l2->data) { 14 | l1->bottom = mergeLists(l1->bottom, l2); 15 | return l1; 16 | } 17 | else { 18 | l2->bottom = mergeLists(l1, l2->bottom); 19 | return l2; 20 | } 21 | } 22 | 23 | Node *flatten(Node *root) { 24 | // base case 25 | if(!root || !root->next) 26 | return root; 27 | // recursive call 28 | return mergeLists(root, flatten(root->next)); 29 | } 30 | -------------------------------------------------------------------------------- /Day-06_LinkedList/intersection_Y.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/intersection-of-two-linked-lists/ 3 | */ 4 | 5 | ListNode *getIntersectionNode(ListNode *headA, Listnode *headB) { 6 | ListNode *a = headA; 7 | ListNode *b = headB; 8 | 9 | while(a != b) { 10 | a = (a == NULL) ? headB : a->next; 11 | b = (b == NULL) ? headA : b->next; 12 | } 13 | return a; 14 | } 15 | -------------------------------------------------------------------------------- /Day-06_LinkedList/palindrome_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/palindrome-linked-list/ 3 | */ 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode() : val(0), next(nullptr) {} 11 | * ListNode(int x) : val(x), next(nullptr) {} 12 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 13 | * }; 14 | */ 15 | 16 | ListNode *reverse(Listnode *reverse) { 17 | ListNode *P = NULL; 18 | ListNode *C = head; 19 | ListNode *N; 20 | 21 | while(C) { 22 | N = C->next; 23 | C->next = P; 24 | P = C; 25 | C = N; 26 | } 27 | return P; 28 | } 29 | 30 | bool isPalindrome(ListNode *head) { 31 | ListNode *slow = head; 32 | ListNode *fast = head; 33 | 34 | // find middle of the linked list 35 | while(fast && fast->next) { 36 | slow = slow->next; 37 | fast = fast->next->next; 38 | } 39 | // move fast to head 40 | fast = head; 41 | slow = reverse(slow); 42 | 43 | while(slow) { 44 | if(slow->val != fast->val) 45 | return false; 46 | // move 1 step each 47 | slow = slow->next; 48 | fast = fast->next; 49 | } 50 | return true; 51 | } 52 | -------------------------------------------------------------------------------- /Day-06_LinkedList/reverse_groups_k.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/reverse-nodes-in-k-group/ 3 | */ 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode() : val(0), next(nullptr) {} 11 | * ListNode(int x) : val(x), next(nullptr) {} 12 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 13 | * }; 14 | */ 15 | class Solution { 16 | // temp head and tail 17 | ListNode *th = NULL, *tt = NULL; 18 | public: 19 | // helper function to calculate the size of the linked list 20 | int length(ListNode *head) { 21 | int size = 0; 22 | while(head) { 23 | size++; 24 | head = head->next; 25 | } 26 | return size; 27 | } 28 | 29 | // helper function to add node at the starting of the list 30 | void addFirst(ListNode *node) { 31 | if(th == NULL) 32 | th = tt = node; 33 | else { 34 | node->next = th; 35 | th = node; 36 | } 37 | } 38 | 39 | ListNode* reverseKGroup(ListNode* head, int k) { 40 | // edge cases 41 | if(!head || !head->next || k == 1) 42 | return head; 43 | // find the length of the list 44 | int size = length(head); 45 | ListNode *curr = head; 46 | 47 | // original head and tails for the final merged linked list 48 | ListNode *oh = NULL, *ot = NULL; 49 | 50 | while(size >= k) { 51 | int temp = k; 52 | // reverse the links of K nodes 53 | while(temp--) { 54 | // take the left most node 55 | ListNode *N = curr->next; 56 | // break the link 57 | curr->next = NULL; 58 | addFirst(curr); 59 | // update values for next iteration 60 | curr = N; 61 | } 62 | // first set of k reversed nodes 63 | if(!oh) { 64 | oh = th; 65 | ot = tt; 66 | } 67 | else { 68 | ot->next = th; 69 | ot = tt; 70 | } 71 | 72 | // reset th and tt 73 | th = tt = NULL; 74 | // decrease size 75 | size -= k; 76 | } 77 | // attach the remaining part: residual group of size < k 78 | if(size) 79 | ot->next = curr; 80 | return oh; 81 | } 82 | }; -------------------------------------------------------------------------------- /Day-06_LinkedList/rotate_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/rotate-list/description/ 3 | */ 4 | 5 | /** 6 | * Definition for singly-linked list. 7 | * struct ListNode { 8 | * int val; 9 | * ListNode *next; 10 | * ListNode() : val(0), next(nullptr) {} 11 | * ListNode(int x) : val(x), next(nullptr) {} 12 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 13 | * }; 14 | */ 15 | 16 | ListNode *rotateRight(ListNode *head, int k) { 17 | // edge cases 18 | if(!head || !head->next || k == 0) 19 | return head; 20 | 21 | ListNode *curr = head; 22 | int len = 1; 23 | while(curr->next) { 24 | len++; 25 | curr = curr->next; 26 | } 27 | // curr is on the last node: connect it with the head to form a loop 28 | curr->next = head; 29 | k %= len; 30 | k = len - k; 31 | 32 | while(k--) 33 | curr = curr->next; 34 | 35 | // update the head node 36 | head = curr->next; 37 | // break the link 38 | curr->next = NULL; 39 | 40 | return head; 41 | } -------------------------------------------------------------------------------- /Day-07_Two_Pointers/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Copy List with random pointers | adjacent copy nodes | [view](clone_list.cpp) 6 | 2 | Three Sum 0 | sorting, 2 pointer approach | [view](Three_sum.cpp) 7 | 3 | Max consecutive ones | Kadane's algo | [view](max_consecutive_ones.cpp) 8 | 4 | remove duplicates in sorted array | 2 pointers | [view](remove_duplicates_sorted.cpp) 9 | 5 | Trapping Rainwater | 2 pointers, min(max_left, max_right) - arr[i] | [view](trapping_rainwater.cpp) -------------------------------------------------------------------------------- /Day-07_Two_Pointers/Three_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/3sum/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | vector> threeSum(vector& nums) { 8 | // base case: min 3 elements should be there 9 | if(nums.size() < 3) 10 | return {}; 11 | 12 | vector> result; 13 | sort(nums.begin(), nums.end()); 14 | 15 | for(int i = 0; i < nums.size() - 2; i++) { 16 | // edge case 17 | if(i > 0 and nums[i] == nums[i - 1]) 18 | continue; 19 | int left = i + 1, right = nums.size() - 1; 20 | while(left < right) { 21 | int sum = nums[i] + nums[left] + nums[right]; 22 | // now there are 3 cases 23 | if(sum == 0) { 24 | result.push_back({nums[i], nums[left], nums[right]}); 25 | left++; 26 | 27 | // avoid duplicates 28 | while(left < right and nums[left] == nums[left - 1]) 29 | left++; 30 | // this is a major blunder 31 | /*while(left < right and nums[right] == nums[right + 1]) 32 | right--; 33 | */ 34 | } 35 | else if(sum < 0) 36 | left++; 37 | else 38 | right--; 39 | } 40 | } 41 | return result; 42 | } 43 | }; -------------------------------------------------------------------------------- /Day-07_Two_Pointers/clone_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/copy-list-with-random-pointer/ 3 | */ 4 | 5 | /* 6 | // Definition for a Node. 7 | class Node { 8 | public: 9 | int val; 10 | Node* next; 11 | Node* random; 12 | 13 | Node(int _val) { 14 | val = _val; 15 | next = NULL; 16 | random = NULL; 17 | } 18 | }; 19 | */ 20 | 21 | class Solution { 22 | public: 23 | // video solution link: https://youtu.be/_v8O9TZwKSU 24 | Node* copyRandomList(Node* head) { 25 | // create new nodes by inserting them in between the original nodes 26 | if(!head) 27 | return NULL; 28 | Node *curr = head; 29 | Node *temp; 30 | 31 | while(curr) { 32 | // store the next pointer 33 | temp = curr->next; 34 | // add new node 35 | curr->next = new Node(curr->val); 36 | // make new node point to next node 37 | curr->next->next = temp; 38 | curr = temp; 39 | } 40 | // copy the random pointers to the new nodes 41 | // for a node curr, curr->next is the newly created copy node 42 | curr = head; 43 | while(curr) { 44 | // random pointer could be NULL too. 45 | curr->next->random = curr->random ? curr->random->next : NULL; 46 | // move to the next original node 47 | curr = curr->next->next; 48 | } 49 | // separate the two lists and restore the links of the original linked list 50 | Node *original = head; 51 | Node *copy = head->next; 52 | Node *result_ptr = copy; 53 | 54 | while(original && copy) { 55 | // make original point to next original node 56 | original->next = copy->next; 57 | // make copy point to next copy node 58 | copy->next = copy->next ? copy->next->next : NULL; 59 | // move to the next nodes 60 | original = original->next; 61 | copy = copy->next; 62 | } 63 | return result_ptr; 64 | } 65 | }; -------------------------------------------------------------------------------- /Day-07_Two_Pointers/max_consecutive_ones.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/max-consecutive-ones/ 3 | */ 4 | 5 | int findMaxConsecutiveOnes(vector &nums) { 6 | int max_count = 0, count = 0; 7 | 8 | for(const int &x : nums) { 9 | if(x == 1) 10 | count++; 11 | else 12 | count = 0; 13 | 14 | max_count = max(max_count, count); 15 | } 16 | return max_count; 17 | } -------------------------------------------------------------------------------- /Day-07_Two_Pointers/remove_duplicates_sorted.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/remove-duplicates-from-sorted-array/ 3 | */ 4 | 5 | // return length of the array: in-place array of unique elements 6 | int removeDuplicates(vector &nums) { 7 | int n = nums.size(); 8 | 9 | if(n <= 1) 10 | return n; 11 | 12 | int i = 0; // pointer to track unique elements 13 | for(int j = 1; j < n; j++) { 14 | if(nums[j] != nums[i]) 15 | nums[++i] = nums[j]; 16 | } 17 | return i + 1; 18 | } -------------------------------------------------------------------------------- /Day-07_Two_Pointers/trapping_rainwater.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/trapping-rain-water/ 3 | */ 4 | 5 | 6 | int trappingWater(int arr[], int n){ 7 | // calculate the water stored on/ above each block 8 | // using 2 pointer approach 9 | int left = 0, right = n - 1; 10 | int max_left = 0, max_right = 0; 11 | int total = 0; 12 | 13 | while(left <= right) { 14 | // left one is the min height 15 | if(arr[left] < arr[right]) { 16 | // maintain max height from left 17 | if(arr[left] > max_left) 18 | max_left = arr[left]; // no water can be stored on this block 19 | else 20 | total += (max_left - arr[left]); // max capacity - cur height 21 | 22 | left++; 23 | } 24 | // right one is the min height 25 | else { 26 | // maintain max height from right 27 | if(arr[right] > max_right) 28 | max_right = arr[right]; // no water can be stored on this block 29 | else 30 | total += (max_right - arr[right]); // max capacity - cur height 31 | 32 | right--; 33 | } 34 | } 35 | return total; 36 | } -------------------------------------------------------------------------------- /Day-08_Greedy/N_meeting_one_room.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/n-meetings-in-one-room-1587115620/1 3 | */ 4 | 5 | // helper function to sort array in ascending order of finishing time 6 | static bool compare(pair &a, pair &b) { 7 | return a.second < b.second; 8 | } 9 | 10 | //Function to find the maximum number of meetings that can 11 | //be performed in a meeting room. 12 | int maxMeetings(int start[], int end[], int n) { 13 | // create a pair of starting, finishing time 14 | vector> arr(n); 15 | for(int i = 0; i < n; i++) 16 | arr[i] = make_pair(start[i], end[i]); 17 | 18 | // sort it in ascending order of finishing time: we want to complete activities which end at the earliest 19 | sort(arr.begin(), arr.end(), compare); 20 | 21 | int count = 1; // pick the first activity 22 | int ft = arr[0].second; // finishing time of first activity 23 | 24 | for(int i = 1; i < n; i++) { 25 | // take current activity if its starting time > finishing time of earlier chosen activity 26 | if(arr[i].first > ft) { 27 | count++; 28 | ft = arr[i].second; 29 | } 30 | } 31 | return count; 32 | } -------------------------------------------------------------------------------- /Day-08_Greedy/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Fractional Knapsack | sorting: value/weight | [view](fractional_knapsack.cpp) 6 | 2 | Coin Change | bottom-up dp | [view](coin_change.cpp) 7 | 3 | Job Sequencing | n-slots, job index in sorted array | [view](job_sequencing.cpp) 8 | 4 | Activity Selection | pick earliest finishing activity | [view](activity_selection.cpp) 9 | 5 | N Meetings in One Room | same as activity selection | [view](N_meeting_one_room.cpp) 10 | 6 | Minimum number of Railway Platforms | sorted: arrival vs dep times | [view](min_platforms_railway.cpp) -------------------------------------------------------------------------------- /Day-08_Greedy/activity_selection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/activity-selection-1587115620/1 3 | */ 4 | 5 | // helper function to sort the array in ascending order of ending day 6 | static bool compare(pair &a, pair &b) { 7 | return a.second < b.second; 8 | } 9 | 10 | //Function to find the maximum number of activities that can 11 | //be performed by a single person. 12 | int activitySelection(vector start, vector end, int n) { 13 | // create a pair of starting, ending day 14 | vector> arr(n); 15 | for(int i = 0; i < n; i++) 16 | arr[i] = make_pair(start[i], end[i]); 17 | 18 | // sort it in ascending order of ending day: we want to complete activity which end at the earliest 19 | sort(arr.begin(), arr.end(), compare); 20 | 21 | int count = 1; // pick the first activity 22 | int ft = arr[0].second; // finishing time of first activity 23 | 24 | for(int i = 1; i < n; i++) { 25 | // take current activity if its starting time > finishing time of earlier chosen activity 26 | if(arr[i].first > ft) { 27 | ft = arr[i].second; 28 | count++; 29 | } 30 | } 31 | return count; 32 | } -------------------------------------------------------------------------------- /Day-08_Greedy/coin_change.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/coin-change/ 3 | */ 4 | 5 | // DP Solution 6 | int coinChange(vector &coins, int amount) { 7 | vector dp(amount + 1, amount + 1); 8 | int n = coins.size(); 9 | // dp[i] stores the min coins required to make amount "i" 10 | // base case 11 | dp[0] = 0; 12 | // sort the coins vector 13 | sort(coins.begin(), coins.end()); 14 | // traverse the dp array 15 | for(int i = 1; i <= amount; i++) { 16 | // go through the coins with value <= i 17 | for(const int &c : coins) { 18 | if(c <= i) { 19 | int result = dp[i - c]; 20 | if(result != INT_MAX) 21 | dp[i] = min(dp[i], result + 1); 22 | } 23 | else // we are able to break since we sorted the coins vector 24 | break; 25 | } 26 | } 27 | return dp[amount] == INT_MAX ? -1 : dp[amount]; 28 | } -------------------------------------------------------------------------------- /Day-08_Greedy/fractional_knapsack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/fractional-knapsack-1587115620/1 3 | */ 4 | 5 | struct Item { 6 | int value; 7 | int weight; 8 | }; 9 | 10 | class Solution 11 | { 12 | public: 13 | // custom compare function based on higher ratio of value/weight. 14 | static bool compare(Item &a, Item &b) { 15 | return ((double)a.value / a.weight) > ((double)b.value / b.weight); 16 | } 17 | 18 | //Function to get the maximum total value in the knapsack. 19 | double fractionalKnapsack(int W, Item arr[], int n) { 20 | // Your code here 21 | sort(arr, arr + n, compare); 22 | 23 | int cur_w = 0; 24 | double max_val = 0; 25 | 26 | for(int i = 0; i < n; i++) { 27 | // current weight could be accomodated fully 28 | if(cur_w + arr[i].weight <= W) { 29 | cur_w += arr[i].weight; 30 | max_val += arr[i].value; 31 | } 32 | else { 33 | // add fraction of the weight value 34 | int remaining_w = W - cur_w; 35 | max_val += arr[i].value * ((double)remaining_w / arr[i].weight); 36 | break; 37 | } 38 | } 39 | return max_val; 40 | } 41 | 42 | }; -------------------------------------------------------------------------------- /Day-08_Greedy/job_sequencing.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/job-sequencing-problem-1587115620/1# 3 | */ 4 | 5 | // helper function to sort the array in descending order of profit 6 | static bool compare(Job &a, Job &b) { 7 | return a.profit > b.profit; 8 | } 9 | 10 | 11 | //Function to find the maximum profit and the number of jobs done. 12 | vector JobScheduling(Job arr[], int n) { 13 | // your code here 14 | // sort in descending order of profit 15 | sort(arr, arr + n, compare); 16 | int result[n]; // store the index of the job 17 | int slot[n] = {0}; // deadline based free slots 18 | // for a job with deadline 3, it can only be stored at index 0,1,2 ie. upto deadline - 1 19 | 20 | for(int i = 0; i < n; i++) { 21 | // find a free slot to accomodate this job 22 | for(int j = min(n, arr[i].dead) - 1; j >= 0; j--) { 23 | // free slot is found 24 | if(slot[j] == 0) { 25 | result[j] = i; // store the job index in the sorted array 26 | slot[j] = 1; // indicates slot is occupied 27 | break; 28 | } 29 | } 30 | } 31 | int jobs = 0, profit = 0; 32 | for(int i = 0; i < n; i++) { 33 | if(slot[i] == 1) { 34 | // the job is taken into account ie. finished before deadline 35 | jobs++; // increment number of jobs 36 | profit += arr[result[i]].profit; 37 | } 38 | } 39 | return {jobs, profit}; 40 | } 41 | }; -------------------------------------------------------------------------------- /Day-08_Greedy/min_platforms_railway.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/minimum-platforms-1587115620/1# 3 | */ 4 | 5 | //Function to find the minimum number of platforms required at the 6 | //railway station such that no train waits. 7 | int findPlatform(int arr[], int dep[], int n) { 8 | // Your code here 9 | // sort both the arrival and departure times in ascending order 10 | sort(arr, arr + n); 11 | sort(dep, dep + n); 12 | 13 | int count = 1; // platform needed for the arrival of the first train 14 | int max_count = 1; 15 | // use Two pointer approach 16 | int i = 1, j = 0; 17 | 18 | while(i < n && j < n) { 19 | // current train arrives before prev train's departure 20 | if(arr[i] <= dep[j]) { 21 | count++; 22 | i++; 23 | } 24 | // one platform gets free as current train arrives after the departure of prev train 25 | else { 26 | count--; 27 | j++; 28 | } 29 | // update max platforms needed at a particular moment of time 30 | if(count > max_count) 31 | max_count = count; 32 | } 33 | return max_count; 34 | } 35 | -------------------------------------------------------------------------------- /Day-09_Recursion/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Subset Sums | Recursion {pick, dont pick} element | [view](subset_sums.cpp) 6 | 2 | Generate Subsets without duplicates | ds of size 1,2...n | [view](subset_sum_duplicates.cpp) 7 | 3 | Combination sum with repetition | recursion with 2 options | [view](combination_sum.cpp) 8 | 4 | Combination sum without repetition | recursion with 2 options; avoid duplicates | [view](combination_sum_without_rep.cpp) 9 | 5 | Palindromic Partitions | Backtracking: left part-palindrome | [view](palindrome_partitioning.cpp) 10 | 6 | Kth Permutation sequence | fix one number; find interval | [view](kth_permutation.cpp) -------------------------------------------------------------------------------- /Day-09_Recursion/combination_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/combination-sum/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // helper function to find valid combinations 8 | void find_combinations(vector &candidates, int target, int idx, vector &path, vector> &results) { 9 | // base case 10 | if(idx == candidates.size()) { 11 | // the current path is a valid subset 12 | if(target == 0) 13 | results.push_back(path); 14 | return; 15 | } 16 | // we have 2 options:- 17 | // option-1: pick element with repetition 18 | if(candidates[idx] <= target) { 19 | // add the element in the path 20 | path.push_back(candidates[idx]); 21 | // recursive call with the same index: allows repetition of the current element 22 | find_combinations(candidates, target - candidates[idx], idx, path, results); 23 | // unpick the element for the next iteration: backtracking 24 | path.pop_back(); 25 | } 26 | // option-2: dont pick the current element 27 | find_combinations(candidates, target, idx + 1, path, results); 28 | } 29 | 30 | vector> combinationSum(vector& candidates, int target) { 31 | vector> results; 32 | vector path; 33 | 34 | find_combinations(candidates, target, 0, path, results); 35 | return results; 36 | } 37 | }; -------------------------------------------------------------------------------- /Day-09_Recursion/combination_sum_without_rep.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/combination-sum-ii/ 3 | */ 4 | 5 | class Solution { 6 | int prev_candidate; 7 | public: 8 | Solution() { 9 | // to avoid duplicates 10 | prev_candidate = 60; 11 | } 12 | // helper function to find valid combinations 13 | void find_combinations(vector &candidates, int target, int idx, vector &path, vector> &results) { 14 | // base case 15 | if(idx == candidates.size()) { 16 | // the current path is a valid subset 17 | if(target == 0) 18 | results.push_back(path); 19 | return; 20 | } 21 | // we have 2 options:- 22 | // option-1: pick element without repetition 23 | if(candidates[idx] <= target && prev_candidate != candidates[idx]) { 24 | // add the element in the path 25 | path.push_back(candidates[idx]); 26 | // recursive call with the next index: doesn't allow repetition of the current element 27 | find_combinations(candidates, target - candidates[idx], idx + 1, path, results); 28 | // update prev candidate 29 | prev_candidate = candidates[idx]; 30 | // unpick the element for the next iteration: backtracking 31 | path.pop_back(); 32 | } 33 | // option-2: dont pick the current element 34 | find_combinations(candidates, target, idx + 1, path, results); 35 | } 36 | 37 | vector> combinationSum2(vector& candidates, int target) { 38 | vector> results; 39 | vector path; 40 | 41 | sort(candidates.begin(), candidates.end()); 42 | 43 | find_combinations(candidates, target, 0, path, results); 44 | return results; 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /Day-09_Recursion/generate_Subsequences_bitMasking.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | for an array of size = n 3 | Total number of subarrays/substrings = n(n+1)/2 4 | Total number of subsequences = 2^n - 1 5 | Note: 6 | Every subarray is a subsequence. 7 | Subsequences is a generalization of subarrays. 8 | */ 9 | // given an array generate all the subsequences. 10 | 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | void allSubseq(int *arr, int n) { 16 | int size = pow(2, n); 17 | for(int i = 1; i < size; i++) { 18 | int temp = i; 19 | int j = 0; 20 | 21 | while(temp) { 22 | if(temp & 1) 23 | cout << arr[j] << " "; 24 | j++; 25 | temp >>= 1; 26 | } 27 | cout << endl; 28 | } 29 | } 30 | 31 | int main() { 32 | int arr[] = {1, 2, 3, 4}; 33 | int n = sizeof(arr) / sizeof(arr[0]); 34 | 35 | cout << "All non-empty subsequences: " << endl; 36 | allSubseq(arr, n); 37 | } -------------------------------------------------------------------------------- /Day-09_Recursion/kth_permutation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/permutation-sequence/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | string getPermutation(int n, int k) { 8 | vector numbers; 9 | int fact = 1; 10 | // compute (n-1)! --> permutations when the first number is fixed 11 | for(int i = 1; i < n; i++) { 12 | fact *= i; 13 | numbers.push_back(i); 14 | } 15 | numbers.push_back(n); 16 | string result = ""; 17 | k--; // to convert into 0 based indexing 18 | while(true) { 19 | result = result + to_string(numbers[k/ fact]); 20 | // remove this number 21 | numbers.erase(numbers.begin() + k / fact); 22 | // if all the numbers are used 23 | if(numbers.empty()) 24 | break; 25 | 26 | // update k and fact 27 | k = k % fact; 28 | fact = fact / numbers.size(); 29 | } 30 | return result; 31 | } 32 | }; -------------------------------------------------------------------------------- /Day-09_Recursion/palindrome_partitioning.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/palindrome-partitioning/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // helper function to check for palindrome 8 | bool isPalindrome(string &s, int start, int end) { 9 | while(start <= end) { 10 | if(s[start++] != s[end--]) 11 | return false; 12 | } 13 | return true; 14 | } 15 | 16 | // helper function to find palindromic partitions 17 | void partition_helper(string &s, int idx, vector &path, vector> &results) { 18 | // base case: all the partitions are done, last '|' after the last char of string 19 | if(idx == s.size()) { 20 | results.push_back(path); 21 | return; 22 | } 23 | // recursive calls 24 | for(int i = idx; s[i]; i++) { 25 | // make partitions if possible and make recursive call on the rem string 26 | if(isPalindrome(s, idx, i)) { 27 | // add left palindromic part of the partition 28 | path.push_back(s.substr(idx, i - idx + 1)); 29 | // recursive call: on the right part of the partition made right now 30 | partition_helper(s, i + 1, path, results); 31 | // remove the added substr for next iteration: backtracking 32 | path.pop_back(); 33 | } 34 | } 35 | } 36 | 37 | vector> partition(string s) { 38 | vector> results; 39 | vector path; 40 | 41 | partition_helper(s, 0, path, results); 42 | return results; 43 | } 44 | }; -------------------------------------------------------------------------------- /Day-09_Recursion/subset_sum_duplicates.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Solving: https://leetcode.com/problems/subsets-ii/ 3 | */ 4 | 5 | // find subsets with ds size = 1 then 2 .... n 6 | void find_subsets(vector &nums, int idx, int n, vector &ds, vector> &results) { 7 | results.push_back(ds); 8 | for(int i = idx; i < n; i++) { 9 | // avoid duplicates 10 | if(i > idx && nums[i] == nums[i - 1]) 11 | continue; 12 | ds.push_back(nums[i]); 13 | // recursive call 14 | find_subsets(nums, i + 1, n, ds, results); 15 | // backtracking: remove the added element 16 | ds.pop_back(); 17 | } 18 | } 19 | 20 | vector> subsetsWithDup(vector& nums) { 21 | vector> results; 22 | vector ds; 23 | int n = nums.size(); 24 | sort(nums.begin(), nums.end()); 25 | find_subsets(nums, 0, n, ds, results); 26 | 27 | return results; 28 | } -------------------------------------------------------------------------------- /Day-09_Recursion/subset_sums.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/subset-sums2234/1 3 | */ 4 | 5 | void subsets_helper(vector &arr, int idx, int sum, int n, vector &results) { 6 | // base case 7 | if(idx == n) { 8 | results.push_back(sum); 9 | return; 10 | } 11 | // recursive calls: there are 2 options 12 | // pick the current element 13 | subsets_helper(arr, idx + 1, sum + arr[idx], n, results); 14 | // do-not pick the current element 15 | subsets_helper(arr, idx + 1, sum, n, results); 16 | 17 | } 18 | 19 | vector subsetSums(vector arr, int n) { 20 | // Write Your Code here 21 | vector results; 22 | subsets_helper(arr, 0, 0, n, results); 23 | // sort the vector 24 | sort(results.begin(), results.end()); 25 | 26 | return results; 27 | } -------------------------------------------------------------------------------- /Day-10_Backtracking/M_coloring.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/m-coloring-problem-1587115620/1# 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | bool isPossible(int node, int color[], bool graph[101][101], int V, int col) { 9 | // check the colors of the adjacent node 10 | for(int k = 0; k < V; k++) { 11 | // k should not be the node itself 12 | // there should exist an edg betweent the node and its adjacent node 13 | // the adjacent node is marked with the same color: condition violated 14 | if(k != node && graph[k][node] == 1 && color[k] == col) 15 | return false; 16 | } 17 | return true; 18 | } 19 | 20 | bool solve(int node, int color[], int m, int V, bool graph[101][101]) { 21 | // base case 22 | if(node == V) 23 | return true; 24 | 25 | // try every color from 1 to m 26 | for(int i = 1; i <= m; i++) { 27 | // check if it is possible to color "node" with color "i" 28 | if(isPossible(node, color, graph, V, i)) { 29 | // mark the color of the node 30 | color[node] = i; 31 | // recursive call: if it is possible no need to unmark the color 32 | if(solve(node + 1, color, m, V, graph)) 33 | return true; 34 | else 35 | // unmark the node for further iterations: backtracking 36 | color[node] = 0; 37 | } 38 | } 39 | return false; 40 | } 41 | 42 | //Function to determine if graph can be coloured with at most M colours such 43 | //that no two adjacent vertices of graph are coloured with same colour. 44 | bool graphColoring(bool graph[101][101], int m, int V) { 45 | // your code here 46 | int color[V] = {0}; 47 | 48 | if(solve(0, color, m, V, graph)) 49 | return true; 50 | return false; 51 | } 52 | 53 | int main() { 54 | int t; 55 | cin >> t; 56 | while (t--) { 57 | int n, m, e; 58 | cin >> n >> m >> e; 59 | int i; 60 | bool graph[101][101]; 61 | for (i = 0; i < n; i++) { 62 | memset(graph[i], 0, sizeof(graph[i])); 63 | } 64 | for (i = 0; i < e; i++) { 65 | int a, b; 66 | cin >> a >> b; 67 | graph[a - 1][b - 1] = 1; 68 | graph[b - 1][a - 1] = 1; 69 | } 70 | cout << graphColoring(graph, m, n) << endl; 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /Day-10_Backtracking/N_Queens.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/n-queens/ 3 | */ 4 | 5 | // helper function to check if the queen is safe to be placed 6 | bool isQueenSafe(vector &chess, int row, int col) { 7 | // check vertically upwards 8 | for(int i = row - 1, j = col; i >= 0; i--) { 9 | // a queen is already there to attack 10 | if(chess[i][j] == 'Q') 11 | return false; 12 | } 13 | // check left upward diagonal 14 | for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { 15 | // a queen is already there to attack 16 | if(chess[i][j] == 'Q') 17 | return false; 18 | } 19 | // check right upward diagonal 20 | for(int i = row - 1, j = col + 1; i >= 0 && j < chess[0].size(); i--, j++) { 21 | // a queen is already there to attack 22 | if(chess[i][j] == 'Q') 23 | return false; 24 | } 25 | // it is safe to place the queen at chess[row][col] 26 | return true; 27 | } 28 | 29 | // helper function to place 1 Queen in one row 30 | void printNQueens(vector &chess, vector> &results, int row, int n) { 31 | // base case: all rows are processed ie. all the queens are placed 32 | if(row == n) { 33 | results.push_back(chess); 34 | return; 35 | } 36 | 37 | // go through all the options of placing queen in a column of a row 38 | for(int col = 0; col < n; col++) { 39 | // place the queen if it is a safe position 40 | if(isQueenSafe(chess, row, col)) { 41 | // place the queen 42 | chess[row][col] = 'Q'; 43 | // recursive call: place queen in the next row 44 | printNQueens(chess, results, row + 1, n); 45 | // restore original config: remove the Queen for further iterations: backtracking 46 | chess[row][col] = '.'; 47 | } 48 | } 49 | } 50 | 51 | vector> solveNQueens(int n) { 52 | vector> results; 53 | // chess board of nxn with all values: '.' 54 | vector chess(n, string(n, '.')); 55 | // start placing queen in 0th ie. first row 56 | printNQueens(chess, results, 0, n); 57 | 58 | return results; 59 | } -------------------------------------------------------------------------------- /Day-10_Backtracking/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | All permutations of an array | fixing first position, all swaps | [view](print_permutations.cpp) 6 | 2 | N Queens | backtracking, finding safe position {3 directions} | [view](N_Queens.cpp) 7 | 3 | Rat in a Maze | bactracking, dfs calls in 4 directions | [view](rat_maze.cpp) 8 | 4 | Sudoku Solver | bactracking, finding correct value | [view](sudoku_solver.cpp) 9 | 5 | M Coloring | backtracking, trying all possible colors | [view](M_coloring.cpp) 10 | 6 | Word Break | backtracking, check partition | [view](word_break.cpp) -------------------------------------------------------------------------------- /Day-10_Backtracking/print_permutations.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/permutations/ 3 | */ 4 | 5 | // backtracking helper function 6 | void permute_helper(vector> &results, vector &nums, int idx) { 7 | // base case 8 | if(idx == (int)nums.size() - 1) { 9 | results.push_back(nums); 10 | return; 11 | } 12 | // recursive calls: fix the first position by all swaps 13 | for(int i = idx; i < (int)nums.size(); i++) { 14 | // fix the ith element at the start and permute over the remaining part 15 | swap(nums[i], nums[idx]); 16 | permute_helper(results, nums, idx + 1); 17 | // unswap for the next iteration: backtracking 18 | swap(nums[i], nums[idx]); 19 | } 20 | } 21 | 22 | vector> permute(vector &nums) { 23 | vector> results; 24 | permute_helper(results, nums, 0); 25 | 26 | return results; 27 | } -------------------------------------------------------------------------------- /Day-10_Backtracking/rat_maze.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/rat-in-a-maze-problem/1 3 | */ 4 | 5 | class Solution{ 6 | // lexographical order: DLRU 7 | int row_dirs[4] = {1, 0, 0, -1}; 8 | int col_dirs[4] = {0, -1, 1, 0}; 9 | string dir = "DLRU"; 10 | 11 | public: 12 | 13 | void dfs_helper(int sr, int sc, vector> &matrix, int n, string moves, 14 | vector &results) { 15 | // base case: destination is reached 16 | if(sr == n - 1 && sc == n - 1) { 17 | results.push_back(moves); 18 | return; 19 | } 20 | // base case: boundary conditions + cell not reachable + cell already visited 21 | if(sr < 0 || sc < 0 || sr >= n || sc >= n || matrix[sr][sc] == 0) 22 | return; 23 | 24 | // mark cur cell to be visited 25 | matrix[sr][sc] = 0; 26 | 27 | for(int idx = 0; idx < 4; idx++) { 28 | // recursive call: 4 directions 29 | dfs_helper(sr + row_dirs[idx], sc + col_dirs[idx], matrix, n, moves + dir[idx], results); 30 | } 31 | // unmark cell for further iterations: backtracking 32 | matrix[sr][sc] = 1; 33 | } 34 | 35 | vector findPath(vector> &matrix, int n) { 36 | // Your code goes here 37 | vector results; 38 | 39 | if(matrix[0][0] == 1 && matrix[n - 1][n - 1] == 1) 40 | dfs_helper(0, 0, matrix, n, "", results); 41 | 42 | return results; 43 | } 44 | }; -------------------------------------------------------------------------------- /Day-10_Backtracking/sudoku_solver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/sudoku-solver/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | void solveSudoku(vector>& board) { 8 | solve(board); 9 | } 10 | 11 | // helper function to check is char ch can be placed at (r, c) 12 | bool isValid(vector> &board, int r, int c, char ch) { 13 | for(int i = 0; i < 9; i++) { 14 | // check-1: already present in column c 15 | if(board[i][c] == ch) 16 | return false; 17 | // check-2: already present in row r 18 | if(board[r][i] == ch) 19 | return false; 20 | // check-3: 3x3 submatrix 21 | if(board[3 * (r / 3) + i / 3][3 * (c / 3) + i % 3] == ch) 22 | return false; 23 | } 24 | return true; 25 | } 26 | 27 | bool solve(vector> &board) { 28 | for(int i = 0; i < 9; i++) { 29 | for(int j = 0; j < 9; j++) { 30 | // find the empty position 31 | if(board[i][j] == '.') { 32 | // try putting in the correct value at this position 33 | for(char c = '1'; c <= '9'; c++) { 34 | if(isValid(board, i, j, c)) { 35 | // place the value 36 | board[i][j] = c; 37 | // recursive call 38 | // if valid number is placed no need to backtrack: fix the value at that position and move ahead 39 | if(solve(board) == true) 40 | return true; 41 | else 42 | // unplace the value for further iterations: backtracking 43 | board[i][j] = '.'; 44 | } 45 | } 46 | return false; 47 | } 48 | } 49 | } 50 | // everything is filled up: sudoku completed 51 | return true; // false was never returned 52 | } 53 | }; -------------------------------------------------------------------------------- /Day-10_Backtracking/word_break.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/word-break1352/1# 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | int wordBreak(string A, vector &B); 9 | 10 | int main(){ 11 | int t; 12 | cin>>t; 13 | while(t--){ 14 | int n; 15 | cin>>n; 16 | vector dict; 17 | for(int i=0;i>S; 20 | dict.push_back(S); 21 | } 22 | string line; 23 | cin>>line; 24 | cout< &dict, unordered_map &dp) { 31 | // base case 32 | if(s.empty()) 33 | return 1; 34 | // value is pre-computed: memoization 35 | if(dp[s] != 0) 36 | return dp[s]; 37 | int size = s.size(); 38 | // recursive calls on all possible substrings of s 39 | for(int i = 1; i <= size; i++) { 40 | bool found = false; 41 | string ss = s.substr(0, i); // substring of size i 42 | // now search this substring in the dictionary 43 | for(string &d : dict) { 44 | if(ss.compare(d) == 0) { 45 | found = true; 46 | break; 47 | } 48 | } 49 | // recursive call on the remaining substring 50 | if(found == 1 && solve(s.substr(i, size - i), dict, dp) == 1) 51 | return dp[s] = 1; 52 | } 53 | return dp[s] = 0; 54 | } 55 | 56 | int wordBreak(string s, vector &dict) { 57 | //code here 58 | unordered_map dp; 59 | // dp[string] = 1; if string is present in the dictionary 60 | // by default dp[string] = 0; 61 | return solve(s, dict, dp) == 1 ? 1 : 0; 62 | } -------------------------------------------------------------------------------- /Day-11_Binary_Search/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Median of 2 Sorted Arrays | Binary Search: Contribution size of smaller vector | [view](median_2_sortedArrays.cpp) 6 | 2 | Kth element of 2 Sorted Arrays | Binary Search: contribution size of k | [view](kth_2_sortedArrays.cpp) 7 | 3 | Allocate min pages | monotonic search space of min possible max upper bound | [view](allocate_min_pages.cpp) 8 | 4 | Aggressive Cows | monotonic search space of min separation | [view](aggressive_cows.cpp) 9 | 5 | Search Rotated | 2 parts Binary Search | [view](search_rotated.cpp) 10 | 6 | Single Element | odd, even index; left part shrinkage | [view](single_element.cpp) 11 | 7 | Median in Row sorted matrix | count of left part of sorted array; upper_bound | [view](median_row_sorted.cpp) 12 | 8 | Nth Root | epsilon difference estimation | [view](nth_root.cpp) -------------------------------------------------------------------------------- /Day-11_Binary_Search/aggressive_cows.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://www.spoj.com/problems/AGGRCOW/ 3 | */ 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | // greedy helper function to place cows with min separation = mid 9 | bool isPossible(int *arr, int n, int c, int min_sep) { 10 | // place the cow at the first position 11 | int prev_cow = arr[0], count = 1; 12 | for(int i = 1; i < n; i++) { 13 | if(arr[i] - prev_cow >= min_sep) { 14 | count++; 15 | prev_cow = arr[i]; 16 | // all the cows are placed 17 | if(count == c) 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | // find the largest min. distance between 2 cows 25 | int find(int *arr, int n, int c) { 26 | int start = 0, end = arr[n - 1] - arr[0]; 27 | int max_sep = 0; 28 | 29 | while(start <= end) { 30 | int mid = start + (end - start) / 2; 31 | if(isPossible(arr, n, c, mid)) { 32 | max_sep = mid; 33 | start = mid + 1; 34 | } 35 | else 36 | end = mid - 1; 37 | } 38 | return max_sep; 39 | } 40 | 41 | int main() { 42 | 43 | int T, n, c; 44 | cin >> T; 45 | 46 | while(T--) { 47 | cin >> n >> c; 48 | int arr[n]; 49 | for(int i = 0; i < n; i++) 50 | cin >> arr[i]; 51 | 52 | sort(arr, arr + n); 53 | cout << find(arr, n, c) << endl; 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /Day-11_Binary_Search/allocate_min_pages.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/allocate-minimum-number-of-pages0937/1# 3 | */ 4 | #include 5 | using namespace std; 6 | 7 | class Solution 8 | { 9 | public: 10 | // helper function: greedy approach: give max possible load to each student 11 | bool isPossible(int *arr, int n, int m, int cur_min) { 12 | int students = 1; 13 | int pages_read = 0; 14 | 15 | for(int i = 0; i < n; ) { 16 | // assign pages to the current student 17 | if(pages_read + arr[i] <= cur_min) { 18 | pages_read += arr[i]; 19 | i++; 20 | } 21 | else { 22 | // assign pages to the new student; 23 | students++; 24 | pages_read = 0; 25 | // condition check 26 | if(students > m) 27 | return false; 28 | } 29 | } 30 | return true; 31 | } 32 | 33 | int findPages(int arr[], int n, int m) { 34 | //code here 35 | // edge case: students are more than the number of books 36 | if(m > n) 37 | return -1; 38 | 39 | int result = INT_MAX; 40 | // count the total number of pages 41 | int sum = 0; 42 | for(int i = 0; i < n; i++) 43 | sum += arr[i]; 44 | 45 | // apply binary search 46 | int start = *max_element(arr, arr + n); 47 | int end = sum; 48 | 49 | while(start <= end) { 50 | int mid = start + (end - start) / 2; 51 | // each student reads atmost mid number of pages [max upper_bound] 52 | if(isPossible(arr, n, m, mid)) { 53 | result = min(result, mid); 54 | end = mid - 1; 55 | } 56 | else 57 | start = mid + 1; 58 | } 59 | return result; 60 | } 61 | }; 62 | 63 | int main() { 64 | int t; 65 | cin>>t; 66 | while(t--){ 67 | int n; 68 | cin>>n; 69 | int A[n]; 70 | for(int i=0;i>A[i]; 72 | } 73 | int m; 74 | cin>>m; 75 | Solution ob; 76 | cout << ob.findPages(A, n, m) << endl; 77 | } 78 | return 0; 79 | } -------------------------------------------------------------------------------- /Day-11_Binary_Search/kth_2_sortedArrays.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/k-th-element-of-two-sorted-array1317/1 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | class Solution{ 9 | public: 10 | int kthElement(int arr1[], int arr2[], int n1, int n2, int k) { 11 | // we will calculate the contribution size of the smaller array 12 | if(n1 > n2) 13 | return kthElement(arr2, arr1, n2, n1, k); 14 | 15 | // monotonic search space for binary search 16 | /* 17 | edge case: you can't always pick 0 elements from arr1 and n2 elements from arr2 18 | if k > n2 then u need to pick atleast k - n2 from arr1 since we need to pick k elements overall 19 | */ 20 | int start = max(0, k - n2), end = min(k, n1); 21 | 22 | while(start <= end) { 23 | // contribution size in each array 24 | // to compute left half of the final merged array, we need k elements 25 | int mid1 = start + (end - start) / 2; 26 | int mid2 = k - mid1; 27 | 28 | // 4 variables to check the validity of partition 29 | // max values in the left part of array 30 | int max1 = mid1 == 0 ? INT_MIN : arr1[mid1 - 1]; 31 | int max2 = mid2 == 0 ? INT_MIN : arr2[mid2 - 1]; 32 | 33 | // min values in the right part of array 34 | int min1 = mid1 == n1 ? INT_MAX : arr1[mid1]; 35 | int min2 = mid2 == n2 ? INT_MAX : arr2[mid2]; 36 | 37 | // elements on the left part <= elements on the right part for the partition to be valid 38 | // max1 <= min1 is implied as the array is sorted 39 | if(max1 <= min2 && max2 <= min1) { 40 | return max(max1, max2); 41 | } 42 | // consider min2 before max1, dont consider max1 for now 43 | // decrease the contribution size of smaller array 44 | else if(max1 > min2) 45 | end = mid1 - 1; 46 | else 47 | start = mid1 + 1; 48 | } 49 | return -1; 50 | } 51 | }; 52 | 53 | int main() 54 | { 55 | int t; 56 | cin>>t; 57 | while(t--){ 58 | int n,m,k; 59 | cin>>n>>m>>k; 60 | int arr1[n],arr2[m]; 61 | for(int i=0;i>arr1[i]; 63 | for(int i=0;i>arr2[i]; 65 | 66 | Solution ob; 67 | cout << ob.kthElement(arr1, arr2, n, m, k)<& nums1, vector& nums2) { 8 | int n1 = nums1.size(); 9 | int n2 = nums2.size(); 10 | // we will calculate the contribution size of the smaller vector 11 | if(n1 > n2) 12 | return findMedianSortedArrays(nums2, nums1); 13 | 14 | // monotonic search space for binary search 15 | int start = 0, end = n1; 16 | 17 | while(start <= end) { 18 | // contribution size in each array 19 | // to compute left half of the final merged array, we need (n1 + n2 + 1) / 2 elements. 20 | int mid1 = start + (end - start) / 2; // contrib size of nums1 = mid elements towards the final merged left half 21 | int mid2 = (n1 + n2 + 1) / 2 - mid1; 22 | 23 | // 4 variables to check the validity of the partition 24 | // max values in the left part of each vector, handle corner cases 25 | int max1 = (mid1 == 0) ? INT_MIN : nums1[mid1 - 1]; 26 | int max2 = (mid2 == 0) ? INT_MIN : nums2[mid2 - 1]; 27 | 28 | // min values in the right part of each vector, handle corner cases 29 | int min1 = (mid1 == n1) ? INT_MAX : nums1[mid1]; 30 | int min2 = (mid2 == n2) ? INT_MAX : nums2[mid2]; 31 | 32 | // elements on left part should be <= elements on the right part, for the partition to be valid 33 | // max1 <= min1 is impied as the vector is sorted 34 | if(max1 <= min2 and max2 <= min1) { 35 | // odd number of elements 36 | if((n1 + n2) % 2 == 1) 37 | return (double)max(max1, max2); 38 | else 39 | return (double)(min(min1, min2) + max(max1, max2)) / 2; 40 | } 41 | // consider min2 first before max1, dont consider max1 for now 42 | // decrease the contribution size of smaller vector 43 | else if(max1 > min2) 44 | end = mid1 - 1; 45 | else 46 | start = mid1 + 1; 47 | } 48 | return -1; 49 | } 50 | }; -------------------------------------------------------------------------------- /Day-11_Binary_Search/median_row_sorted.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/median-in-a-row-wise-sorted-matrix1527/1 3 | */ 4 | 5 | class Solution{ 6 | public: 7 | // helper function to find count of elements <= mid in a row 8 | int countSmallerThanEqualToMid(vector &row, int n, int key) { 9 | int start = 0, end = n - 1; 10 | while(start <= end) { 11 | int mid = start + (end - start) / 2; 12 | if(row[mid] <= key) 13 | start = mid + 1; 14 | else 15 | end = mid - 1; 16 | } 17 | return start; 18 | } 19 | 20 | int median(vector> &matrix, int r, int c){ 21 | // code here 22 | // monotonic search space over possible matrix median value 23 | int start = 0, end = 2000; 24 | // apply binary search 25 | while(start <= end) { 26 | int mid = start + (end - start) / 2; 27 | int count = 0; // <= mid (left part of final sorted merged array) 28 | // go through each row 29 | for(int i = 0; i < r; i++) { 30 | //count += countSmallerThanEqualToMid(matrix[i], r, mid); 31 | count += (upper_bound(matrix[i].begin(), matrix[i].end(), mid) - matrix[i].begin()); 32 | } 33 | // expand the left portion 34 | if(count <= (r * c) / 2) 35 | start = mid + 1; 36 | else 37 | end = mid - 1; 38 | } 39 | return start; 40 | } 41 | }; -------------------------------------------------------------------------------- /Day-11_Binary_Search/nth_root.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Find nth root of a number m upto p decimal places. 3 | */ 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | // multiply num n times 10 | double multiply(double num, int n) { 11 | double ans = 1.0; 12 | while(n--) 13 | ans *= num; 14 | 15 | return ans; 16 | } 17 | 18 | void getNthRoot(int n, int m, int p) { 19 | double start = 1, end = m; 20 | double eps = pow(10, -p); 21 | 22 | while((end - start) > eps) { 23 | double mid = start + (end - start) / 2; 24 | if(multiply(mid, n) < m) 25 | start = mid; 26 | else 27 | end = mid; 28 | } 29 | 30 | cout << "estimated ans:"; 31 | cout << start << " " << end << endl; 32 | cout << "actual ans:"; 33 | cout << pow(m, (double)(1.0 / (double)n)); 34 | } 35 | 36 | int main() { 37 | 38 | int n, m, p; 39 | cin >> n >> m >> p; 40 | 41 | getNthRoot(n, m, p); 42 | 43 | return 0; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Day-11_Binary_Search/search_rotated.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/search-in-rotated-sorted-array/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | class Solution { 8 | public: 9 | int search(vector& nums, int target) { 10 | int start = 0, end = nums.size() - 1; 11 | 12 | while(start <= end) { 13 | int mid = start + (end - start) / 2; 14 | 15 | if(target == nums[mid]) 16 | return mid; 17 | 18 | if(nums[mid] >= nums[start]) { 19 | // part 1 of the array 20 | // check if target lies in the first part 21 | if(target >= nums[start] and target < nums[mid]) 22 | end = mid - 1; 23 | else 24 | start = mid + 1; 25 | } 26 | else { 27 | // part 2 of the array 28 | if(target > nums[mid] and target <= nums[end]) 29 | start = mid + 1; 30 | else 31 | end = mid - 1; 32 | } 33 | } 34 | return -1; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /Day-11_Binary_Search/single_element.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/single-element-in-a-sorted-array/ 3 | */ 4 | 5 | // Time complexity of xor approach: O(n) 6 | 7 | class Solution { 8 | public: 9 | /* 10 | check condition for the left part: 11 | 1st instance --> even index then check at next index that number is there or not 12 | 2nd instance --> odd index then check at prev index that number is there or not 13 | 14 | use ^ 15 | mid = 4 is even so we need the next index ie. 5 which is 4 ^ 1 ==> 100 ^ 1 = 101 ==> 5 16 | mid = 5 is odd so we need the prev index ie. 4 which is 5 ^ 1 ==> 101 ^ 1 = 100 ==> 4 17 | */ 18 | int singleNonDuplicate(vector& nums) { 19 | // if the single element is at the last position 20 | int start = 0, end = nums.size() - 2; 21 | while(start <= end) { 22 | int mid = start + (end - start) / 2; 23 | // left part so move to the right 24 | if(nums[mid] == nums[mid ^ 1]) 25 | start = mid + 1; 26 | else 27 | end = mid - 1; 28 | } 29 | return nums[start]; 30 | } 31 | }; -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Power of 2 | n&(n-1) == 0 | [view](powerOf2.cpp) 6 | 2 | Counting Bits | DP, counting bits in every number | [view](countingBits.cpp) 7 | 3 | Count Total Set Bits | f(n)=x*2^(x-1)+(n-2^x+1)+f(n-2^x) | [view](count_total_set_bits.cpp) 8 | 4 | Find MSB | one by one set all the bits | [view](find_MSB.cpp) 9 | 5 | Division of 2 numbers | subtract highest multiple; leftshift | [view](divide_numbers.cpp) 10 | 6 | Power Set-1 | vector, char included/excluded | [view](power_set_vector.cpp) 11 | 7 | Power Set-2 | recursion, char included/excluded | [view](power_set_recursion.cpp) 12 | 8 | Power Set-3 (Generate all subsequences) | Bit manipulation | [view](power_set_bit.cpp) 13 | 9 | Sqaure using Bit | Left shift + recursion | [view](square_bit.cpp) -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/count_total_set_bits.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/count-total-set-bits-1587115620/1 3 | */ 4 | 5 | class Solution{ 6 | public: 7 | // n: input to count the number of set bits 8 | //Function to return sum of count of set bits in the integers from 1 to n. 9 | 10 | /* 11 | recursive solution 12 | x*2^(x-1) --> total set bits in group (nearest power of 2) 13 | for the above group MSB will be 0 14 | for the remaining numbers not part of the group: MSB will be 1 15 | count of those MSB bits = n - 2^x + 1 16 | now we need to count set bits in the remaining numbers after removing their MSB 17 | 18 | // recursive function: f(n) = x*2^(x-1) + (n - 2^x + 1) + f(n - 2^x) 19 | 20 | Note: 21 | 2^x = (1 << x) 22 | */ 23 | 24 | // helper function to find the greatest power of 2 <= n 25 | int largestPowerOf2(int n) { 26 | int x = 0; 27 | while((1 << x) <= n) 28 | x++; 29 | 30 | return x - 1; 31 | } 32 | 33 | int countSetBits(int n) { 34 | // edge case 35 | if(n == 0) 36 | return 0; 37 | 38 | int x = largestPowerOf2(n); 39 | int bitsInGroup = x * (1 << (x - 1)); 40 | int msb_rem = n - (1 << x) + 1; 41 | int smaller_prob = n - (1 << x); 42 | 43 | return bitsInGroup + msb_rem + countSetBits(smaller_prob); 44 | } 45 | }; -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/countingBits.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/counting-bits/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // DP Solution 8 | vector countBits(int n) { 9 | // edge case 10 | if(n == 0) 11 | return {0}; 12 | 13 | vector dp(n + 1); 14 | // base cases 15 | dp[0] = 0; // number of set bits in 0 16 | dp[1] = 1; // number of set bits in 1 17 | 18 | for(int i = 2; i <= n; i++) { 19 | // odd number 20 | if(i & 1) 21 | dp[i] = dp[i / 2] + 1; 22 | // even number 23 | dp[i] = dp[i / 2]; 24 | } 25 | return dp; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/divide_numbers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/divide-two-integers/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | int divide(int dividend, int divisor) { 8 | // edge case 9 | if(dividend == INT_MIN && divisor == -1) 10 | return INT_MAX; 11 | 12 | long dvd = labs(dividend), dvs = labs(divisor), result = 0; 13 | int sign = dividend > 0 ^ divisor > 0 ? -1 : 1; 14 | // while dividend is >= divisor, we can keep subtracting it 15 | while(dvd >= dvs) { 16 | long temp = dvs, m = 1; 17 | // finding the greatest value of divisor to be subtracted 18 | while((temp << 1) <= dvd) { 19 | temp <<= 1; 20 | m <<= 1; 21 | } 22 | // subtract the max multiple of divisor 23 | dvd -= temp; 24 | result += m; 25 | } 26 | return sign * result; 27 | } 28 | }; -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/find_MSB.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://www.codingninjas.com/codestudio/problems/find-msb-in-o-1_1112570?leftPanelTab=2 3 | */ 4 | 5 | /* 6 | Time Complexity: O(1) solution to find the nearest power of 2 <= n 7 | Space complexity: O(1) 8 | */ 9 | 10 | #include 11 | using namespace std; 12 | 13 | int findMSB(int n) { 14 | 15 | n = n | n >> 1; 16 | n = n | n >> 2; 17 | n = n | n >> 4; 18 | n = n | n >> 8; 19 | n = n | n >> 16; 20 | 21 | n = n + 1; 22 | 23 | return (n >> 1); 24 | } 25 | 26 | int main() { 27 | 28 | int n; 29 | cin >> n; 30 | 31 | cout << findMSB(n) << endl; 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/powerOf2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/power-of-2-1587115620/1 3 | */ 4 | 5 | bool isPowerOfTwo(long long n) { 6 | if(n == 0) 7 | return false; 8 | 9 | return (n & (n - 1)) == 0; 10 | } -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/power_set_bit.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/power-set4302/1# 3 | */ 4 | 5 | vector AllPossibleStrings(string s){ 6 | // Code here 7 | vector results; 8 | int n = (int)s.size(); 9 | // go through binary representation from 1 to 2^n 10 | for(int i = 1; i < (1 << n); i++) { 11 | string res = ""; 12 | int temp = i, j = 0; 13 | while(temp) { 14 | if(temp & 1) 15 | res += s[j]; 16 | j++; 17 | temp >>= 1; 18 | } 19 | // don't include the empty substring 20 | if(!res.empty()) 21 | results.push_back(res); 22 | } 23 | // lexographic order of results 24 | sort(results.begin(), results.end()); 25 | return results; 26 | } -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/power_set_recursion.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/power-set4302/1# 3 | */ 4 | 5 | void generateSubstrings(string s, vector &results, int idx = 0, string ans = "") { 6 | // base case 7 | if(idx == s.size()) { 8 | // don't include empty substring 9 | if(ans != "") 10 | results.push_back(ans); 11 | return; 12 | } 13 | // recursive calls: 14 | // exclude the current element 15 | generateSubstrings(s, results, idx + 1, ans); 16 | // include the current element 17 | generateSubstrings(s, results, idx + 1, ans + s[idx]); 18 | } 19 | 20 | 21 | vector AllPossibleStrings(string s){ 22 | // Code here 23 | vector results; 24 | generateSubstrings(s, results); 25 | sort(results.begin(), results.end()); 26 | return results; 27 | } -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/power_set_vector.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/power-set4302/1# 3 | */ 4 | 5 | vector generateSubstrings(string s) { 6 | // base case: empty substring when no char is selected 7 | if(s.empty()) 8 | return {""}; // vector of size 1 having empty string 9 | 10 | // extract the first char 11 | char ch = s[0]; 12 | // get the remaining string 13 | string rem_s = s.substr(1); 14 | // recursive calls 15 | vector results = generateSubstrings(rem_s); 16 | vector my_results; 17 | // first char is not included 18 | for(string &str : results) 19 | my_results.push_back("" + str); 20 | // first char is included 21 | for(string &str : results) 22 | my_results.push_back(ch + str); 23 | 24 | return my_results; 25 | } 26 | 27 | vector AllPossibleStrings(string s) { 28 | // Code here 29 | vector results = generateSubstrings(s); 30 | results.erase(results.begin()); // remove the empty substring from power set 31 | sort(results.begin(), results.end()); 32 | 33 | return results; 34 | } -------------------------------------------------------------------------------- /Day-12_Bit_Manipulation/square_bit.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://www.geeksforgeeks.org/calculate-square-of-a-number-without-using-and-pow/ 3 | Calculate square of a number without using *, / and pow() 4 | */ 5 | 6 | #include 7 | using namespace std; 8 | /* 9 | If n is even, it can be written as 10 | n = 2*x 11 | n2 = (2*x)^2 = 4*x^2 12 | If n is odd, it can be written as 13 | n = 2*x + 1 14 | n2 = (2*x + 1)^2 = 4*x^2 + 4*x + 1 15 | */ 16 | int square(int n) { 17 | // base case 18 | if(n == 0) 19 | return 0; 20 | 21 | // negative numbers 22 | if(n < 0) 23 | n = -n; 24 | 25 | // get floor(n / 2) using right shift operator 26 | int x = n >> 1; 27 | 28 | // recursive calls: 29 | // case-1: n is odd 30 | if(n & 1) 31 | return ((square(x) << 2) + (x << 2) + 1); 32 | // case-2: n is even 33 | else 34 | return (square(x) << 2); 35 | 36 | /* 37 | x << 2 is same as x * 4 38 | */ 39 | } 40 | 41 | int main() { 42 | 43 | int n; 44 | cin >> n; 45 | 46 | cout << square(n); 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Next Greater Element-1 | add elements from right to left | [view](next_greater_element_1.cpp) 6 | 2 | Next Greater Element-2 (circular array) | unroll: 2*n-1 NGE| [view](next_greater_element_2.cpp) 7 | 3 | Balanced Parenthesis | stack of closing brackets; switch case | [view](balanced_parenthesis.cpp) 8 | 4 | Implement stack using arrays | fixed sized array with top pointer | [view](stack_array.cpp) 9 | 5 | Implement queue using arrays | fixed sized array with front and rear pointers | [view](queue_array.cpp) 10 | 6 | Implement stack using 1 queue | size-1 times push front and pop | [view](stack_using_queue.cpp) 11 | 7 | Implement queue using 2 stacks | input, output stack; all operations from output stack | [view](queue_using_stack.cpp) -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/balanced_parenthesis.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/valid-parentheses/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | bool isValid(string str) { 8 | stack s; 9 | // for every opening bracket push the corresponding closing bracket 10 | for(const char &ch : str) { 11 | switch(ch) { 12 | case '(': 13 | s.push(')'); 14 | break; 15 | case '{': 16 | s.push('}'); 17 | break; 18 | case '[': 19 | s.push(']'); 20 | break; 21 | default: 22 | // closing bracket is encountered 23 | // no opening bracket exists 24 | if(s.empty()) 25 | return false; 26 | // matching bracket is found: pop it and continue 27 | else if(ch == s.top()) 28 | s.pop(); 29 | else 30 | return false; 31 | break; 32 | } 33 | } 34 | // some extra brackets could have been left out 35 | // for valid parenthesis, stack must be empty 36 | return s.empty(); 37 | } 38 | }; -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/next_greater_element_1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/next-greater-element-i/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | vector nextGreaterElement(vector& nums1, vector& nums2) { 8 | unordered_map m; // {element : next greater element} 9 | stack s; // store indices 10 | int n = (int)nums2.size(); 11 | // traverse from right to left 12 | for(int i = n - 1; i >= 0; i--) { 13 | // pop stack elements if current element is greater than top of stack 14 | while(!s.empty() && nums2[i] >= nums2[s.top()]) 15 | s.pop(); 16 | 17 | m[nums2[i]] = s.empty() ? -1 : nums2[s.top()]; 18 | // push the current element on the stack 19 | s.push(i); 20 | } 21 | vector results; 22 | for(int &x : nums1) 23 | results.push_back(m[x]); 24 | return results; 25 | } 26 | }; -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/next_greater_element_2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/next-greater-element-ii/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | vector nextGreaterElements(vector& arr) { 8 | int n = arr.size(); 9 | vector result(n); // to store the result 10 | stack s; // to store the indices of the next greater number. 11 | // we are not storing numbers because of duplicates 12 | 13 | for(int i = 2 * n - 1; i >= 0; i--) { 14 | while(!s.empty() and arr[s.top()] <= arr[i % n]) { 15 | s.pop(); 16 | } 17 | result[i % n] = (s.empty() ? -1 : arr[s.top()]); 18 | // push the current index on the stack 19 | s.push(i % n); 20 | } 21 | return result; 22 | } 23 | }; -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/queue_array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/implement-queue-using-array/1/ 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | struct QueueNode 9 | { 10 | int data; 11 | QueueNode *next; 12 | }; 13 | 14 | class MyQueue { 15 | private: 16 | int arr[100005]; 17 | int front; 18 | int rear; 19 | 20 | public : 21 | MyQueue(){front=0;rear=0;} 22 | void push(int); 23 | int pop(); 24 | }; 25 | 26 | int main() 27 | { 28 | int T; 29 | cin>>T; 30 | while(T--) 31 | { 32 | MyQueue *sq = new MyQueue(); 33 | 34 | int Q; 35 | cin>>Q; 36 | while(Q--){ 37 | int QueryType=0; 38 | cin>>QueryType; 39 | if(QueryType==1) 40 | { 41 | int a; 42 | cin>>a; 43 | sq->push(a); 44 | }else if(QueryType==2){ 45 | cout<pop()<<" "; 46 | 47 | } 48 | } 49 | cout<= 100005) 58 | return; 59 | arr[rear++] = x; 60 | } 61 | 62 | //Function to pop an element from queue and return that element. 63 | int MyQueue :: pop() { 64 | // Your Code 65 | return front == rear ? -1 : arr[front++]; 66 | } 67 | -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/queue_using_stack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/implement-queue-using-stacks/ 3 | */ 4 | 5 | class MyQueue { 6 | public: 7 | // IMPLEMENTATION USING TWO STACKS: all operations would be performed on the output stack 8 | /* 9 | Amortized O(1) push and pop operations 10 | */ 11 | /** Initialize your data structure here. */ 12 | stack input, output; 13 | MyQueue() { 14 | 15 | } 16 | 17 | /** Push element x to the back of queue. */ 18 | void push(int x) { 19 | input.push(x); 20 | } 21 | 22 | /** Removes the element from in front of queue and returns that element. */ 23 | int pop() { 24 | int e; // top element that needs to be returned 25 | // move elements from input to output 26 | if(output.empty()) { 27 | while(!input.empty()) { 28 | output.push(input.top()); 29 | input.pop(); 30 | } 31 | } 32 | e = output.top(); 33 | output.pop(); 34 | return e; 35 | } 36 | 37 | /** Get the front element. */ 38 | int peek() { 39 | // move elements from input to output 40 | if(output.empty()) { 41 | while(!input.empty()) { 42 | output.push(input.top()); 43 | input.pop(); 44 | } 45 | } 46 | return output.top(); 47 | } 48 | 49 | /** Returns whether the queue is empty. */ 50 | bool empty() { 51 | return input.empty() && output.empty(); 52 | } 53 | }; 54 | 55 | /** 56 | * Your MyQueue object will be instantiated and called as such: 57 | * MyQueue* obj = new MyQueue(); 58 | * obj->push(x); 59 | * int param_2 = obj->pop(); 60 | * int param_3 = obj->peek(); 61 | * bool param_4 = obj->empty(); 62 | */ 63 | -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/stack_array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/implement-stack-using-array/1 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | class MyStack 9 | { 10 | private: 11 | int arr[1000]; 12 | int top; 13 | public: 14 | MyStack(){top=-1;} 15 | int pop(); 16 | void push(int); 17 | }; 18 | 19 | 20 | int main() 21 | { 22 | 23 | int T; 24 | cin>>T; 25 | while(T--) 26 | { 27 | MyStack *sq = new MyStack(); 28 | 29 | int Q; 30 | cin>>Q; 31 | while(Q--){ 32 | int QueryType=0; 33 | cin>>QueryType; 34 | if(QueryType==1) 35 | { 36 | int a; 37 | cin>>a; 38 | sq->push(a); 39 | }else if(QueryType==2){ 40 | cout<pop()<<" "; 41 | 42 | } 43 | } 44 | cout<= 1000) 53 | return; 54 | arr[++top] = x; 55 | } 56 | 57 | //Function to remove an item from top of the stack. 58 | int MyStack :: pop() { 59 | // Your Code 60 | return top == -1 ? -1 : arr[top--]; 61 | } 62 | -------------------------------------------------------------------------------- /Day-13_Stacks_Queues/stack_using_queue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/implement-stack-using-queues/solution/ 3 | */ 4 | 5 | class MyStack { 6 | public: 7 | // IMPLEMENTATION USINIG A SINGLE QUEUE 8 | /** Initialize your data structure here. */ 9 | queue q; 10 | MyStack() { 11 | } 12 | 13 | /** Push element x onto stack. */ 14 | void push(int x) { 15 | q.push(x); 16 | // pop size - 1 elements and push them at the back 17 | // this ensures the current element added t the end of the queue comes to the front 18 | int size = q.size(); 19 | for(int i = 0; i < size - 1; i++) { 20 | q.push(q.front()); 21 | q.pop(); 22 | } 23 | } 24 | 25 | /** Removes the element on top of the stack and returns that element. */ 26 | int pop() { 27 | int front = q.front(); 28 | q.pop(); 29 | return front; 30 | } 31 | 32 | /** Get the top element. */ 33 | int top() { 34 | return q.front(); 35 | } 36 | 37 | /** Returns whether the stack is empty. */ 38 | bool empty() { 39 | return q.empty(); 40 | } 41 | }; 42 | 43 | /** 44 | * Your MyStack object will be instantiated and called as such: 45 | * MyStack* obj = new MyStack(); 46 | * obj->push(x); 47 | * int param_2 = obj->pop(); 48 | * int param_3 = obj->top(); 49 | * bool param_4 = obj->empty(); 50 | */ -------------------------------------------------------------------------------- /Day-14_Stacks/LRU_cache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/lru-cache/ 3 | */ 4 | 5 | // Doubly linked list node 6 | class Node { 7 | public: 8 | int key; 9 | int value; 10 | Node *next; 11 | Node *prev; 12 | 13 | // param ctor 14 | Node(int key, int value) { 15 | this->key = key; 16 | this->value = value; 17 | } 18 | }; 19 | 20 | class LRUCache { 21 | /* 22 | NOTATION: The nodes from left to right are the latest used ones 23 | The nearest node to the tail ie. the right-most node is the least recently used one 24 | */ 25 | Node *head = new Node(-1, -1); // dummy head node 26 | Node *tail = new Node(-1, -1); // dummy tail node 27 | 28 | int capacity; // total size of the cache allowed 29 | // indicates the location address of the nodes present in the cache 30 | unordered_map m; // {key -> node pointer} 31 | public: 32 | 33 | LRUCache(int capacity) { 34 | this->capacity = capacity; 35 | // connect head with tail and vice-versa 36 | head->next = tail; 37 | tail->prev = head; 38 | } 39 | 40 | // helper function to add a node just after the head node 41 | void addNode(Node *node) { 42 | node->next = head->next; 43 | node->prev = head; 44 | head->next = node; 45 | node->next->prev = node; 46 | } 47 | 48 | // helper function to delete node from the tail node 49 | void deleteNode(Node *node) { 50 | Node *prev_node = node->prev; 51 | prev_node->next = node->next; 52 | node->next->prev = prev_node; 53 | } 54 | 55 | int get(int key) { 56 | // check if the node exists in the cache 57 | if(m.find(key) != m.end()) { 58 | Node *result_node = m[key]; 59 | int result_val = result_node->value; 60 | // now this node becomes the latest used node 61 | // delete the entry from cache ie. unordered_map 62 | m.erase(key); 63 | // delete the node from DLL 64 | deleteNode(result_node); 65 | // add the node after the head 66 | addNode(result_node); 67 | // add the entry {with new node address} in the cache ie. unordered_map 68 | m[key] = head->next; 69 | return result_val; 70 | } 71 | // the key doesn't exist in the cache 72 | return -1; 73 | } 74 | 75 | void put(int key, int value) { 76 | // check if node exists in the cache: delete it since we have to insert it again 77 | if(m.find(key) != m.end()) { 78 | Node *result_node = m[key]; 79 | // delete the entry from cache 80 | m.erase(key); 81 | // delete the node from DLL 82 | deleteNode(result_node); 83 | } 84 | // remove the last frequently used node if capacity is at max 85 | if(m.size() == capacity) { 86 | // remove the least recently used node 87 | // ie. the node closest to the tail (right-most node) 88 | // delete the entry from cache 89 | m.erase(tail->prev->key); 90 | // delete the node from DLL 91 | deleteNode(tail->prev); 92 | } 93 | // add the node in DLL 94 | addNode(new Node(key, value)); 95 | // add the entry in cache 96 | m[key] = head->next; 97 | } 98 | }; 99 | 100 | /** 101 | * Your LRUCache object will be instantiated and called as such: 102 | * LRUCache* obj = new LRUCache(capacity); 103 | * int param_1 = obj->get(key); 104 | * obj->put(key,value); 105 | */ -------------------------------------------------------------------------------- /Day-14_Stacks/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Nearest Smaller Element | stack: left to right traversal | [view](nearest_smaller_element.cpp) 6 | 2 | LRU Cache | Hashing + DLL {latest used on left near head} | [view](LRU_cache.cpp) 7 | 3 | Rotten Oranges | BFS using queue | [view](rotten_oranges.cpp) 8 | 4 | Implement Min Stack (Easy version) | stack> | [view](min_stack.cpp) 9 | 5 | Get Min at Pop | 2 stacks | [view](get_min_pop.cpp) 10 | 6 | Sliding Window Maximum | Deque + sliding window | [view](sliding_window_max.cpp) 11 | 7 | Largest rectangle in Histogram | PSE + NSE to compute spanning width | [view](largest_rectangle_histogram_1.cpp) 12 | 8 | Largest rectangle in Histogram Efficient | 3 vars: i-->nse, top = height, below top = pse | [view](largest_rectangle_histogram_2.cpp) -------------------------------------------------------------------------------- /Day-14_Stacks/get_min_pop.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/get-min-at-pop/1/ 3 | */ 4 | #include 5 | using namespace std; 6 | 7 | // function declarations 8 | stack _push(int arr[],int n); 9 | void _getMinAtPop(stacks); 10 | 11 | //Function to push all the elements into the stack. 12 | stack _push(int arr[],int n) { 13 | // your code here 14 | stack s; 15 | for(int i = 0; i < n; i++) 16 | s.push(arr[i]); 17 | 18 | return s; 19 | } 20 | 21 | //Function to print minimum value in stack each time while popping. 22 | void _getMinAtPop(stack s) { 23 | // your code here 24 | vector arr; 25 | // add elements in the vector 26 | while(!s.empty()) { 27 | arr.push_back(s.top()); 28 | s.pop(); 29 | } 30 | stack minStack; 31 | // we just store the min values in the minStack and all the values in the actual stac 32 | 33 | int n = arr.size(); 34 | for(int i = n - 1; i >= 0; i--) { 35 | s.push(arr[i]); 36 | // add the last element in both the stacks 37 | // if value is lesser than minStack top, add in minStack 38 | if(minStack.empty() || arr[i] < minStack.top()) 39 | minStack.push(arr[i]); 40 | else 41 | minStack.push(minStack.top()); 42 | } 43 | // printing the elements of minStack 44 | while(!minStack.empty()) { 45 | cout << minStack.top() << " "; 46 | minStack.pop(); 47 | } 48 | cout << endl; 49 | } 50 | 51 | int main() { 52 | int t; 53 | cin>>t; 54 | while(t--) 55 | { 56 | int n; 57 | cin>>n; 58 | int arr[n]; 59 | for(int i=0;i>arr[i]; 61 | stackmys=_push(arr,n); 62 | _getMinAtPop(mys); 63 | 64 | 65 | 66 | } 67 | return 0; 68 | } -------------------------------------------------------------------------------- /Day-14_Stacks/largest_rectangle_histogram_1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://www.interviewbit.com/old/problems/largest-rectangle-in-histogram/ 3 | */ 4 | 5 | int Solution::largestRectangleArea(vector &arr) { 6 | int max_area = 0; 7 | int n = (int)arr.size(); 8 | 9 | int pse[n]; // previous smaller element on the left 10 | int nse[n]; // next smaller element on the right 11 | 12 | stack s; // store the indices of the elements: to calculate width later 13 | // compute previous smaller element 14 | for(int i = 0; i < n; i++) { 15 | while(!s.empty() && arr[s.top()] >= arr[i]) 16 | s.pop(); 17 | // store the index 18 | pse[i] = s.empty() ? -1 : s.top(); 19 | // push the current index in the stack 20 | s.push(i); 21 | } 22 | // empty the stack 23 | while(!s.empty()) 24 | s.pop(); 25 | 26 | // compute the next smaller element 27 | for(int i = n - 1; i >= 0; i--) { 28 | while(!s.empty() && arr[s.top()] >= arr[i]) 29 | s.pop(); 30 | 31 | // store the index 32 | nse[i] = s.empty() ? n : s.top(); 33 | // push the current index in the stack 34 | s.push(i); 35 | } 36 | 37 | // compute the max area of each block: by expanding it both sides 38 | // until strictly smaller height block is found 39 | int cur_area; 40 | for(int i = 0; i < n; i++) { 41 | cur_area = arr[i] * (nse[i] - pse[i] - 1); 42 | if(cur_area > max_area) 43 | max_area = cur_area; 44 | } 45 | return max_area; 46 | } 47 | -------------------------------------------------------------------------------- /Day-14_Stacks/largest_rectangle_histogram_2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/maximum-rectangular-area-in-a-histogram-1587115620/1/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | //Function to find largest rectangular area possible in a given histogram. 8 | long long getMaxArea(long long arr[], int n) { 9 | // Your code here 10 | stack s; 11 | long long max_area = 0, cur_area = 0; 12 | 13 | // i would be the index of nse for top of stack 14 | // the element below top of stack would be the pse 15 | // pse and nse are used to provide the width of the rectangle 16 | // edge cases: when s is empty ie pse doesn't exist we take pse to be 0 17 | // when nse doesn't exist we take nse to be n 18 | 19 | for(int i = 0; i <= n; i++) { 20 | // i == n will count for elements with no nse: so take nse = n 21 | while(!s.empty() && (i == n || arr[i] <= arr[s.top()])) { 22 | // i is the nse 23 | // pse is the element below top of stack 24 | // arr[tp] is the height 25 | // width = nse - pse - 1 26 | long long tp = s.top(); 27 | s.pop(); 28 | cur_area = arr[tp] * (s.empty() ? i : i - s.top() - 1); 29 | if(cur_area > max_area) 30 | max_area = cur_area; 31 | } 32 | // insert current index in the stack 33 | s.push(i); 34 | } 35 | return max_area; 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /Day-14_Stacks/min_stack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/min-stack/ 3 | */ 4 | 5 | class MinStack { 6 | stack> s; // {value, min_value} 7 | public: 8 | /** initialize your data structure here. */ 9 | MinStack() { 10 | 11 | } 12 | 13 | void push(int x) { 14 | if(s.empty()) 15 | s.push({x, x}); 16 | else 17 | s.push({x, min(x, s.top().second)}); 18 | } 19 | 20 | void pop() { 21 | if(!s.empty()) 22 | s.pop(); 23 | } 24 | 25 | int top() { 26 | return s.top().first; 27 | } 28 | 29 | int getMin() { 30 | return s.top().second; 31 | } 32 | }; 33 | 34 | /** 35 | * Your MinStack object will be instantiated and called as such: 36 | * MinStack* obj = new MinStack(); 37 | * obj->push(x); 38 | * obj->pop(); 39 | * int param_3 = obj->top(); 40 | * int param_4 = obj->getMin(); 41 | */ -------------------------------------------------------------------------------- /Day-14_Stacks/nearest_smaller_element.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://www.interviewbit.com/problems/nearest-smaller-element/ 3 | */ 4 | 5 | vector Solution::prevSmaller(vector &arr) { 6 | stack s; 7 | int n = (int)arr.size(); 8 | vector results(n); 9 | 10 | for(int i = 0; i < n; i++) { 11 | // pop elements from stack if arr[i] <= top of stack elements 12 | while(!s.empty() && arr[i] <= arr[s.top()]) 13 | s.pop(); 14 | results[i] = s.empty() ? -1 : arr[s.top()]; 15 | // insert the current element's index in the stack 16 | s.push(i); 17 | } 18 | return results; 19 | } -------------------------------------------------------------------------------- /Day-14_Stacks/rotten_oranges.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/rotting-oranges/ 3 | */ 4 | 5 | class Solution { 6 | // denotes the four neighbours of a grid cell 7 | int row_dirs[4] = {0, 0, -1, 1}; 8 | int col_dirs[4] = {-1, 1, 0, 0}; 9 | public: 10 | // BFS solution 11 | int orangesRotting(vector>& grid) { 12 | int rows = grid.size(), cols = grid[0].size(); 13 | queue> q; // to store the indices of the rotten oranges 14 | int fresh_oranges = 0, timer_count = 0; 15 | // initially insert all the indices with rotten oranges into the queue 16 | for(int i = 0; i < rows; i++) { 17 | for(int j = 0; j < cols; j++) { 18 | if(grid[i][j] == 2) 19 | q.push({i, j}); 20 | else if(grid[i][j]) 21 | fresh_oranges++; 22 | } 23 | } 24 | // if there are no fresh oranges, it will take 0 time. 25 | if(fresh_oranges == 0) 26 | return 0; 27 | // apply BFS 28 | while(!q.empty()) { 29 | int n = q.size(); 30 | while(n--) { 31 | auto [r, c] = q.front(); 32 | q.pop(); 33 | // impact oranges in 4 directions 34 | for(int itr = 0; itr < 4; itr++) { 35 | int new_r = r + row_dirs[itr]; 36 | int new_c = c + col_dirs[itr]; 37 | 38 | // we only make a call if the neighbour exist and is a fresh orange 39 | if(new_r < 0 || new_c < 0 || new_r >= rows || new_c >= cols || grid[new_r][new_c] != 1) 40 | continue; 41 | // mark the fresh orange as rotten 42 | grid[new_r][new_c] = 2; 43 | // reduce fresh oranges count by 1 44 | fresh_oranges--; 45 | // add the neighbor in the queue 46 | q.push({new_r, new_c}); 47 | } 48 | } 49 | timer_count++; 50 | } 51 | return fresh_oranges > 0 ? -1 : timer_count - 1; 52 | } 53 | }; -------------------------------------------------------------------------------- /Day-14_Stacks/sliding_window_max.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/maximum-of-all-subarrays-of-size-k3101/1/ 3 | */ 4 | 5 | #include 6 | using namespace std; 7 | 8 | class Solution { 9 | public: 10 | //Function to find maximum of each subarray of size k. 11 | vector max_of_subarrays(int *arr, int n, int k) { 12 | // your code here 13 | vector results; 14 | deque dq(k); // to store the indices of useful elements 15 | // front of the dq stores the index of the max window element 16 | 17 | // process the first window 18 | for(int i = 0; i < k; i++) { 19 | // remove element from back of dq if current element is greater than back element 20 | while(!dq.empty() && arr[i] >= arr[dq.back()]) 21 | dq.pop_back(); 22 | // push the current index at the end of deque 23 | dq.push_back(i); 24 | } 25 | // process the remaining elements 26 | for(int i = k; i < n; i++) { 27 | // add max of the prev window in results 28 | results.push_back(arr[dq.front()]); 29 | 30 | // remove the elements going out of window 31 | while(!dq.empty() && dq.front() <= i - k) 32 | dq.pop_front(); 33 | 34 | // remove the useless elements 35 | while(!dq.empty() && arr[i] >= arr[dq.back()]) 36 | dq.pop_back(); 37 | 38 | // add the current index at the end of deque 39 | dq.push_back(i); 40 | } 41 | // add max of last window 42 | results.push_back(arr[dq.front()]); 43 | return results; 44 | } 45 | }; 46 | 47 | int main() { 48 | 49 | int t; 50 | cin >> t; 51 | 52 | while(t--){ 53 | 54 | int n, k; 55 | cin >> n >> k; 56 | 57 | int arr[n]; 58 | for(int i = 0;i> arr[i]; 60 | Solution ob; 61 | vector res = ob.max_of_subarrays(arr, n, k); 62 | for (int i = 0; i < res.size (); i++) 63 | cout << res[i] << " "; 64 | cout << endl; 65 | } 66 | return 0; 67 | } -------------------------------------------------------------------------------- /Day-15_Strings/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Reverse Words in a string | stack + conditions | [view](reverse_words.cpp) 6 | 2 | Longest Palindromic Substring | Two pointer consecutive + 1 gap apart expansion | [view](longest_palindromic_substring.cpp) 7 | 3 | Roman to integer | map, subtract if cur < next | [view](roman_to_integer.cpp) 8 | 4 | Integer to Roman | Store the exception symbols like 1, 4, 5, 9, etc | [view](integer_to_roman.cpp) -------------------------------------------------------------------------------- /Day-15_Strings/integer_to_roman.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/integer-to-roman/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | string intToRoman(int num) { 8 | string result; 9 | string symbols[13] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; 10 | int val[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; 11 | 12 | for(int i = 0; num != 0; i++) { 13 | while(num >= val[i]) { 14 | num -= val[i]; 15 | result += symbols[i]; 16 | } 17 | } 18 | return result; 19 | } 20 | }; -------------------------------------------------------------------------------- /Day-15_Strings/longest_palindromic_substring.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/longest-palindromic-substring/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | void expandBothSides(string &s, int left, int right, int &start_idx, int &max_len, const int n) { 8 | // expand the palindrome on both sides if there is a match 9 | while(left >= 0 && right < n && s[left] == s[right]) { 10 | // keep the max len palindromic substring 11 | if(right - left + 1 > max_len) { 12 | start_idx = left; 13 | max_len = right - left + 1; 14 | } 15 | // expand the window 16 | left--; 17 | right++; 18 | } 19 | } 20 | 21 | string longestPalindrome(string &s) { 22 | const int n = (int)s.size(); 23 | int start_idx = 0; // starting index where the substring starts 24 | int max_len = 1; // single char is considered to be a substring 25 | int left, right; // 2 pointers 26 | 27 | for(int i = 1; i < n; i++) { 28 | // consecutive pointers _ _ 29 | left = i - 1; 30 | right = i; 31 | expandBothSides(s, left, right, start_idx, max_len, n); 32 | 33 | // pointers with 1 gap in between _x_ 34 | left = i - 1; 35 | right = i + 1; 36 | expandBothSides(s, left, right, start_idx, max_len, n); 37 | } 38 | return s.substr(start_idx, max_len); 39 | } 40 | }; -------------------------------------------------------------------------------- /Day-15_Strings/reverse_words.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/reverse-words-in-a-string/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | string reverseWords(string s) { 8 | stack st; 9 | string word; 10 | int n = s.size(); 11 | for(int i = 0; i < n; i++) { 12 | // leading spaces at the start 13 | if(word.empty()) { 14 | while(s[i] == ' ') 15 | i++; 16 | } 17 | // add the characters to the string word 18 | if(s[i] != ' ') 19 | word += s[i]; 20 | // push the words when space is encountered or i == (n - 1), for the last word 21 | if(s[i] == ' ' || i == n - 1) { 22 | if(!word.empty()) 23 | st.push(word); 24 | // reset string to store the next word 25 | word.clear(); 26 | } 27 | } 28 | word.clear(); 29 | while(!st.empty()) { 30 | word += st.top(); 31 | st.pop(); 32 | word += " "; 33 | } 34 | // remove the last added space 35 | word.pop_back(); 36 | return word; 37 | } 38 | }; -------------------------------------------------------------------------------- /Day-15_Strings/roman_to_integer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/roman-to-integer/ 3 | */ 4 | 5 | class Solution { 6 | unordered_map m = { 7 | {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, 8 | {'C', 100}, {'D', 500}, {'M', 1000} 9 | }; 10 | 11 | public: 12 | int romanToInt(string &s) { 13 | int result = 0, n = s.size(); 14 | int curr = m[s[0]]; 15 | for(int i = 0; i < n; i++) { 16 | // next will be 0 if we reach the end of the string 17 | int next = m[s[i + 1]]; 18 | if(curr < next) 19 | result -= curr; 20 | else 21 | result += curr; 22 | curr = next; 23 | } 24 | return result; 25 | } 26 | }; -------------------------------------------------------------------------------- /Day-17_Binary_Tree/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Inorder Traversal | iterative using stack | [view](inorder_traversal.cpp) 6 | 2 | Preorder Traversal | BFS, iterative using stack | [view](preorder_traversal.cpp) 7 | 3 | Postorder Traversal | BFS, reverse traversal | [view](postorder_traversal.cpp) 8 | 4 | Left View | leftmost node of each level | [view](left_view.cpp) 9 | 5 | Right View | rightmost node of each level | [view](right_view.cpp) 10 | 6 | Top View | first enc node at each horizontal distance | [view](top_view.cpp) 11 | 7 | Bottom View | last enc node at each horizontal distance | [view](bottom_view.cpp) -------------------------------------------------------------------------------- /Day-17_Binary_Tree/bottom_view.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/bottom-view-of-binary-tree/1 3 | */ 4 | 5 | vector bottomView(Node *root) { 6 | // base case 7 | if(!root) 8 | return {}; 9 | 10 | queue> q; {node, horizontal distance from the root node} 11 | q.push({root, 0}); 12 | map m; // {horizontal distance from the root node} 13 | // perform BFS: level order traversal 14 | while(!q.empty()) { 15 | Node *front = q.front().first; 16 | int distance = q.front().second; 17 | q.pop(); 18 | 19 | // overwrite the map 20 | m[distance] = front->data; 21 | // insert the children in the queue if they exist 22 | if(front->left) 23 | q.push({front->left, distance - 1}); 24 | if(front->right) 25 | q.push({front->right, distance + 1}); 26 | } 27 | // store node data values in the vector 28 | vector results; 29 | for(auto &p : m) 30 | results.push_back(p.second); 31 | 32 | return results; 33 | } -------------------------------------------------------------------------------- /Day-17_Binary_Tree/inorder_traversal.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-tree-inorder-traversal/ 3 | */ 4 | 5 | vector inorderTraversal(TreeNode *root) { 6 | vector results; 7 | stack s; 8 | 9 | // LNR 10 | while(!s.empty() || root) { 11 | // push all the left nodes 12 | while(root) { 13 | s.push(root); 14 | root = root->left; 15 | } 16 | // the last leftmost node is taken into account 17 | root = s.top(); 18 | s.pop(); 19 | results.push_back(root->val); 20 | // move to the right subtree of the current root node 21 | root = root->right; 22 | } 23 | return results; 24 | } -------------------------------------------------------------------------------- /Day-17_Binary_Tree/left_view.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/left-view-of-binary-tree/1 3 | */ 4 | 5 | // helper function to find the nodes visible from the left view 6 | void left_helper(Node *root, int level, int &max_level, vector &results) { 7 | // base case 8 | if(!root) 9 | return; 10 | 11 | // store the first encountered node (leftmost) at each new level 12 | if(level > max_level) { 13 | max_level = level; 14 | results.push_back(root->data); 15 | } 16 | // recursive calls: left subtree first 17 | left_helper(root->left, level + 1, max_level, results); 18 | left_helper(root->right, level + 1, max_level, results); 19 | } 20 | 21 | vector leftView(Node *root) { 22 | vector results; 23 | int max_level = -1; 24 | // call to the helper function 25 | left_helper(root, 0, max_level, results); 26 | 27 | return results; 28 | } -------------------------------------------------------------------------------- /Day-17_Binary_Tree/postorder_traversal.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-tree-postorder-traversal/ 3 | */ 4 | 5 | vector postorderTraversal(TreeNode *root) { 6 | // base case 7 | if(!root) 8 | return {}; 9 | 10 | vector results; 11 | stack s; 12 | s.push(root); 13 | // LRN: perform level order traversal 14 | while(!s.empty()) { 15 | TreeNode *front = s.top(); 16 | // add the data in the results 17 | results.push_back(front->val); 18 | // NRL (reverse of LRN) is performed 19 | // owing to LIFO rule, we push the left child first 20 | if(front->left) 21 | s.push(front->left); 22 | if(front->right) 23 | s.push(front->right); 24 | } 25 | reverse(results.begin(), results.end()); 26 | return results; 27 | } -------------------------------------------------------------------------------- /Day-17_Binary_Tree/preorder_traversal.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-tree-preorder-traversal/ 3 | */ 4 | 5 | vector preorderTraversal(TreeNode *root) { 6 | // base case 7 | if(!root) 8 | return {}; 9 | 10 | vector results; 11 | stack s; 12 | // NLR: so the root node is printed first 13 | s.push(root); 14 | 15 | // we follow level order traversal 16 | while(!s.empty()) { 17 | TreeNode *front = s.top(); 18 | s.pop(); 19 | // add the data in the results 20 | results.push_back(front->val); 21 | // add the right child first before the left one 22 | // owing to LIFO rule, the left child will be popped first 23 | if(front->right) 24 | s.push(front->right); 25 | if(front->left) 26 | s.push(front->left); 27 | } 28 | return results; 29 | } -------------------------------------------------------------------------------- /Day-17_Binary_Tree/right_view.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-tree-right-side-view/ 3 | */ 4 | 5 | void findRightView(TreeNode* root, int level, int &max_level, vector &results) { 6 | // base case 7 | if(!root) 8 | return; 9 | // new node (rightmost) of each new level 10 | if(level > max_level) { 11 | results.push_back(root->val); 12 | max_level = level; 13 | } 14 | 15 | // recursive calls: right subtree first 16 | findRightView(root->right, level + 1, max_level, results); 17 | findRightView(root->left, level + 1, max_level, results); 18 | } 19 | 20 | vector rightSideView(TreeNode* root) { 21 | int max_level = -1; 22 | vector results; 23 | findRightView(root, 0, max_level, results); 24 | 25 | return results; 26 | } -------------------------------------------------------------------------------- /Day-17_Binary_Tree/top_view.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/top-view-of-binary-tree/1 3 | */ 4 | 5 | // function to return list of nodes from left to right in Binary tree 6 | vector topView(Node *root) { 7 | // BFS level order traversal 8 | queue> q; // {node, horizontal distance from the root node} 9 | q.push({root, 0}); 10 | map m; // {horizontal distance from the root node, node value} 11 | // find the first encountered node at each vertical strips ie. horizontal distances from the root node 12 | while(!q.empty()) { 13 | Node *front = q.front().first; 14 | int distance = q.front().second; 15 | q.pop(); 16 | 17 | // we dont have any node at this horizontal distance 18 | if(m.find(distance) == m.end()) 19 | m[distance] = front->data; 20 | // add the children in the queue if they exist 21 | if(front->left) 22 | q.push({front->left, distance - 1}); 23 | if(front->right) 24 | q.push({front->right, distance + 1}); 25 | } 26 | // store the node data values 27 | vector results; 28 | for(auto &p : m) 29 | results.push_back(p.second); 30 | 31 | return results; 32 | } 33 | -------------------------------------------------------------------------------- /Day-18_Binary_Tree/LCA.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/ 3 | */ 4 | 5 | TreeNode* LCA(TreeNode *root, TreeNode *p, TreeNode *q) { 6 | // base case 7 | if(!root) 8 | return NULL; 9 | 10 | // a node is its own ancestor 11 | if(root == p || root == q) 12 | return root; 13 | // recursive calls: postorder traversal 14 | TreeNode *left = LCA(root->left, p, q); 15 | TreeNode *right = LCA(root->right, p, q); 16 | // root is the LCA if both the children nodes are found 17 | if(left && right) 18 | return root; 19 | else if(left) 20 | return left; 21 | else 22 | return right; 23 | } -------------------------------------------------------------------------------- /Day-18_Binary_Tree/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Level Order Traversal | BFS using queue | [view](levelorder.cpp) 6 | 2 | Level Order Spiral Traversal | flag variable, BFS using queue | [view](levelorder_spiral.cpp) 7 | 3 | Height of Tree | recursion, find max depth | [view](height_tree.cpp) 8 | 4 | Diameter of Tree | height, dia recursion with 3 cases | [view](diameter.cpp) 9 | 5 | Height balanced check | recursion, {height, bool} | [view](height_balanced.cpp) 10 | 6 | Identical Trees | simple step by step recursion | [view](identical_trees.cpp) 11 | 7 | LCA of 2 nodes | postorder recursion | [view](LCA.cpp) -------------------------------------------------------------------------------- /Day-18_Binary_Tree/diameter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/diameter-of-binary-tree/ 3 | */ 4 | 5 | /* 6 | diameter of tree = longest distance between any 2 nodes of the tree 7 | diameter could be the number of nodes between node of left subtree and node of right subtree. 8 | (inverted V shaped). 9 | We basically count the edges for the calculation of diameter. 10 | there are 3 cases: 11 | diameter passes through the root ==> height(left) + height(right) 12 | diameter lies in the left subtree ==> recursive function call 13 | diameter lies in the right subtree ==> recursive function call 14 | */ 15 | #define pii pair // {height, diameter} 16 | 17 | pii dia_helper(TreeNode *root) { 18 | // base case 19 | if(!root) 20 | return {0, 0}; 21 | 22 | // recursive calls: postorder traversal 23 | pii left = dia_helper(root->left); 24 | pii right = dia_helper(root->right); 25 | // calculate the height of the current node 26 | int height = max(left.first, right.first) + 1; 27 | // case-1: dia passes through the root 28 | int option1 = left.first + right.first; 29 | // case-2: dia lies in the left subtree 30 | int option2 = left.second; 31 | // case-3: dia lies in the right subtree 32 | int option3 = right.second; 33 | // we choose the max of these 3 options 34 | int diameter = max({option1, option2, option3}); 35 | 36 | return {height, diameter}; 37 | } 38 | 39 | int diameterOfBinaryTree(TreeNode *root) { 40 | return dia_helper(root).second; 41 | } -------------------------------------------------------------------------------- /Day-18_Binary_Tree/height_balanced.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/balanced-binary-tree/ 3 | */ 4 | 5 | /* 6 | For a tree to be height balanced, at every node: 7 | absolute difference between height of left and right subtrees should be <= 1 8 | abs(height(left) - height(right)) <= 1 9 | */ 10 | 11 | #define pii pair // {height, isBalanced = bool} 12 | 13 | pii balanced(TreeNode *root) { 14 | // base case 15 | if(!root) 16 | return {0, 1}; 17 | // recursive calls: postorder traversal 18 | pii left = balanced(root->left); 19 | pii right = balanced(root->right); 20 | // height of the current node 21 | int height = max(left.first, right.first) + 1; 22 | // is the current node balanced, same for left and right subtrees 23 | if(left.second && right.second && abs(left.first - right.first) <= 1) 24 | return {height, 1}; 25 | else 26 | return {height, 0}; 27 | } 28 | 29 | bool isBalanced(TreeNode *root) { 30 | return balanced(root).second; 31 | } 32 | -------------------------------------------------------------------------------- /Day-18_Binary_Tree/height_tree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/height-of-binary-tree/1 3 | */ 4 | 5 | int height(Node *root) { 6 | // base case 7 | if(!root) 8 | return 0; 9 | // recursive calls 10 | int left_h = height(root->left); 11 | int right_h = height(root->right); 12 | 13 | return max(left_h, right_h) + 1; 14 | } -------------------------------------------------------------------------------- /Day-18_Binary_Tree/identical_trees.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/same-tree/ 3 | */ 4 | 5 | bool isSame(TreeNode *p, TreeNode *q) { 6 | // base case 7 | if(!p && !q) 8 | return true; 9 | if(!p || !q) 10 | return false; 11 | if(p->val != q->val) 12 | return false; 13 | // recursive calls 14 | return isSame(p->left, q->left) && isSame(p->right, q->right); 15 | } -------------------------------------------------------------------------------- /Day-18_Binary_Tree/levelorder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-tree-level-order-traversal/ 3 | */ 4 | 5 | vector> levelOrder(TreeNode *root) { 6 | // edge case 7 | if(!root) 8 | return {}; 9 | 10 | vector> results; 11 | queue q; 12 | q.push(root); // push the root node 13 | // perform the level order traversal 14 | while(!q.empty()) { 15 | int n = q.size(); 16 | vector inter; 17 | while(n--) { 18 | TreeNode *front = q.front(); 19 | q.pop(); 20 | // push the data value in the vector 21 | inter.push_back(front->data); 22 | // add the children in the queue if they exist 23 | if(front->left) 24 | q.push(front->left); 25 | if(front->right) 26 | q.push(front->right); 27 | } 28 | results.push_back(inter); 29 | } 30 | return results; 31 | } -------------------------------------------------------------------------------- /Day-18_Binary_Tree/levelorder_spiral.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ 3 | */ 4 | 5 | vector> zigzagLevelOrder(TreeNode *root) { 6 | // edge case 7 | if(!root) 8 | return {}; 9 | 10 | vector> results; 11 | queue q; 12 | q.push(root); // push the root node 13 | bool left_to_right = true; 14 | // perform BFS: level order traversal 15 | while(!q.empty()) { 16 | int n = q.size(); 17 | vector inter(n); 18 | 19 | for(int i = 0; i < n; i++) { 20 | TreeNode *front = q.front(); 21 | q.pop(); 22 | // find the position to fill the node's value 23 | int idx = left_to_right ? i : n - 1 - i; 24 | // insert the node data value 25 | inter[idx] = front->val; 26 | // add the children in the queue if they exist 27 | if(front->left) 28 | q.push(front->left); 29 | if(front->right) 30 | q.push(front->right); 31 | } 32 | // reverse the order for the next level 33 | left_to_right = !left_to_right; 34 | results.push_back(inter); 35 | } 36 | return results; 37 | } -------------------------------------------------------------------------------- /Day-19_Binary_Tree/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Max Path Sum | recursion 4 cases, propagate max sum | [view](max_path_sum.cpp) 6 | 2 | Check Mirror / Symmetric Tree| recursion with conditions | [view](check_mirror.cpp) 7 | 3 | Check Mirror n-ary Tree | stack & queue | [view](mirror_n_ary.cpp) 8 | 4 | Flatten Tree into Linked List | Morris Traversal | [view](flatten_tree_list.cpp) 9 | 5 | Tree from inorder and preorder | div and conq type | [view](tree_in_preorder.cpp) 10 | 6 | Tree from inorder and postorder | div and conq type | [view](tree_in_postorder.cpp) -------------------------------------------------------------------------------- /Day-19_Binary_Tree/check_mirror.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/symmetric-tree/ 3 | */ 4 | 5 | // helper function for sequential comparison 6 | bool isMirror(TreeNode *ls, TreeNode *rs) { 7 | // base cases 8 | if(!ls && !rs) 9 | return true; 10 | if(!ls || !rs) 11 | return false; 12 | if(ls->val != rs->val) 13 | return false; 14 | // recursive calls 15 | return isMirror(ls->left, rs->right) && isMirror(ls->right, rs->left); 16 | } 17 | 18 | bool isSymmetric(TreeNode *root) { 19 | return isMirror(root, root); 20 | } -------------------------------------------------------------------------------- /Day-19_Binary_Tree/flatten_tree_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/ 3 | */ 4 | 5 | // Morris like traversal 6 | void flatten(TreeNode *root) { 7 | // edge case 8 | if(!root) 9 | return; 10 | 11 | while(root) { 12 | // connect left subtree to the right 13 | if(root->left) { 14 | TreeNode *leftRightMost = root->left; 15 | while(leftRightMost->right) 16 | leftRightMost = leftRightMost->right; 17 | // rewire the connections 18 | leftRightMost->right = root->right; 19 | root->right = root->left; 20 | root->left = NULL; 21 | } 22 | // move to the next node 23 | root = root->right; 24 | } 25 | } -------------------------------------------------------------------------------- /Day-19_Binary_Tree/max_path_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-tree-maximum-path-sum/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // we will propagate the max sum from bottom to top 8 | // in case of negative sum, we will propagate 0 (similar to kadane's algo) 9 | int path_helper(TreeNode *root, int &max_sum) { 10 | // base case 11 | if(!root) 12 | return 0; 13 | // recursive calls: postorder traversal 14 | int left_sum = path_helper(root->left, max_sum); 15 | int right_sum = path_helper(root->right, max_sum); 16 | 17 | // there could be 4 cases: 18 | // case-1: root node only 19 | int opt1 = root->val; 20 | // case-2: left subtree + root node 21 | int opt2 = left_sum + root->val; 22 | // case-3: right subtree + root node 23 | int opt3 = right_sum + root->val; 24 | // case-4: left subtree + right subtree + root node 25 | int opt4 = left_sum + right_sum + root->val; 26 | 27 | // update the max sum to be the max of these 4 options 28 | max_sum = max({max_sum, opt1, opt2, opt3, opt4}); 29 | // if we encounter negative sum it's better to not consider the node further 30 | // root should return max sum with atmost one child only (else would violate the condition of path) 31 | return max({0, opt1, opt2, opt3}); 32 | } 33 | 34 | 35 | int maxPathSum(TreeNode* root) { 36 | // edge case 37 | if(!root) 38 | return 0; 39 | 40 | int max_sum = INT_MIN; 41 | // call to the helper function 42 | path_helper(root, max_sum); 43 | 44 | return max_sum; 45 | } 46 | }; -------------------------------------------------------------------------------- /Day-19_Binary_Tree/mirror_n_ary.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/check-mirror-in-n-ary-tree1528/1# 3 | */ 4 | 5 | int checkMirrorTree(int n, int e, int A[], int B[]) { 6 | vector> s(n + 1); 7 | vector> q(n + 1); 8 | // connect the edges: create an adjacency list 9 | for(int i = 0; i < 2 * e; i += 2) { 10 | s[A[i]].push(A[i + 1]); 11 | q[B[i]].push(B[i + 1]); 12 | } 13 | // go through each vertices (nodes) of the tree 14 | for(int i = 1; i <= n; i++) { 15 | // compare the nodes one by one 16 | while(!s[i].empty() && !q[i].empty()) { 17 | if(s[i].top() != q[i].front()) 18 | return false; 19 | // pop the elements 20 | s[i].pop(); 21 | q[i].pop(); 22 | } 23 | } 24 | return true; 25 | } -------------------------------------------------------------------------------- /Day-19_Binary_Tree/tree_in_postorder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/ 3 | */ 4 | 5 | /* 6 | Steps: 7 | 1) iteratively pick one element from postorder array and create a node 8 | 2) search for the index of this element in inorder array 9 | 3) make recursive call on left and right subtree 10 | */ 11 | 12 | // helper function to create the binary tree 13 | TreeNode *build_helper(vector &postorder, vector &inorder, int start, int end, int &post_index) { 14 | // base case 15 | if(start > end) 16 | return NULL; 17 | // create node from postorder value 18 | TreeNode *root = new TreeNode(postorder[post_index]); 19 | // search for the index in the inorder vector 20 | int idx = -1; 21 | for(int i = start; i <= end; i++) { 22 | if(inorder[i] == postorder[post_index]) { 23 | idx = i; 24 | break; 25 | } 26 | } 27 | // decrease the index of the postorder vector 28 | post_index--; 29 | // recursive calls: right first (LRN) from right to left it is N->R->L 30 | root->right = build_helper(postorder, inorder, idx + 1, end, post_index); 31 | root->left = build_helper(postorder, inorder, start, idx - 1, post_index); 32 | 33 | return root; 34 | } 35 | 36 | TreeNode *buildTree(vector &inorder, vector &postorder) { 37 | int n = postorder.size(), post_index = n - 1; 38 | // call to the helper function 39 | return build_helper(postorder, inorder, 0, n - 1, post_index); 40 | } -------------------------------------------------------------------------------- /Day-19_Binary_Tree/tree_in_preorder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 3 | */ 4 | 5 | /* 6 | Steps: 7 | 1) iteratively pick one element from preorder array and create a new node 8 | 2) search for the index of this element in inorder array 9 | 3) make recursive call on left and right subtree 10 | */ 11 | 12 | TreeNode *build_helper(vector &preorder, vector &inorder, int start, int end, int &pre_index) { 13 | // base case 14 | if(start > end) 15 | return NULL; 16 | 17 | // create new node from preorder value 18 | TreeNode *root = new TreeNode(preorder[pre_index]); 19 | // search for index in order vector 20 | int idx = -1; 21 | for(int i = start; i <= end; i++) { 22 | if(inorder[i] == preorder[pre_index]) { 23 | idx = i; 24 | break; 25 | } 26 | } 27 | pre_index++; // increment the pointer in the preorder vector 28 | // recursive calls 29 | root->left = build_helper(preorder, inorder, start, idx - 1, pre_index); 30 | root->right = build_helper(preorder, inorder, idx + 1, end, pre_index); 31 | 32 | return root; 33 | } 34 | 35 | // static variable will traverse the pre-order array 36 | TreeNode *buildTree(vector &preorder, vector &inorder) { 37 | int n = preorder.size(), pre_index = 0; 38 | return build_helper(preorder, inorder, 0, n - 1, pre_index); 39 | } 40 | -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/LCA_BST.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/lowest-common-ancestor-in-a-bst/1 3 | */ 4 | 5 | Node *LCA(node *root, int n1, int n2) { 6 | // case-1: both lie in the right subtree 7 | if(min(n1, n2) > root->data) 8 | return LCA(root->right, n1, n2); 9 | // case-2: both lie in the left subtree 10 | if(max(n1, n2) < root->data) 11 | return LCA(root->left, n1, n2); 12 | // one lies on the left and another on right 13 | return root; 14 | } -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Populate next pointers | BFS | [view](populate_next_pointers.cpp) 6 | 2 | Search in BST | recursion | [view](search_BST.cpp) 7 | 3 | Check BST | iterative order condition | [view](check_BST_iterative.cpp) 8 | 4 | Check BST | range validation | [view](check_BST_range.cpp) 9 | 5 | Construct BST from sorted array | div and conq type | [view](bst_array.cpp) 10 | 6 | LCA in BST | check the side of data points | [view](LCA_BST.cpp) 11 | 7 | Inorder Successor | recursion | [view](inorder_successor.cpp) 12 | 8 | Inorder Predecessor and Successor | Recursion | [view](inorder_pre_suc.cpp) -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/bst_array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/ 3 | */ 4 | 5 | // helper function to construct the BST 6 | TreeNode *buildBST(vector &nums, int start, int end) { 7 | // base case 8 | if(start > end) 9 | return NULL; 10 | 11 | int mid = start + (end - start) / 2; 12 | // create a new node 13 | TreeNode *root = new TreeNode(nums[mid]); 14 | // recursive calls 15 | root->left = buildBST(nums, start, mid - 1); 16 | root->right = buildBST(nums, mid + 1, end); 17 | 18 | return root; 19 | } 20 | 21 | TreeNode *sortedArrayToBST(vector &nums) { 22 | return buildBST(nums, 0, nums.size() - 1); 23 | } -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/check_BST_iterative.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/validate-binary-search-tree/ 3 | */ 4 | 5 | // iterative inorder traversal 6 | bool isValidBST(TreeNode *root) { 7 | // edge case 8 | if(!root) 9 | return true; 10 | stack s; 11 | TreeNode *prev = NULL; 12 | 13 | while(!s.empty() || root) { 14 | // push the nodes on the left 15 | while(root) { 16 | s.push(root); 17 | root = root->left; 18 | } 19 | // leftmost node is taken into consideration 20 | root = s.top(); 21 | s.pop(); 22 | // violation of increasing order condition 23 | if(prev && root->val <= prev->val) 24 | return false; 25 | // update prev to be the current node under consideration 26 | prev = root; 27 | // move to the right child 28 | root = root->right; 29 | } 30 | return true; 31 | } -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/check_BST_range.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/validate-binary-search-tree/ 3 | */ 4 | 5 | // helper function to validate BST using range validation 6 | bool isBST(TreeNode *root, long long min_val = -1e10, long long max_val = 1e10) { 7 | // base case 8 | if(!root) 9 | return true; 10 | // check if the node data lies in the range 11 | if(root->val > min_val && root->val < max_val) { 12 | // recursive calls 13 | if(isBST(root->left, min_val, root->val) && isBST(root->right, root->val, max_val) 14 | return true; 15 | } 16 | return false; 17 | } 18 | 19 | bool isValidBST(TreeNode *root) { 20 | return isBST(root); 21 | } -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/inorder_pre_suc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/predecessor-and-successor/1# 3 | */ 4 | 5 | void findPreSuc(Node *root, Node *&pre, Node *&succ, int key) { 6 | // base case 7 | if(!root) 8 | return; 9 | // successor candidate 10 | if(root->key > key) { 11 | succ = root; 12 | // key lies in the left subtree 13 | return findPreSuc(root->left, pre, succ, key); 14 | } 15 | // predecessor candidate 16 | else if(root->key < key) { 17 | pre = root; 18 | // key lies in the right subtree 19 | return findPreSuc(root->right, pre, suc, key); 20 | } 21 | // both successor and predecessor candidates 22 | else { 23 | // recursive calls on both sides 24 | if(root->left) 25 | findPreSuc(root->left, pre, suc, key); 26 | if(root->right) 27 | findPreSuc(root->right, pre, suc, key); 28 | } 29 | } -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/inorder_successor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/inorder-successor-in-bst/1 3 | */ 4 | 5 | // successor has a value just greater than the node x 6 | Node *inOrderSuccessor(Node *root, int x) { 7 | Node *succ = NULL; 8 | while(root) { 9 | if(root->data > x->data) { 10 | succ = root; 11 | // x will lie in the left subtree 12 | root = root->left; 13 | } 14 | else 15 | root = root->right; 16 | } 17 | return succ; 18 | } -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/populate_next_pointers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/populating-next-right-pointers-in-each-node/ 3 | */ 4 | 5 | Node *connect(Node *root) { 6 | // edge case 7 | if(!root) 8 | return NULL; 9 | 10 | queue q; 11 | q.push(root); 12 | Node *curr; 13 | // perform BFS: level order traversal 14 | while(!q.empty()) { 15 | int n = q.size(); // denotes the number of nodes in the current level 16 | for(int i = 0; i < n; i++) { 17 | curr = q.front(); 18 | q.pop(); 19 | // make the last node point to NULL: no node on its right 20 | if(i == n - 1) 21 | curr->next = NULL; 22 | // make the current node point to the next node in the queue 23 | else 24 | curr->next = q.front(); 25 | // add the children in the queue if they exist 26 | if(curr->left) 27 | q.push(curr->left); 28 | if(curr->right) 29 | q.push(curr->right); 30 | } 31 | } 32 | return root; 33 | } 34 | -------------------------------------------------------------------------------- /Day-20_Binary_Search_Tree/search_BST.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/search-in-a-binary-search-tree/ 3 | */ 4 | 5 | 6 | TreeNode *searchBST(TreeNode *root, int val) { 7 | // base case 8 | if(!root) 9 | return NULL; 10 | // condition check 11 | if(root->val == val) 12 | return root; 13 | // recursive calls: narrow down the search space 14 | if(val < root->val) 15 | return searchBST(root->left, val); 16 | else 17 | return searchBST(root->right, val); 18 | } -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Floor in BST | storage + recursion | [view](floor_BST.cpp) 6 | 2 | Ceil in BST | storage + recursion | [view](ceil_BST.cpp) 7 | 3 | Kth smallest in BST | iterative inorder using stack | [view](kth_smallest.cpp) 8 | 4 | Kth largest in BST | reverse iterative inorder using stack | [view](kth_largest.cpp) 9 | 5 | Pair sum | 2 pointer approach using 2 stacks | [view](pair_sum.cpp) 10 | 6 | Serialize and Deserialize Tree | preorder + queue | [view](serial_deserial.cpp) 11 | 7 | Largest BST in a tree | postorder + 4 variables | [view](largest_BST.cpp) 12 | 8 | BST iterator | iterative inorder using stack | [view](bst_iterator.cpp) -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/bst_iterator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/binary-search-tree-iterator/ 3 | */ 4 | 5 | /** 6 | * Definition for a binary tree node. 7 | * struct TreeNode { 8 | * int val; 9 | * TreeNode *left; 10 | * TreeNode *right; 11 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 12 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 13 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 14 | * }; 15 | */ 16 | class BSTIterator { 17 | public: 18 | stack s; 19 | BSTIterator(TreeNode* root) { 20 | inorder(root); 21 | } 22 | 23 | // helper function 24 | void inorder(TreeNode *root) { 25 | // push all the left most nodes 26 | while(root) { 27 | s.push(root); 28 | root = root->left; 29 | } 30 | } 31 | 32 | int next() { 33 | // pop the top node 34 | TreeNode *top = s.top(); 35 | s.pop(); 36 | // make a call to the right node 37 | inorder(top->right); 38 | return top->val; 39 | } 40 | 41 | bool hasNext() { 42 | return !s.empty(); 43 | } 44 | }; 45 | 46 | /** 47 | * Your BSTIterator object will be instantiated and called as such: 48 | * BSTIterator* obj = new BSTIterator(root); 49 | * int param_1 = obj->next(); 50 | * bool param_2 = obj->hasNext(); 51 | */ -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/ceil_BST.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/implementing-ceil-in-bst/1/?track=DSASP-BST&batchId=393 3 | */ 4 | 5 | int findCeil(Node *root, int key) { 6 | int ceil_val = -1; 7 | while(root) { 8 | if(root->data == key) 9 | return key; 10 | else if(root->data > key) { 11 | ceil_val = root->data; 12 | root = root->left; 13 | } 14 | else 15 | root = root->right; 16 | } 17 | return ceil_val; 18 | } -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/floor_BST.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/implementing-floor-in-bst/1/?track=DSASP-BST&batchId=393 3 | */ 4 | 5 | int floor(Node *root, int key) { 6 | int floor_val = -1; 7 | while(root) { 8 | if(root->data == key) 9 | return key; 10 | else if(root->data > key) 11 | root = root->left; 12 | else { 13 | floor_val = root->data; 14 | root = root->right; 15 | } 16 | } 17 | return floor_val; 18 | } -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/kth_largest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/kth-largest-element-in-bst/1 3 | */ 4 | 5 | // reverse iterative inorder traversal using stack 6 | int kthLargest(Node *root, int k) { 7 | stack s; 8 | while(!s.empty() || root) { 9 | // reach the rightmost node 10 | while(root) { 11 | s.push(root); 12 | root = root->right; 13 | } 14 | // pop the rightmost node 15 | root = s.top(); 16 | s.pop(); 17 | // condition check 18 | if(--k == 0) 19 | return root->data; 20 | // move to the left subtree 21 | else 22 | root = root->left; 23 | } 24 | return -1; 25 | } -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/kth_smallest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/kth-smallest-element-in-a-bst/ 3 | */ 4 | 5 | // iterative inorder traversal using stack 6 | int kthSmallest(TreeNode *root, int k) { 7 | stack s; 8 | while(!s.empty() || root) { 9 | // reach the left most node 10 | while(root) { 11 | s.push(root); 12 | root = root->left; 13 | } 14 | // pop the left most node 15 | root = s.top(); 16 | s.pop(); 17 | i(--k == 0) 18 | return root->val; 19 | // move to the right subtree 20 | root = root->right; 21 | } 22 | return -1; 23 | } -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/largest_BST.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Largest BST: https://practice.geeksforgeeks.org/problems/largest-bst/1 3 | */ 4 | 5 | struct bst { 6 | bool isBST; 7 | int size; 8 | int min, max; 9 | }; 10 | 11 | class Solution{ 12 | public: 13 | int size; 14 | // helper function 15 | bst find(Node *root) { 16 | // base case: null node 17 | if(!root) 18 | return {true, 0, INT_MAX, INT_MIN}; 19 | 20 | // leaf node 21 | if(!root->left && !root->right) 22 | return {true, 1, root->data, root->data}; 23 | 24 | // recursive calls: postorder traversal: LRN 25 | bst left = find(root->left); 26 | bst right = find(root->right); 27 | 28 | // condition check 29 | if(left.isBST && right.isBST) { 30 | if(root->data > left.max && root->data < right.min) { 31 | int min_val = left.min; 32 | int max_val = right.max; 33 | // condition check 34 | if(min_val == INT_MAX) 35 | min_val = root->data; 36 | if(max_val == INT_MIN) 37 | max_val = root->data; 38 | 39 | return {1, left.size + right.size + 1, min_val, max_val}; 40 | } 41 | } 42 | return {0, max(left.size, right.size), 0, 0}; 43 | } 44 | 45 | /*You are required to complete this method */ 46 | // Return the size of the largest sub-tree which is also a BST 47 | int largestBst(Node *root) 48 | { 49 | //Your code here 50 | bst b = find(root); 51 | return b.size; 52 | } 53 | }; -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/pair_sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/two-sum-iv-input-is-a-bst/ 3 | */ 4 | 5 | // iterative traversal using 2 stacks 6 | // similar to 2 pointer approach 7 | 8 | bool findTarget(TreeNode *root, int target) { 9 | stack leftStack, rightStack; 10 | TreeNode *ptr = root; // maintain a copy of the root node 11 | // fill the leftStack 12 | while(ptr) { 13 | leftStack.push(ptr); 14 | ptr = ptr->left; 15 | } 16 | // fill the rightStack 17 | ptr = root; 18 | while(ptr) { 19 | rightStack.push(ptr); 20 | ptr = ptr->right; 21 | } 22 | // apply 2 pointer approach 23 | // edge case: root node is a part of 24 | while(!leftStack.empty() && !rightStack.empty() && leftStack.top() != rightStack.top()) { 25 | // fetch the values from stack {cur_min, cur_max} 26 | TreeNode *left_node = leftStack.top(); 27 | TreeNode *right_node = rightStack.top(); 28 | 29 | // if the required pair is found 30 | if(left_node->val + right_node->val == k) 31 | return true; 32 | else if(left_node->val + right_node->val < k) { 33 | // increase the left pointer 34 | TreeNode *temp = leftStack.top(); 35 | leftStack.pop(); 36 | // move to the right and add the leftmost nodes in the stack 37 | temp = temp->right; 38 | while(temp) { 39 | leftStack.push(temp); 40 | temp = temp->left; 41 | } 42 | } 43 | else { 44 | // decrease the right pointer 45 | TreeNode *temp = rightStack.top(); 46 | rightStack.pop(); 47 | // move to the left and add the rightmost nodes in the stack 48 | temp = temp->left; 49 | while(temp) { 50 | rightStack.push(temp); 51 | temp = temp->right; 52 | } 53 | } 54 | } 55 | return false; // the pair is not found 56 | } -------------------------------------------------------------------------------- /Day-21_Binary_Search_Tree/serial_deserial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/ 3 | */ 4 | 5 | // encode a tree into a single string 6 | // preorder tree traversal 7 | string serialize(TreeNode *root) { 8 | // base case 9 | if(!root) 10 | return "NULL,"; 11 | // recursive calls 12 | return to_string(root->val) + "," + serialize(root->left) + serialize(root->right); 13 | } 14 | 15 | // helper function to create a queue (level order traversal) 16 | TreeNode *deserialize_helper(queue &q) { 17 | string front = q.front(); 18 | q.pop(); 19 | // base case 20 | if(front == "NULL") 21 | return NULL; 22 | // create the current new node 23 | TreeNode *root = new TreeNode(stoi(front)); 24 | // recursive calls 25 | root->left = deserialize_helper(q); 26 | root->right = deserialize_helper(q); 27 | 28 | return root; 29 | } 30 | 31 | // decodes encoded data to tree 32 | TreeNode *deserialize(string data) { 33 | queue q; 34 | string s; 35 | for(char &c : data) { 36 | if(c == ',') { 37 | q.push(s); 38 | // reset the string 39 | s = ""; 40 | } 41 | else 42 | s += c; 43 | } 44 | if(!s.empty()) 45 | q.push(s); 46 | // call to the helper function to deserialize 47 | return deserialize_helper(q); 48 | } -------------------------------------------------------------------------------- /Day-22_Mixed_Questions/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Binary Tree to Doubly Linked List | dll connections: 4 cases | [view](tree_to_DLL.cpp) 6 | 2 | Flood-Fill Algorithm | dfs on a graph | [view](flood_fill.cpp) 7 | 3 | Kth Largest Element | minHeap of size k | [view](kth_largest.cpp) 8 | 4 | Kth Largest Element in a running stream | minHeap of size k | [view](kth_largest_stream.cpp) 9 | 5 | Median in a running stream | maxHeap and minHeap | [view](median_stream.cpp) 10 | 6 | Count distinct in each window | hashmap + sliding window | [view](count_distinct_window.cpp) -------------------------------------------------------------------------------- /Day-22_Mixed_Questions/count_distinct_window.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://www.interviewbit.com/problems/distinct-numbers-in-window/# 3 | */ 4 | 5 | vector Solution::dNums(vector &A, int k) { 6 | vector results; 7 | const int n = A.size(); 8 | unordered_map m; 9 | int count = 0; 10 | 11 | // insert the elements of the first window 12 | for(int i = 0; i < k; i++) { 13 | // count of unique elements 14 | if(m[A[i]] == 0) 15 | count++; 16 | m[A[i]]++; 17 | } 18 | results.push_back(count); 19 | // process the remaining elements 20 | for(int i = k; i < n; i++) { 21 | // remove the element going out of the current window 22 | if(m[A[i - k]] == 1) 23 | count--; 24 | m[A[i - k]]--; 25 | // add the current element in the window 26 | if(m[A[i]] == 0) 27 | count++; 28 | m[A[i]]++; 29 | // update the count in the vector 30 | results.push_back(count); 31 | } 32 | return results; 33 | } 34 | -------------------------------------------------------------------------------- /Day-22_Mixed_Questions/flood_fill.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/flood-fill/ 3 | */ 4 | 5 | class Solution { 6 | int rows, cols; 7 | int row_dirs[4] = {0, 0, -1, 1}; 8 | int col_dirs[4] = {-1, 1, 0, 0}; 9 | public: 10 | 11 | // helper function 12 | void dfs_helper(vector> &image, int r, int c, int oldColor, int newColor) { 13 | // base cases 14 | if(r < 0 || c < 0 || r >= rows || c >= cols || image[r][c] != oldColor) 15 | return; 16 | // transform the color 17 | image[r][c] = newColor; 18 | // make recursive dfs calls on the neighbors 19 | for(int itr = 0; itr < 4; itr++) 20 | dfs_helper(image, r + row_dirs[itr], c + col_dirs[itr], oldColor, newColor); 21 | } 22 | 23 | vector> floodFill(vector>& image, int sr, int sc, int newColor) { 24 | this->rows = image.size(); 25 | this->cols = image[0].size(); 26 | 27 | int oldColor = image[sr][sc]; 28 | // initiate a dfs call with the source pixel 29 | if(oldColor != newColor) 30 | dfs_helper(image, sr, sc, oldColor, newColor); 31 | return image; 32 | } 33 | }; -------------------------------------------------------------------------------- /Day-22_Mixed_Questions/kth_largest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/kth-largest-element-in-an-array/ 3 | */ 4 | 5 | int findKthLargest(vector &nums, int k) { 6 | priority_queue, greater> pq; 7 | for(int i = 0; i < nums.size(); i++) { 8 | if(pq.size() < k) 9 | pq.push(nums[i]); 10 | else if(nums[i] > pq.top()) { 11 | pq.pop(); 12 | pq.push(nums[i]); 13 | } 14 | } 15 | return pq.top(); 16 | } -------------------------------------------------------------------------------- /Day-22_Mixed_Questions/kth_largest_stream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/kth-largest-element-in-a-stream2220/1 3 | */ 4 | 5 | vector kthLargest(int k, int arr[], int n) { 6 | vector results(k - 1, -1); // no window of size k found 7 | priority_queue, greater> pq; // min heap 8 | // iterate the stream of numbers 9 | for(int i = 0; i < k; i++) 10 | pq.push(arr[i]); 11 | 12 | results.push_back(pq.top()); 13 | for(int i = k; i < n; i++) { 14 | if(arr[i] > pq.top()) { 15 | pq.pop(); 16 | pq.push(arr[i]); 17 | } 18 | results.push_back(pq.top()); 19 | } 20 | return results; 21 | } -------------------------------------------------------------------------------- /Day-22_Mixed_Questions/median_stream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/find-median-from-data-stream/ 3 | */ 4 | 5 | class MedianFinder { 6 | public: 7 | priority_queue maxHeap; // max of the left part 8 | priority_queue, greater> minHeap; // min of right part 9 | 10 | void addNum(int num) { 11 | // left side of the array 12 | if(maxHeap.empty() || num <= maxHeap.top()) 13 | maxHeap.push(num); 14 | else 15 | minHeap.push(num); 16 | 17 | // balance the 2 heaps 18 | if(maxHeap.size() < minHeap.size()) { 19 | maxHeap.push(minHeap.top()); 20 | minHeap.pop(); 21 | } 22 | else if(maxHeap.size() - minHeap.size() >= 2) { 23 | minHeap.push(maxHeap.top()); 24 | maxHeap.pop(); 25 | } 26 | } 27 | 28 | double findMedian() { 29 | if(maxHeap.size() == minHeap.size()) 30 | return (maxHeap.top() + minHeap.top()) / 2.0; 31 | else 32 | return maxHeap.top(); 33 | } 34 | }; -------------------------------------------------------------------------------- /Day-22_Mixed_Questions/tree_to_DLL.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/binary-tree-to-dll/1 3 | */ 4 | 5 | struct Node { 6 | int data; 7 | Node *left, *right; 8 | 9 | Node(int data) { 10 | this->data = data; 11 | left = right = NULL; 12 | } 13 | }; 14 | 15 | struct LinkedList { 16 | Node *head; 17 | Node *tail; 18 | }; 19 | 20 | LinkedList flatten(Node *root) { 21 | // base case 22 | LinkedList dll; 23 | if(!root) { 24 | // init an empty list 25 | dll.head = dll.tail = NULL; 26 | return dll; 27 | } 28 | // case-1: left node 29 | if(!root->left && !root->right) { 30 | dll.head = dll.tail = root; 31 | return dll; 32 | } 33 | // case-2: only left subtree exists 34 | else if(root->left && !root->right) { 35 | // convert left subtree into DLL 36 | LinkedList left = flatten(root->left); 37 | // connect the tail of the left subtree with the root node 38 | left.tail->right = root; 39 | root->left = left.tail; 40 | // update the tail to be the root node 41 | dll.tail = root; 42 | // update the head to be the head of the left subtree 43 | dll.head = left.head; 44 | 45 | return dll; 46 | } 47 | // case-3: only right subtree exists 48 | else if(!root->left && root->right) { 49 | // convert right subtree into DLL 50 | LinkedList right = flatten(root->right); 51 | // connect the head of the right subtree with the root node 52 | right.head->left = root; 53 | root->right = right.head; 54 | // update the head to be the root node 55 | dll.head = root; 56 | // update the tail to be the tail of the right subtree 57 | dll.tail = right.tail; 58 | 59 | return dll; 60 | } 61 | // case-4: both subtrees exist 62 | else { 63 | // convert left subtree into DLL 64 | LinkedList left = flatten(root->left); 65 | // convert right subtree into DLL 66 | LinkedList right = flatten(root->right); 67 | // connect tail of left subtree with root node 68 | left.tail->right = root; 69 | root->left = left.tail; 70 | // connect head of the right subtree with root node 71 | right.head->left = root; 72 | root->right = right.head; 73 | // update head to be the head of the left subtree 74 | dll.head = left.head; 75 | // update tail to be the tail of the right subtree 76 | dll.tail = right.tail; 77 | 78 | return dll; 79 | } 80 | } 81 | 82 | Node *bToDLL(Node *root) { 83 | return flatten(root).head; 84 | } -------------------------------------------------------------------------------- /Day-23_Graph/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | DFS | recursion + visited bool array | [view](dfs_graph.cpp) 6 | 2 | BFS | queue, level order traversal | [view](bfs_graph.cpp) 7 | 3 | Cycle detection in undirected graph | BFS, visited, parent array | [view](cycle_undirected.cpp) 8 | 4 | Cycle detection in undirected graph | DFS, parent node | [view](cycle_undirected_dfs.cpp) 9 | 5 | Cycle detection in directed graph | DFS, stack_path for back-edge | [view](cycle_directed.cpp) 10 | 6 | Cycle detection in directed graph | BFS, Kahn's algo for topo sort | [view](cycle_directed_bfs.cpp) 11 | 7 | Topological Sort | Kahn's algo | [view](topo_sort.cpp) 12 | 8 | Number of islands | DFS in 4 directions | [view](number_islands.cpp) 13 | 9 | Check Bipartite graph | BFS, adjacent 2 colors | [view](bipartite_bfs.cpp) 14 | 10 | Check Bipartite graph | DFS, adjacent 2 colors | [view](bipartite_dfs.cpp) 15 | 11 | Clone a undirected graph | DFS, vector created | [view](clone_undirected.cpp) 16 | 12 | Topological Sort | DFS, push the node when rec call is over | [view](topo_sort_dfs.cpp) -------------------------------------------------------------------------------- /Day-23_Graph/bfs_graph.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/bfs-traversal-of-graph/1 3 | */ 4 | 5 | vector bfsOfGraph(int V, vector adj[]) { 6 | // all nodes are initially not visited 7 | vector visited(V, false); 8 | vector results; 9 | queue q; 10 | // push the source node in the queue 11 | q.push(0); 12 | // mark the source node as visited 13 | visited[0] = true; 14 | 15 | while(!q.empty()) { 16 | int front = q.front(); 17 | q.pop(); 18 | results.push_back(front); 19 | // find the unvisited neighbours and add them in the queue 20 | for(int &nbr : adj[front]) { 21 | if(!visited[nbr]) { 22 | q.push(nbr); 23 | // mark the nbr as visited 24 | visited[nbr] = true; 25 | } 26 | } 27 | } 28 | return results; 29 | } -------------------------------------------------------------------------------- /Day-23_Graph/bipartite_bfs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/bipartite-graph/1 3 | */ 4 | 5 | class Solution { 6 | public: 7 | /* 8 | bipartite graph is a graph that can be colored with exactly 2 colors 9 | such that no 2 adjacent nodes have the same color. 10 | */ 11 | // helper function using bfs 12 | bool check_bipartite(int source, vector adj[], vector &color) { 13 | queue q; 14 | q.push(source); 15 | color[source] = 1; 16 | // visit the adjacent nodes and mark them with opposite color 17 | while(!q.empty()) { 18 | int front = q.front(); 19 | q.pop(); 20 | 21 | for(int &nbr : adj[front]) { 22 | // check if not colored/ visited previously 23 | if(color[nbr] == -1) { 24 | color[nbr] = 1 - color[front]; 25 | // push the neighbor in the queue 26 | q.push(nbr); 27 | } 28 | // 2 adjacent nodes having the same color: not a bipartite 29 | else if(color[nbr] == color[front]) 30 | return false; 31 | } 32 | } 33 | return true; 34 | } 35 | 36 | bool isBipartite(int V, vectoradj[]){ 37 | // Code here 38 | vector color(V, -1); 39 | // init bfs call for each disconnected component 40 | for(int i = 0; i < V; i++) { 41 | if(color[i] == -1) { 42 | if(!check_bipartite(i, adj, color)) 43 | return false; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | }; -------------------------------------------------------------------------------- /Day-23_Graph/bipartite_dfs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/bipartite-graph/1 3 | */ 4 | 5 | class Solution { 6 | public: 7 | /* 8 | bipartite graph is a graph that can be colored with exactly 2 colors 9 | such that no 2 adjacent nodes have the same color. 10 | */ 11 | // helper function using dfs 12 | bool check_bipartite(int node, vector adj[], vector &color) { 13 | // for the source node, we start with color 1 14 | if(color[node] == -1) 15 | color[node] = 1; 16 | 17 | // make dfs calls on the adjacent nodes 18 | for(int &nbr : adj[node]) { 19 | // if the node is prev. unvisited, color it with opposite color 20 | if(color[nbr] == -1) { 21 | // first color and then make the recursive call 22 | color[nbr] = 1 - color[node]; 23 | if(!check_bipartite(nbr, adj, color)) 24 | return false; 25 | } 26 | // same color for 2 adjacent nodes: not bipartite 27 | else if(color[nbr] == color[node]) 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | bool isBipartite(int V, vectoradj[]){ 34 | // Code here 35 | vector color(V, -1); 36 | // init dfs call for each disconnected component 37 | for(int i = 0; i < V; i++) { 38 | if(color[i] == -1) { 39 | if(!check_bipartite(i, adj, color)) 40 | return false; 41 | } 42 | } 43 | return true; 44 | } 45 | 46 | }; -------------------------------------------------------------------------------- /Day-23_Graph/clone_undirected.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/clone-graph/ 3 | */ 4 | 5 | /* 6 | // Definition for a Node. 7 | class Node { 8 | public: 9 | int val; 10 | vector neighbors; 11 | Node() { 12 | val = 0; 13 | neighbors = vector(); 14 | } 15 | Node(int _val) { 16 | val = _val; 17 | neighbors = vector(); 18 | } 19 | Node(int _val, vector _neighbors) { 20 | val = _val; 21 | neighbors = _neighbors; 22 | } 23 | }; 24 | */ 25 | 26 | class Solution { 27 | public: 28 | // helper function 29 | void dfs_helper(Node *node, Node *copy, vector &created) { 30 | // store the pointer to the current copy node 31 | created[copy->val] = copy; 32 | // iterate through the adjacent nodes 33 | for(auto nbr : node->neighbors) { 34 | // if the neighbor node is not previously visited, create a new node 35 | if(!created[nbr->val]) { 36 | Node *new_node = new Node(nbr->val); 37 | // push this neighbor node in the neighbors vector of copy node 38 | (copy->neighbors).push_back(new_node); 39 | // init a recursive dfs call 40 | dfs_helper(nbr, new_node, created); 41 | } 42 | else 43 | (copy->neighbors).push_back(created[nbr->val]); 44 | } 45 | } 46 | 47 | Node* cloneGraph(Node* node) { 48 | // edge case 49 | if(!node) 50 | return NULL; 51 | 52 | vector created(101, NULL); 53 | Node *copy = new Node(node->val); 54 | dfs_helper(node, copy, created); 55 | 56 | return copy; 57 | } 58 | }; -------------------------------------------------------------------------------- /Day-23_Graph/cycle_directed.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/detect-cycle-in-a-directed-graph/1 3 | */ 4 | #include 5 | using namespace std; 6 | 7 | class Solution { 8 | public: 9 | // helper function to detect cycle using dfs 10 | bool checkForCycle(int node, vector &visited, vector &stack_path, vector adj[]) { 11 | // mark the current node as visited 12 | visited[node] = true; 13 | // add the node in the stack path, indicates it is a part of the current path 14 | stack_path[node] = true; 15 | 16 | for(int &nbr : adj[node]) { 17 | // check for back-edge 18 | if(stack_path[nbr]) 19 | return true; 20 | // init dfs call for unvisited nodes 21 | else if(!visited[nbr]) { 22 | if(checkForCycle(nbr, visited, stack_path, adj)) 23 | return true; 24 | } 25 | } 26 | // when we leave the node, it is no longer a part of the current path 27 | stack_path[node] = false; 28 | return false; 29 | } 30 | 31 | bool isCyclic(int V, vector adj[]) { 32 | vector visited(V, false); 33 | vector stack_path(V, false); 34 | 35 | // init a dfs call on each unvisited node (disconnected component) 36 | for(int i = 0; i < V; i++) { 37 | if(checkForCycle(i, visited, stack_path, adj)) 38 | return true; 39 | } 40 | return false; 41 | } 42 | }; 43 | 44 | int main() 45 | { 46 | 47 | int t; 48 | cin >> t; 49 | while(t--) 50 | { 51 | int V, E; 52 | cin >> V >> E; 53 | 54 | vector adj[V]; 55 | 56 | for(int i = 0; i < E; i++) 57 | { 58 | int u, v; 59 | cin >> u >> v; 60 | adj[u].push_back(v); 61 | } 62 | 63 | Solution obj; 64 | cout << obj.isCyclic(V, adj) << "\n"; 65 | } 66 | 67 | return 0; 68 | } -------------------------------------------------------------------------------- /Day-23_Graph/cycle_directed_bfs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/detect-cycle-in-a-directed-graph/1 3 | */ 4 | 5 | // topological sort is applicable for DAG only. So if topo sort is not possible then we can be sure there is a cycle. 6 | 7 | class Solution { 8 | public: 9 | bool isCyclic(int N, vector adj[]) { 10 | queue q; 11 | vector indegree(N, 0); 12 | for(int u = 0; u < N; u++) { 13 | for(int &v : adj[u]) 14 | indegree[v]++; 15 | } 16 | // push the nodes in the queue having an indegree of 0 17 | for(int i = 0; i < N; i++) { 18 | if(indegree[i] == 0) 19 | q.push(i); 20 | } 21 | int count = 0; 22 | while(!q.empty()) { 23 | int node = q.front(); 24 | q.pop(); 25 | count++; 26 | 27 | // reduce the indegree of the neighbors by 1 28 | for(int &nbr : adj[node]) { 29 | if(--indegree[nbr] == 0) 30 | q.push(nbr); 31 | } 32 | } 33 | // topological sort is complete, graph is acyclic 34 | if(count == N) 35 | return false; 36 | return true; 37 | } 38 | }; -------------------------------------------------------------------------------- /Day-23_Graph/cycle_undirected.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/detect-cycle-in-an-undirected-graph/1 3 | */ 4 | 5 | bool bfs(vector adj[], int source, int V, vector &visited) { 6 | queue q; 7 | q.push(source); 8 | // mark the source node as visited 9 | visited[source] = true; 10 | vector parent(V, -1); 11 | 12 | // apply BFS 13 | while(!q.empty()) { 14 | int front = q.front(); 15 | q.pop(); 16 | 17 | // visit the neighbours of this node 18 | for(int &nbr : adj[front]) { 19 | if(!visited[nbr]) { 20 | visited[nbr] = true; 21 | parent[nbr] = front; 22 | q.push(nbr); 23 | } 24 | else if(parent[front] != nbr) 25 | return true; 26 | } 27 | } 28 | return false; 29 | } 30 | 31 | // the graph could contain disconnected components as well 32 | bool isCycle(int V, vector adj[]) { 33 | // initially mark all the nodes as unvisited 34 | vector visited(V, false); 35 | // go through each node and call BFS on each unvisited node 36 | for(int i = 0; i < V; i++) { 37 | // cycle is detected 38 | if(!visited[i] && bfs(adj, i, V, visited)) 39 | return true; 40 | } 41 | return false; 42 | } 43 | -------------------------------------------------------------------------------- /Day-23_Graph/cycle_undirected_dfs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/detect-cycle-in-an-undirected-graph/1 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // dfs helper function to find cycle 8 | bool checkForCycle(int node, int parent, vector &visited, vector adj[]) { 9 | // mark the current node as visited 10 | visited[node] = true; 11 | for(int &nbr : adj[node]) { 12 | // if nbr is unvisited, init a dfs call 13 | if(!visited[nbr]) { 14 | if(checkForCycle(nbr, node, visited, adj)) 15 | return true; 16 | } 17 | // nbr = parent means it is the adjacent node (no cycle as such) 18 | else if(nbr != parent) 19 | return true; 20 | } 21 | return false; 22 | } 23 | 24 | // Function to detect cycle in an undirected graph. 25 | bool isCycle(int V, vector adj[]) { 26 | // Code here 27 | vector visited(V, false); 28 | for(int i = 0; i < V; i++) { 29 | if(!visited[i]) { 30 | if(checkForCycle(i, -1, visited, adj)) 31 | return true; 32 | } 33 | } 34 | return false; 35 | } 36 | }; -------------------------------------------------------------------------------- /Day-23_Graph/dfs_graph.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/depth-first-traversal-for-a-graph/1 3 | */ 4 | 5 | void dfs_helper(int node, vector adj[], int V, vector &visited, vector &results) { 6 | // base case 7 | if(visited[node]) 8 | return; 9 | // mark the node as visited 10 | visited[node] = true; 11 | results.push_back(node); 12 | 13 | // recursive dfs calls over the nodes in the connected component 14 | for(int &nbr : adj[node]) { 15 | if(!visited[nbr]) 16 | dfs_helper(nbr, adj, V, visited, results); 17 | } 18 | } 19 | 20 | //Function to return a list containing the DFS traversal of the graph. 21 | vector dfsOfGraph(int V, vector adj[]) { 22 | vector visited(V, false); 23 | vector results; 24 | // init dfs calls on each disconnected component 25 | for(int i = 0; i < V; i++) { 26 | if(!visited[i]) 27 | dfs_helper(i, adj, V, visited, results); 28 | } 29 | return results; 30 | } -------------------------------------------------------------------------------- /Day-23_Graph/number_islands.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://leetcode.com/problems/number-of-islands/ 3 | */ 4 | 5 | class Solution { 6 | public: 7 | // DFS Solution 8 | // denotes the 4 neighbors of a grid cell 9 | int row_dirs[4] = {0, 0, -1, 1}; 10 | int col_dirs[4] = {-1, 1, 0, 0}; 11 | int rows, cols; 12 | 13 | void dfs_helper(int r, int c, vector> &grid) { 14 | // base conditions: corner cases of the grid 15 | // when we encounter water, there won't be adjacent neighbor calls 16 | if(r < 0 || c < 0 || r >= rows || c >= cols || grid[r][c] == '0') 17 | return; 18 | // the current land block is visited 19 | grid[r][c] = '0'; 20 | // recursive dfs calls for the neighbors 21 | for(int itr = 0; itr < 4; itr++) 22 | dfs_helper(r + row_dirs[itr], c + col_dirs[itr], grid); 23 | } 24 | 25 | 26 | int numIslands(vector> &grid) { 27 | int count = 0; 28 | this->rows = grid.size(); 29 | this->cols = grid[0].size(); 30 | 31 | // init dfs call on each disconnected component 32 | for(int i = 0; i < rows; i++) { 33 | for(int j = 0; j < cols; j++) { 34 | if(grid[i][j] == '1') { 35 | count++; 36 | dfs_helper(i, j, grid); 37 | } 38 | } 39 | } 40 | return count; 41 | } 42 | 43 | }; -------------------------------------------------------------------------------- /Day-23_Graph/topo_sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Topological Sorting using BFS. 3 | Task dependencies. 4 | Topological sorting for a graph is not possible if the graph is not a DAG. 5 | It is a linear ordering of the vertices such that for every directed edge u, v, 6 | vertix u comes before v in the ordering. 7 | A DAG is a directed graph without any cycle. 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | template 17 | class Graph { 18 | list *l; // array of lists 19 | int V; 20 | public: 21 | Graph(int V) { 22 | this->V = V; 23 | // we have V number of linked lists 24 | l = new list[V]; 25 | } 26 | 27 | void addEdge(T x, T y) { 28 | l[x].push_back(y); 29 | } 30 | 31 | void topoSort() { 32 | // array of indegree 33 | int *indegree = new int[V]; 34 | memset(indegree, 0, V * sizeof(int)); 35 | // update the indegree by traversing edges 36 | for(int i = 0; i < V; i++) { 37 | for(auto const y : l[i]) { 38 | indegree[y]++; 39 | } 40 | } 41 | // find nodes with 0 indegree 42 | queue q; 43 | for(int i = 0; i < V; i++) { 44 | if(indegree[i] == 0) 45 | q.push(i); 46 | } 47 | // apply BFS 48 | while(!q.empty()) { 49 | T front = q.front(); 50 | cout << front << " "; 51 | q.pop(); 52 | 53 | // iterate over the neighbours and reduce their indegree by 1 54 | for(auto const nbr : l[front]) { 55 | indegree[nbr]--; 56 | if(indegree[nbr] == 0) 57 | q.push(nbr); 58 | } 59 | } 60 | 61 | } 62 | }; 63 | 64 | int main() { 65 | 66 | Graph g(6); 67 | g.addEdge(0, 2); 68 | g.addEdge(1, 2); 69 | g.addEdge(2, 3); 70 | g.addEdge(1, 4); 71 | g.addEdge(2, 5); 72 | g.addEdge(4, 5); 73 | g.addEdge(3, 5); 74 | 75 | g.topoSort(); 76 | 77 | return 0; 78 | } -------------------------------------------------------------------------------- /Day-23_Graph/topo_sort_dfs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Topological Sorting using BFS. 3 | Task dependencies. 4 | Topological sorting for a graph is not possible if the graph is not a DAG. 5 | It is a linear ordering of the vertices such that for every directed edge u, v, 6 | vertix u comes before v in the ordering. 7 | A DAG is a directed graph without any cycle. 8 | */ 9 | 10 | class Solution 11 | { 12 | public: 13 | // helper function to perform dfs 14 | void dfs_helper(int node, vector &visited, stack &st, vector adj[]) { 15 | // mark the current node as visited 16 | visited[node] = true; 17 | // init dfs calls over the unvisited adjacent nodes 18 | for(int &nbr : adj[node]) { 19 | if(!visited[nbr]) 20 | dfs_helper(nbr, visited, st, adj); 21 | } 22 | // push the current node after all its adjacent neighbor nodes are pushed 23 | st.push(node); 24 | } 25 | 26 | // Function to return list containing vertices in Topological order. 27 | // topological sort using DFS, u -> v (we will push v in the stack before u) for all edges 28 | vector topoSort(int V, vector adj[]) 29 | { 30 | // code here 31 | stack st; 32 | vector visited(V, false); 33 | // init dfs call over each disconnected component 34 | for(int i = 0; i < V; i++) { 35 | if(!visited[i]) 36 | dfs_helper(i, visited, st, adj); 37 | } 38 | vector results; 39 | while(!st.empty()) { 40 | results.push_back(st.top()); 41 | st.pop(); 42 | } 43 | return results; 44 | } 45 | }; -------------------------------------------------------------------------------- /Day-24_Graph/README.md: -------------------------------------------------------------------------------- 1 | # Problems 2 | 3 | SNo | Name | Logic Used | Link | 4 | ----|------|------------|------| 5 | 1 | Strongly Connected Components | Kosaraju's algo, dfs | [view](SCC_kosaraju.cpp) 6 | 2 | Dijkstra Algo | minheap, relax(u, v) | [view](dijkstra_all_shortest_path.cpp) -------------------------------------------------------------------------------- /Day-24_Graph/SCC_kosaraju.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/strongly-connected-components-kosarajus-algo/1# 3 | */ 4 | 5 | class Solution 6 | { 7 | public: 8 | // Function to find number of strongly connected components in the graph. 9 | // from each node we can reach every other node in the SCC 10 | // dfs from the last node 11 | 12 | /* 13 | Algorithm: 14 | 1. Sort all nodes in the order of finishing time ie. time of reach, when dfs call returns back 15 | 2. Transpose the graph ie. all the edges will get reversed. 16 | 3. Do the DFS according to the finishing time. 17 | */ 18 | // helper function to sort all the nodes in the order of finishing time. 19 | void dfs_helper(int node, stack &st, vector &visited, vector adj[]) { 20 | // mark the current node as visited 21 | visited[node] = true; 22 | for(int &nbr : adj[node]) { 23 | // make a dfs call for the unvisited neighbor 24 | if(!visited[nbr]) 25 | dfs_helper(nbr, st, visited, adj); 26 | } 27 | // push the node once all the adjacent nodes are pushed first 28 | st.push(node); 29 | } 30 | 31 | // helper function to do dfs 32 | void dfs(int node, vector &visited, vector transpose[]) { 33 | // mark the current node as visited 34 | visited[node] = true; 35 | for(int &nbr : transpose[node]) { 36 | // make a dfs call for the unvisited neighbor 37 | if(!visited[nbr]) 38 | dfs(nbr, visited, transpose); 39 | } 40 | } 41 | 42 | int kosaraju(int V, vector adj[]) 43 | { 44 | //code here 45 | stack st; 46 | vector visited(V, false); 47 | // step-1: sort all nodes in the order of the finishing time 48 | // init dfs call for each disconnected component 49 | for(int i = 0; i < V; i++) { 50 | if(!visited[i]) 51 | dfs_helper(i, st, visited, adj); 52 | } 53 | // step-2: take tranpose of the graph 54 | vector transpose[V]; 55 | for(int u = 0; u < V; u++) { 56 | visited[u] = false; // making it ready for the next step 57 | // edge from u to v 58 | for(int &v : adj[u]) { 59 | // edge from v to u 60 | transpose[v].push_back(u); 61 | } 62 | } 63 | int count = 0; 64 | // step-3: do the dfs according to the finishing time. 65 | while(!st.empty()) { 66 | int node = st.top(); 67 | st.pop(); 68 | 69 | if(!visited[node]) { 70 | dfs(node, visited, transpose); 71 | count++; 72 | } 73 | } 74 | return count; 75 | } 76 | }; -------------------------------------------------------------------------------- /Day-24_Graph/dijkstra_all_shortest_path.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Link: https://practice.geeksforgeeks.org/problems/implementing-dijkstra-set-1-adjacency-matrix/1/ 3 | */ 4 | 5 | #define pii pair 6 | class Solution 7 | { 8 | public: 9 | //Function to find the shortest distance of all the vertices 10 | //from the source vertex S. 11 | vector dijkstra(int V, vector> adj[], int S) 12 | { 13 | // Code here 14 | vector visited(V, false); 15 | vector distance(V, INT_MAX); // initially mark all the distance to be infinity 16 | distance[S] = 0; // distance of source node from itself = 0 17 | priority_queue, greater> pq; // minHeap to get the node with least distance 18 | // pii -> {distance, node} 19 | pq.push({distance[S], S}); 20 | while(!pq.empty()) { 21 | // get the current node with min distance 22 | int u = pq.top().second; 23 | pq.pop(); 24 | visited[u] = true; 25 | // perform the relax operation by going through unvisited adjacent nodes 26 | for(auto v : adj[u]) { 27 | // v -> {node, weight} 28 | if(!visited[v[0]] && distance[u] + v[1] < distance[v[0]]) { 29 | distance[v[0]] = distance[u] + v[1]; 30 | // push this node in the pq 31 | pq.push({distance[v[0]], v[0]}); 32 | } 33 | } 34 | } 35 | return distance; 36 | } 37 | }; --------------------------------------------------------------------------------