├── .gitignore ├── Math ├── pow.cpp ├── reverse_integer.cpp └── multiple_with_0_and_1.cpp ├── String ├── is_subsequence.cpp ├── simplify_path.cpp ├── group_shifted_strings.cpp ├── number_of_matching_subsequences.cpp ├── shortest_palindrome.cpp ├── minimum_remove_make_valid_parantheses.cpp ├── shortest_way_to_form_string.cpp ├── encode_and_decode.cpp └── valid_number_hard.cpp ├── PatternSearching ├── naive.cpp ├── KMP.cpp ├── RabinKarp.cpp └── Z_Algorithm.cpp ├── Arrays ├── container_with_most_water.cpp ├── one_edit_distance.cpp ├── valid_palindrome_2.cpp ├── 3sum_closest.cpp ├── first_missing_positive.cpp ├── subarray_sum_equals_k.cpp ├── kth_smallest_element_in_array.cpp ├── product_of_array-except_self.cpp ├── next_permutation.cpp ├── remove_duplicates_from_sorted_array.cpp ├── median_two_sorted_arryas.cpp ├── continous_subarray_sum.cpp └── merge_intervals.cpp ├── LICENSE ├── technical-screening-round └── README.md ├── StandardQuestions └── DP │ ├── subset_sum.cpp │ ├── equal_sum_partition.cpp │ └── knapsack.cpp ├── Miscellneous ├── string_tokenization.cpp ├── comparators.cpp └── randomizer.cpp ├── Tree ├── connect_node_at_same_level.cpp ├── kth_largest_in_BST.cpp └── zigzag_traversal.cpp ├── Map └── longest_palindrome_by_concatenating_two_letter_words.cpp ├── Sorting └── radix_sort.cpp ├── SegmentTree └── segment_tree.cpp ├── SuffixArray └── suffix_array.cpp ├── Trie ├── sorting_array_of_strings.cpp ├── trie.cpp └── palindrome_pairs_hard.cpp ├── onsites-london └── README.md ├── MonotonicQueue ├── shortest_subarray_with_sum_atleast_k.cpp ├── MonotonicQueue.cpp ├── daily_temperature.cpp └── shortest_unsorted_continouos_subarray.cpp ├── BinarySearch └── random_pick_with_weights.cpp ├── README.md ├── LinkedList ├── reorder_list.cpp └── copy_list_with_random-pointer.cpp └── FenwickTree └── BinaryIndexTree.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | /*.out -------------------------------------------------------------------------------- /Math/pow.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file pow.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-06 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | double power(double x, unsigned int n) { 16 | double ans; 17 | if(n == 0) { 18 | return 1; 19 | } 20 | ans = power(x, n/2); 21 | if(n % 2 == 0) 22 | return ans*ans; 23 | else return x*ans*ans; 24 | } 25 | 26 | int main() { 27 | cout << power(2,5); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Math/reverse_integer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file reverse_integer.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-11-22 7 | * @link https://leetcode.com/problems/reverse-integer/ 8 | * 9 | * @copyright Copyright (c) 2021 10 | * 11 | */ 12 | 13 | #include 14 | using namespace std; 15 | 16 | int reverseIntegre(int input) { 17 | int output = 0; 18 | if(input == INT_MAX || input == INT_MIN) { return 0; } 19 | 20 | while(input) { 21 | output *= 10; 22 | output += input % 10; 23 | input /= 10; 24 | } 25 | 26 | return output; 27 | } 28 | 29 | int main() { 30 | cout << reverseIntegre(123456789); 31 | return 0; 32 | } -------------------------------------------------------------------------------- /String/is_subsequence.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file is_subsequence.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-08 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | bool isSubsequence(string s, string t) { 16 | if(s.length() == t.length()) { 17 | return s == t; 18 | } 19 | 20 | int i = 0; 21 | int l = s.length(); 22 | 23 | for(auto x : t) { 24 | if(s[i] == x) i++; 25 | 26 | if(i == l) return true; 27 | } 28 | 29 | return false; 30 | } 31 | 32 | int main() { 33 | string s = "acy"; 34 | string t = "axcdy"; 35 | cout << isSubsequence(s,t) << endl; 36 | return 0; 37 | } -------------------------------------------------------------------------------- /PatternSearching/naive.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file naive.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-03 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | int naivePatternSearch(string input, string pattern) { 16 | int index = -1; 17 | int m = input.length(); 18 | int n = pattern.length(); 19 | 20 | for(int i = 0; i < m-n+1; i++) { 21 | for(int j = 0; j < n; j++) { 22 | if(j == n-1) return i; 23 | else if(input[j+i] != pattern[j]) break; 24 | else continue; 25 | } 26 | } 27 | return index; 28 | } 29 | 30 | int main() { 31 | string input = "roxfoxfox"; 32 | string pattern = "fox"; 33 | cout << naivePatternSearch(input, pattern); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Arrays/container_with_most_water.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file container_with_most_water.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-08 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | int mostWater(vector container) { 16 | int length = container.size(); 17 | int ans = INT_MIN; 18 | // for(int i = 0; i < length; i++) { 19 | // for( int j = i+1; j < length; j++) { 20 | // ans = max(ans, (j-i)*min(container[i], container[j])); 21 | // } 22 | // } 23 | 24 | int left = 0, right = length-1; 25 | 26 | while(left < right) { 27 | ans = max(ans, (right - left)*min(container[left], container[right])); 28 | if(container[left] < container[right]) left++; 29 | else right--; 30 | } 31 | 32 | return ans; 33 | } 34 | 35 | int main() { 36 | 37 | vector container = {1,8,6,2,5,4,8,3,7}; 38 | cout << mostWater(container) << endl; 39 | return 0; 40 | } -------------------------------------------------------------------------------- /Arrays/one_edit_distance.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file one_edit_distance.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-26 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | bool isOneEditDistanceStrings(string s, string t) { 16 | map charSet; 17 | int numOfRemovalChars = 0, numOfInsertionChars = 0; 18 | for(auto ch : t) { 19 | charSet[ch]++; 20 | } 21 | 22 | for(auto y : s) { 23 | charSet[y]--; 24 | } 25 | 26 | for(auto x : charSet) { 27 | if(x.second < 0) numOfRemovalChars--; 28 | else if (x.second > 0) numOfInsertionChars++; 29 | } 30 | 31 | if ( (numOfRemovalChars == -1 && numOfRemovalChars == 0) || (numOfRemovalChars == 0 && numOfInsertionChars == +1) || (numOfRemovalChars == -1 && numOfInsertionChars == +1)) return true; 32 | return false; 33 | } 34 | int main() { 35 | string s = ""; 36 | string t = ""; 37 | cout << isOneEditDistanceStrings(s,t); 38 | return 0; 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Aditya Rana 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /String/simplify_path.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file simplify_path.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-06 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | string simplifyPath(string input) { 16 | string ans; 17 | int length = input.length(); 18 | 19 | stack st; 20 | 21 | for(int i = 0 ; i < length; i++) { 22 | cout << "DEBUG MODE: \t" << "input[" << i+1 << "]" << " " << input[i] << endl; 23 | if(input[i] == '.') continue; 24 | if(!st.empty()) { 25 | if(st.top() == '/' && input[i] == '/') { 26 | continue; 27 | } 28 | else { 29 | st.push(input[i]); 30 | cout << "input : " << input[i] << endl; 31 | } 32 | } 33 | } 34 | ans.clear(); 35 | while(!st.empty()) { 36 | ans += st.top(); 37 | st.pop(); 38 | } 39 | 40 | reverse(ans.begin(), ans.end()); 41 | 42 | return ans; 43 | } 44 | 45 | int main() { 46 | string str = "/path/"; 47 | cout << simplifyPath(str) << endl; 48 | 49 | return 0; 50 | } -------------------------------------------------------------------------------- /technical-screening-round/README.md: -------------------------------------------------------------------------------- 1 | ## Technical Screening Round 2 | 3 | This technical Screening round consists of 2 coding questions - one easy to medium level and one from medium to hard level. 4 | 5 | Interview took place online on zoom and there were 2 interviewers one was taking screening and other was observing it. 6 | 7 | #### Tips to ace online technical screening: 8 | - Be active during the interview 9 | - ask all your clarifications / doubts about the interview question 10 | - tell your approach to the interviewer along with time and space complexity and ask if you can start coding or not 11 | - Dry run your code before getting started with code part and test your code with same / different test case(s) 12 | - Explain everything like you are telling to you 5year old sibling 13 | - Be ready for the Edge / Corner cases where your code can be failed (interviewer will ask this for sure) 14 | - technical Screening rounds are not that much hard what people think about it, do atleast Standard Coding Questions and basic implementation of basic algorithms and data-structures should be handy 15 | - Focus more on Arrays, Strings, LinkedList, Trees, Graphs, BFS, DFS. 16 | - Read past interview experiences at Meta (formerly facebook) -------------------------------------------------------------------------------- /StandardQuestions/DP/subset_sum.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file subset_sum.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-19 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | bool dp[1024][1024]; 16 | 17 | void printDP(int x, int y) { 18 | for(int i = 0; i <= x; i++){ 19 | for(int j = 0; j <= y; j++) 20 | cout << dp[i][j] << "\t"; 21 | cout << endl; 22 | } 23 | } 24 | 25 | int subset_sum(vector input, int targetSum, int size) { 26 | for(int i = 1; i <= targetSum; i++) 27 | dp[0][i] = false; 28 | for(int i = 0; i <= size; i++) 29 | dp[i][0] = true; 30 | 31 | for(int i = 1; i <= size; i++) { 32 | for(int j = 1; j <= targetSum; j++) { 33 | if(input[i-1] <= j) { 34 | dp[i][j] = (dp[i-1][j-input[i-1]] || dp[i-1][j]); 35 | } else { 36 | dp[i][j] = dp[i-1][j]; 37 | } 38 | } 39 | } 40 | //printDP(size, targetSum); 41 | return dp[size][targetSum]; 42 | } 43 | 44 | int main() { 45 | vector arr = {2,3,5,7,8,1}; 46 | memset(dp, false, sizeof(dp)); 47 | cout << subset_sum(arr, 10, 6) << endl; 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Miscellneous/string_tokenization.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file string_tokenization.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-29 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | #include 12 | using namespace std; 13 | 14 | char* STRTOK(char* str, char delim) { 15 | static char* input = NULL; 16 | 17 | if(str!=NULL) { 18 | // initialization of static character array 19 | input = str; 20 | } 21 | 22 | if(input == NULL) { 23 | return NULL; 24 | } 25 | 26 | // Tokenization 27 | char* output = new char[strlen(input)+1]; 28 | int index = 0; 29 | 30 | for(; input[index] != '\0'; index++) { 31 | 32 | if(input[index] != delim) { 33 | output[index] = input[index]; 34 | } else { 35 | output[index] = '\0'; 36 | input = input + index + 1; 37 | return output; 38 | } 39 | } 40 | 41 | output[index] = '\0'; 42 | input = NULL; 43 | return output; 44 | 45 | } 46 | 47 | 48 | int main() { 49 | 50 | char s[] = "Today is a sunny day"; 51 | char* ptr = STRTOK(s, ' '); 52 | 53 | while(ptr !=NULL) { 54 | cout << ptr << endl; 55 | ptr = STRTOK(NULL, ' '); 56 | } 57 | 58 | return 0; 59 | } -------------------------------------------------------------------------------- /Arrays/valid_palindrome_2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file valid_palindrome_2.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-26 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * Given a string s, return true if the s can be palindrome after deleting at most one character from it. 16 | * 17 | * Test Cases: 18 | * 19 | * #1: 20 | * Input: s = "aba" 21 | * Output: true 22 | * 23 | * #2: 24 | * Input: s = "abca" 25 | * Output: true 26 | * Explanation: You could delete the character 'c'. 27 | * 28 | * #3: 29 | * Input: s = "abc" 30 | * Output: false 31 | * 32 | * Constraints: 33 | * - 1 <= s.length <= 105 34 | * - s consists of lowercase English letters. 35 | * 36 | */ 37 | 38 | #include 39 | using namespace std; 40 | 41 | // solution using Map 42 | bool validpalindrome(string input) { 43 | map charSet; 44 | int numOfRemovals = 0; 45 | for(auto x : input) { 46 | charSet[x]++; 47 | } 48 | for(auto ch : charSet) { 49 | if(ch.second < 2) { numOfRemovals++; } 50 | } 51 | 52 | if(numOfRemovals > 2) return false; 53 | return true; 54 | } 55 | 56 | 57 | 58 | int main() { 59 | string input = "abca"; 60 | cout << validpalindrome(input); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /Arrays/3sum_closest.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3sum_closest.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-07 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | int ThreeSumClosest(vector nums, int target) { 16 | int length = nums.size(); 17 | int ans = INT_MIN; 18 | sort(nums.begin(), nums.end()); 19 | int k = 0; 20 | int currentSum = 0; 21 | int minDiff = INT_MAX; 22 | int left = 0, right = length-1; 23 | 24 | while(left < right) { 25 | k = 0; 26 | while(k < length) { 27 | if(k == left || k == right) { 28 | k++; 29 | continue; 30 | } 31 | currentSum = nums[left] + nums[right] + nums[k]; 32 | if(minDiff > abs(currentSum - target)) { 33 | minDiff = abs(currentSum - target); 34 | ans = currentSum; 35 | } 36 | k++; 37 | } 38 | 39 | if(ans == target){ 40 | break; 41 | } 42 | else if(ans > target){ 43 | right--; 44 | } else { 45 | left++; 46 | } 47 | } 48 | 49 | return ans; 50 | 51 | } 52 | 53 | int main() { 54 | vector input = {-1,2,1,-4}; 55 | int target = 2; 56 | cout << ThreeSumClosest(input, target); 57 | return 0; 58 | } -------------------------------------------------------------------------------- /StandardQuestions/DP/equal_sum_partition.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file equal_sum_partition.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-20 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | bool dp[100][100]; 16 | 17 | void printDP(int x, int y) { 18 | for(int i = 0; i <= x; i++){ 19 | for(int j = 0; j <= y; j++) 20 | cout << dp[i][j] << "\t"; 21 | cout << endl; 22 | } 23 | } 24 | 25 | bool isEqualSumpartitionPossible(vector arr) { 26 | int sum = 0; 27 | int size = arr.size(); 28 | sum = accumulate(arr.begin(), arr.end(), sum); 29 | 30 | // odd sum can never be subdivided into two equal integer parts 31 | if(sum%2 !=0) return false; 32 | 33 | for(int i = 0; i <= size; i++) 34 | dp[0][i] = false; 35 | for(int i = 0; i <= sum/2; i++) 36 | dp[i][0] = true; 37 | 38 | for(int i = 1; i<= size; i++) { 39 | for(int j = 1; j <= sum/2; j++) { 40 | if(arr[i-1] <= j) 41 | dp[i][j] = (dp[i-1][j-arr[i-1]] || dp[i-1][j]); 42 | else 43 | dp[i][j] = dp[i-1][j]; 44 | } 45 | } 46 | 47 | //printDP(size, sum/2); 48 | return dp[size][sum/2]; 49 | } 50 | 51 | int main() { 52 | memset(dp, false, sizeof(dp)); 53 | vector arr = {2,4,6,8,10,10}; 54 | cout << isEqualSumpartitionPossible(arr) << endl; 55 | return 0; 56 | } -------------------------------------------------------------------------------- /Tree/connect_node_at_same_level.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file connect_node_at_same_level.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-02 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | struct Node { 16 | int value; 17 | Node* left; 18 | Node* right; 19 | Node* nextRight; 20 | 21 | Node(int val) { 22 | this->value = val; 23 | left = nullptr; 24 | right = nullptr; 25 | nextRight = nullptr; 26 | } 27 | }; 28 | 29 | void connectNodeAtSameLevel(Node* root) { 30 | queue q; 31 | q.push(root); 32 | q.push(nullptr); 33 | 34 | while(!q.empty()) { 35 | Node* ptr = q.front(); 36 | q.pop(); 37 | 38 | if(ptr != nullptr) { 39 | ptr->nextRight = q.front(); 40 | 41 | if(root->left != nullptr) q.push(root->left); 42 | if(root->right!= nullptr) q.push(root->right); 43 | 44 | }else if(!q.empty()){ 45 | q.push(nullptr); 46 | } 47 | } 48 | } 49 | 50 | int main() { 51 | Node* root = new Node(20); 52 | root->left = new Node(8); 53 | root->right = new Node(22); 54 | root->left->left = new Node(4); 55 | root->left->right = new Node(12); 56 | root->left->right->left = new Node(10); 57 | root->left->right->right = new Node(14); 58 | 59 | connectNodeAtSameLevel(root); 60 | return 0; 61 | } -------------------------------------------------------------------------------- /Map/longest_palindrome_by_concatenating_two_letter_words.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file longest_palindrome_by_concatenating_two_letter_words.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-15 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | int longestPalindrome(vector words) { 16 | map wordmap; 17 | int palindromeLength = 0; 18 | bool reached = false; 19 | for(auto w : words) 20 | wordmap[w]++; 21 | 22 | for(auto x : wordmap) { 23 | if(x.first[0] == x.first[1]) { 24 | if(x.second % 2 && !reached) { 25 | reached = true; 26 | palindromeLength += 2*x.second; 27 | x.second = 0; 28 | } else if(x.second%2 == 0) { 29 | palindromeLength += 2*x.second; 30 | x.second = 0; 31 | } 32 | } else { 33 | string temp = x.first; 34 | reverse(temp.begin(), temp.end()); 35 | if(wordmap.find(temp) != wordmap.end()) { 36 | int m = min(wordmap[temp], x.second); 37 | palindromeLength += m*4; 38 | x.second -= m; 39 | wordmap[temp] -= m; 40 | } 41 | } 42 | } 43 | return palindromeLength; 44 | } 45 | 46 | int main() { 47 | vector words = {"cc","ll","xx"}; 48 | cout << longestPalindrome(words) << endl; 49 | return 0; 50 | } -------------------------------------------------------------------------------- /Tree/kth_largest_in_BST.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file kth_largest_in_BST.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-02 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | struct Node { 16 | int value; 17 | Node* left; 18 | Node* right; 19 | 20 | Node(int val) { 21 | this->value = val; 22 | left = nullptr; 23 | right = nullptr; 24 | } 25 | }; 26 | 27 | void printInorderBST(Node* root) { 28 | if(root == nullptr) 29 | return; 30 | 31 | printInorderBST(root->left); 32 | cout << root->value << " "; 33 | printInorderBST(root->right); 34 | } 35 | 36 | void kthLargestInBST(Node* root, int k, int& counter) { 37 | if(root == nullptr || counter >= k) 38 | return; 39 | 40 | kthLargestInBST(root->right, k, counter); 41 | counter++; 42 | if(counter == k) 43 | cout << "Kth smallest elemet is: " << root->value << endl; 44 | kthLargestInBST(root->left, k, counter); 45 | } 46 | 47 | int main() { 48 | Node* root = new Node(20); 49 | root->left = new Node(8); 50 | root->right = new Node(22); 51 | root->left->left = new Node(4); 52 | root->left->right = new Node(12); 53 | root->left->right->left = new Node(10); 54 | root->left->right->right = new Node(14); 55 | 56 | //printInorderBST(root); 57 | cout << endl; 58 | int k = 3; 59 | int c = 0; 60 | kthLargestInBST(root, k, c); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /String/group_shifted_strings.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file group_shifted_strings.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-06 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | string getStringHash(string str) { 16 | string ans = ""; 17 | int shift = 0; 18 | 19 | for(int i = 1; i < str.length(); i++) { 20 | shift = str[i] - str[i-1]; 21 | if(shift < 0) shift += 26; 22 | ans += to_string(shift); 23 | } 24 | 25 | return ans; 26 | } 27 | 28 | vector> groupShiftedStrings(vector ip) { 29 | vector> ans(ip.size()); 30 | map> hmap; 31 | string diff = ""; 32 | 33 | for(auto x : ip) { 34 | int len = x.length(); 35 | diff.clear(); 36 | diff = getStringHash(x); 37 | cout << "DEBUG : " << x << "\t" << diff << endl; 38 | hmap[diff].push_back(x); 39 | } 40 | 41 | int i = 0; 42 | 43 | for(auto y : hmap) { 44 | int l = ans[i].size(); 45 | ans[i].insert(ans[i].begin()+l, y.second.begin(), y.second.end()); 46 | i++; 47 | } 48 | 49 | return ans; 50 | } 51 | 52 | int main() { 53 | vector ip = {"abc","bcd","acef","xyz","az","ba","a","z"}; 54 | auto output = groupShiftedStrings(ip); 55 | 56 | for(auto x : output) { 57 | for(auto h : x) 58 | cout << h << "\t"; 59 | cout << endl; 60 | } 61 | 62 | return 0; 63 | } -------------------------------------------------------------------------------- /Sorting/radix_sort.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file radix_sort.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | #include 12 | using namespace std; 13 | 14 | int getMax(vector input) { 15 | int maxElement = input[0]; 16 | int length = input.size(); 17 | 18 | for(int i = 1; i < length; i++) if(input[i] >= maxElement) { maxElement = input[i]; } 19 | 20 | return maxElement; 21 | } 22 | 23 | vector CountingSort(vector input, int exp) { 24 | int length = input.size(); 25 | int index = 0; 26 | vector count(10, 0), output(length,0); 27 | 28 | for(int i = 0; i < length; i++) { 29 | count[(input[i]/exp)%10]++; 30 | } 31 | 32 | for(int i = 1; i < 10; i++) 33 | count[i] += count[i-1]; 34 | 35 | for(int i = length-1; i >= 0; i--) { 36 | index = (input[i]/exp)%10; 37 | output[count[index]-1] = input[i]; 38 | count[index]--; 39 | } 40 | return output; 41 | } 42 | vector RadixSort(vector input) { 43 | vector output; 44 | int exp = 1; 45 | 46 | int maxelement = getMax(input); 47 | 48 | for( exp = 1; maxelement/exp > 0; exp *= 10) { 49 | output = CountingSort(input, exp); 50 | } 51 | 52 | return output; 53 | } 54 | 55 | int main() { 56 | vector input = {20, 30, 21, 1, 31, 32, 12, 23}; 57 | auto sortedInput = RadixSort(input); 58 | 59 | for(auto x : sortedInput) { 60 | cout << x << endl; 61 | } 62 | 63 | return 0; 64 | } -------------------------------------------------------------------------------- /SegmentTree/segment_tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file segment_tree.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-06 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | // range is = [lx,rx) 16 | struct SegTree { 17 | 18 | int size; 19 | vector sums; 20 | 21 | void init(int n) { 22 | size = 1; 23 | while(size < n) size *= 2; 24 | sums.assign(2 * size, 0LL); 25 | } 26 | 27 | void set(int i , int v, int x, int lx, int rx) { 28 | if(rx-lx == 1) { 29 | sums[x] = v; 30 | return; 31 | } 32 | int m = (lx+rx)/2; 33 | if(i < m) { 34 | set(i,v,2*x+1, lx, m); 35 | }else { 36 | set(i,v,2*x+2,m,rx); 37 | } 38 | sums[x] = sums[2*x+1] + sums[2*x+2]; 39 | } 40 | 41 | void set(int i , int v) { 42 | set(i,v,0,0,size); 43 | } 44 | 45 | long long sum(int l, int r, int x, int lx, int rx) { 46 | if(lx >= r || l >= rx) return 0; 47 | if(lx >= l && rx <= r) return sums[x]; 48 | int m = (lx+rx)/2; 49 | long long s1 = sum(l,r,2*x+1,lx,m); 50 | long long s2 = sum(l,r,2*x+2,m,rx); 51 | return s1+s2; 52 | } 53 | 54 | long long sum(int l, int r) { 55 | return sum(l, r, 0, 0, size); 56 | } 57 | }; 58 | 59 | int main() { 60 | SegTree st; 61 | int n = 5; 62 | st.init(n); 63 | for(int i =0 ; i < n; i++) { 64 | st.set(i, i+1); 65 | } 66 | cout << st.sum(0,5) << endl; 67 | return 0; 68 | } -------------------------------------------------------------------------------- /Miscellneous/comparators.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file comparators.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-29 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | // if a > b then returns true and it swapping will happen in the sorting function. That's ascending sorting my boi ! 16 | bool comparator(int a, int b) { 17 | cout << "executing the comaparator: \t" << "a: " << a << "\t" << "b: " << b << endl; 18 | return a > b; 19 | } 20 | 21 | void bubble_sort(vector& input, bool (&cmp) (int a, int b)) { 22 | int length = input.size(); 23 | for(int i = 0; i < length-1; i++) 24 | for(int j = 0; j < length - i - 1; j++) { 25 | if(cmp(input[j], input[j+1])) { 26 | swap(input[j], input[j+1]); 27 | } 28 | } 29 | } 30 | 31 | // comparator for lower_bound 32 | bool lb_comparator(int a, int b) { 33 | return a <= b; 34 | } 35 | 36 | int main() { 37 | vector input = {5,4,3,2,1}; 38 | bubble_sort(input, comparator); 39 | for(auto x : input) cout << x << " "; 40 | 41 | 42 | // we can use comparators to reverse the logic of the lower_bound() as well ! 43 | vector money = {10,20,30,40,50,60,70,80,90}; 44 | int key = 55; 45 | // lower_bound() gives ">=" comparison" 46 | // so here output will be 60 47 | int lb_index = lower_bound(money.begin(), money.end(), key) - money.begin(); 48 | cout << endl << money[lb_index] << endl; 49 | 50 | int lb_modified_index = lower_bound(money.begin(), money.end(), key, lb_comparator) - money.begin(); 51 | cout << "Modified search via lower_bound" << endl << money[lb_modified_index] << endl; 52 | return 0; 53 | } -------------------------------------------------------------------------------- /Arrays/first_missing_positive.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file first_missing_positive.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-12 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | 13 | /** 14 | * Problem: 15 | * 16 | * Given an unsorted integer array nums, return the smallest missing positive integer. 17 | * 18 | * You must implement an algorithm that runs in O(n) time and uses constant extra space. 19 | * 20 | * #1: 21 | * 22 | * Input: nums = [1,2,0] 23 | * 24 | * Output: 3 25 | * 26 | * #2: 27 | * 28 | * Input: nums = [3,4,-1,1] 29 | * 30 | * Output: 2 31 | * 32 | * #3: 33 | * 34 | * Input: nums = [7,8,9,11,12] 35 | * 36 | * Output: 1 37 | * 38 | */ 39 | #include 40 | using namespace std; 41 | 42 | pair getMax(vector ip) { 43 | int mx = INT_MIN; 44 | int mn = INT_MAX; 45 | for(auto x : ip){ 46 | if(x < 0) continue; 47 | if(x >= mx) mx = x; 48 | else if(x <= mn) mn = x; 49 | } 50 | return {mn, mx}; 51 | } 52 | 53 | int firstMissingPositive(vector input) { 54 | int length = input.size(); 55 | 56 | auto minMaxPair = getMax(input); 57 | map hmap; 58 | 59 | for(int i = (minMaxPair.first > 0 ? 1 : 0); i <= minMaxPair.second; i++) { 60 | hmap[i] = 0; 61 | } 62 | 63 | for(auto x : input) { 64 | if(x < 0) continue; 65 | 66 | hmap[x]++; 67 | } 68 | 69 | for(auto k : hmap) { 70 | if(k.second == 0) return k.first; 71 | } 72 | 73 | // if no element is found then return maximum + 1 (acc to question) 74 | return minMaxPair.second+1; 75 | } 76 | int main() { 77 | 78 | vector arr = {3,4,-1,1}; 79 | cout << firstMissingPositive(arr) << endl; 80 | return 0; 81 | } -------------------------------------------------------------------------------- /Tree/zigzag_traversal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file zigzag_traversal.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-02 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | struct Node { 16 | int value; 17 | Node* left; 18 | Node* right; 19 | 20 | Node(int val) { 21 | this->value = val; 22 | left = nullptr; 23 | right = nullptr; 24 | } 25 | }; 26 | 27 | void zigzagTraversal(Node* root) { 28 | stack currentLevel; 29 | stack nextLevel; 30 | bool leftToRight = true; 31 | 32 | currentLevel.push(root); 33 | 34 | while(!currentLevel.empty()) { 35 | Node* ptr = currentLevel.top(); 36 | currentLevel.pop(); 37 | 38 | if(ptr != nullptr) { 39 | cout << ptr->value << " "; 40 | 41 | if(leftToRight){ 42 | if(ptr->left != nullptr) nextLevel.push(ptr->left); 43 | if(ptr->right != nullptr) nextLevel.push(ptr->right); 44 | } else { 45 | if(ptr->right != nullptr) nextLevel.push(ptr->right); 46 | if(ptr->left != nullptr) nextLevel.push(ptr->left); 47 | } 48 | } 49 | 50 | if(currentLevel.empty()) { 51 | leftToRight = !leftToRight; 52 | swap(currentLevel, nextLevel); 53 | } 54 | } 55 | } 56 | 57 | int main() { 58 | Node* root = new Node(20); 59 | root->left = new Node(8); 60 | root->right = new Node(22); 61 | root->left->left = new Node(4); 62 | root->left->right = new Node(12); 63 | root->left->right->left = new Node(10); 64 | root->left->right->right = new Node(14); 65 | 66 | zigzagTraversal(root); 67 | 68 | return 0; 69 | } -------------------------------------------------------------------------------- /Arrays/subarray_sum_equals_k.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sunarray_sum_equals_k.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-28 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | int numberOfSubArraySumEqualsToK(vector input, int k) { 16 | int numOfValidSubArrays = 0; 17 | int start = 0, end = 0; 18 | int lengthOfInput = input.size(); 19 | int currentSum = 0; 20 | 21 | if(lengthOfInput < 2) { 22 | if(input[0] == k) return 1; 23 | else return 0; 24 | } 25 | 26 | while(start <= end && end < lengthOfInput) { 27 | if(start == end) { 28 | if(currentSum + input[start] < k) { 29 | currentSum += input[start]; 30 | end++; 31 | } else if( currentSum + input[end] == k) { 32 | numOfValidSubArrays++; 33 | currentSum -= input[start]; 34 | start++; 35 | } else { 36 | start++; 37 | end++; 38 | } 39 | continue; 40 | } 41 | 42 | if(currentSum + input[end] < k) { 43 | currentSum += input[end]; 44 | end++; 45 | continue; 46 | } else if(currentSum + input[end] == k) { 47 | numOfValidSubArrays++; 48 | currentSum -= input[start]; 49 | start++; 50 | continue; 51 | } else if(currentSum + input[end] > k) { 52 | currentSum -= input[start]; 53 | start++; 54 | continue; 55 | } 56 | } 57 | 58 | return numOfValidSubArrays; 59 | } 60 | 61 | int main() { 62 | //vector input = {1,1,1}; 63 | vector input = {1,2,3}; 64 | int k = 3; 65 | int output = numberOfSubArraySumEqualsToK(input, k); 66 | cout << output; 67 | return 0; 68 | } -------------------------------------------------------------------------------- /PatternSearching/KMP.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file KMP.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | vector computeTemporaryArray(string input) { 16 | int inputLength = input.length(); 17 | vector lps(inputLength, 0); 18 | 19 | int index = 0; 20 | 21 | for(int i = 1; i < inputLength;) { 22 | if(input[i] == input[index]) { 23 | lps[i] = index+1; 24 | index++; 25 | i++; 26 | } else { 27 | if(index != 0) { 28 | index = lps[index-1]; 29 | } else { 30 | lps[i] = 0; 31 | i++; 32 | } 33 | } 34 | } 35 | return lps; 36 | } 37 | 38 | vector KMPSearch(string text, string pattern) { 39 | vector lps = computeTemporaryArray(pattern); 40 | vector ans; 41 | int i = 0; 42 | int j = 0; 43 | int textLength = text.length(); 44 | int patternLength = pattern.length(); 45 | while(i < textLength && j < patternLength) { 46 | if(text[i] == pattern[j]) { 47 | i++; 48 | j++; 49 | } 50 | if(j == patternLength) { 51 | //cout << "index: " << i-j << endl; 52 | ans.push_back(i-j); 53 | j = lps[j-1]; 54 | }else if(i < textLength && pattern[j] != text[i]) { 55 | if(j != 0) { 56 | j = lps[j-1]; 57 | }else { 58 | i++; 59 | } 60 | } 61 | } 62 | return ans; 63 | } 64 | int main() { 65 | string text = "foxfoxfox"; 66 | string pattern = "fox"; 67 | auto kmp = KMPSearch(text, pattern); 68 | for(auto x : kmp) { 69 | cout << x << "\t"; 70 | } 71 | return 0; 72 | } -------------------------------------------------------------------------------- /PatternSearching/RabinKarp.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file RabinKarp.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-03 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | long long calculateHash(string text, int start, int end, int prime) { 16 | long long hash; 17 | 18 | for(int i = start; i <= end; i++) { 19 | hash += text[i]*pow(prime, i); 20 | } 21 | return hash; 22 | } 23 | 24 | long long reCalculateHash(string text, long long oldHash, int start, int end, int prime) { 25 | long long rehash; 26 | rehash = ((oldHash - text[start-1])/prime) + (text[end]*pow(prime, end-start)); 27 | return rehash; 28 | } 29 | 30 | int RabinKarpSearch(string input, string pattern) { 31 | int inputLength = input.length(); 32 | int patternLength = pattern.length(); 33 | int prime = 3; 34 | long long patternHash = calculateHash(pattern, 0, patternLength-1, prime); 35 | long long inputHash = calculateHash(input, 0, patternLength-1, prime); 36 | 37 | for(int i = 0; i < inputLength-patternLength+1; i++) { 38 | if(patternHash == inputHash) { 39 | bool ok = true; 40 | for(int k = 0; k < patternLength; k++) { 41 | if(pattern[k] != input[k+i]) {ok = false; break;} 42 | } 43 | if(ok) cout << i << endl; 44 | } 45 | if(i < inputLength-patternLength+1) { 46 | inputHash = reCalculateHash(input, inputHash, i+1, i + patternLength -1, prime); 47 | //inputHash = calculateHash(input, i+1, i+patternLength, prime); 48 | cout << inputHash << "\t"; 49 | } 50 | } 51 | return -1; 52 | } 53 | 54 | int main() { 55 | string input = "foxfoxfoxfox"; 56 | string pattern = "fox"; 57 | RabinKarpSearch(input, pattern); 58 | return 0; 59 | } -------------------------------------------------------------------------------- /SuffixArray/suffix_array.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file suffix_array.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | 16 | // Time Complexity - O(nlog^2(n)) 17 | // space complexity - O(n) 18 | void generateSuffixArray(string input) { 19 | input += "$"; 20 | int n = input.length(); 21 | vector p(n), c(n); 22 | 23 | { 24 | //k = 0 25 | vector> a(n); 26 | for(int i = 0; i < n; i++) a[i] = {input[i], i}; 27 | 28 | sort(a.begin(), a.end()); 29 | 30 | for(int i = 0; i < n ; i++) p[i] = a[i].second; 31 | 32 | c[p[0]] = 0; 33 | 34 | for(int i = 1; i < n ; i++) { 35 | if(a[i].first == a[i-1].first) { 36 | c[p[i]] = c[p[i-1]]; 37 | } else { 38 | c[p[i]] = c[p[i-1]] + 1; 39 | } 40 | } 41 | } 42 | 43 | int k = 0; 44 | while((1 << k) < n) { 45 | // k -> k+1 transitions 46 | vector, int>> a(n); 47 | for( int i =0 ; i < n; i++) { 48 | a[i] = {{c[i], c[(i + (1 << k))%n]}, i}; 49 | } 50 | sort(a.begin(), a.end()); 51 | 52 | for(int i = 0; i < n ; i++) p[i] = a[i].second; 53 | 54 | c[p[0]] = 0; 55 | 56 | for(int i = 1; i < n ; i++) { 57 | if(a[i].first == a[i-1].first) { 58 | c[p[i]] = c[p[i-1]]; 59 | } else { 60 | c[p[i]] = c[p[i-1]] + 1; 61 | } 62 | } 63 | k++; 64 | } 65 | 66 | for(int i = 0; i < n; i++) 67 | cout << p[i] << "\t" << input.substr(p[i], n-p[i]) << endl; 68 | } 69 | 70 | int main() { 71 | string input = "ababba"; 72 | generateSuffixArray(input); 73 | return 0; 74 | } -------------------------------------------------------------------------------- /String/number_of_matching_subsequences.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file number_of_matching_subsequences.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-08 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * @link https://leetcode.com/problems/number-of-matching-subsequences/ 16 | * 17 | * Given a string s and an array of strings words, return the number of words[i] that is a subsequence of s. 18 | * 19 | * A subsequence of a string is a new string generated from the original string with some characters 20 | * (can be none) deleted without changing the relative order of the remaining characters. 21 | * 22 | * Test Cases: 23 | * 24 | * #1: 25 | * 26 | * Input: s = "abcde", words = ["a","bb","acd","ace"] 27 | * 28 | * Output: 3 29 | * 30 | * Explanation: There are three strings in words that are a subsequence of s: "a", "acd", "ace". 31 | * 32 | * 33 | * #2: 34 | * 35 | * Input: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"] 36 | * 37 | * Output: 2 38 | * 39 | * 40 | */ 41 | #include 42 | using namespace std; 43 | 44 | int NumberOfMatchingSubseq(string S, vector& words) { 45 | vector waiting[128]; 46 | for (auto &w : words) 47 | waiting[w[0]].push_back(w.c_str()); 48 | 49 | // for(auto x: waiting) { 50 | // for(auto y : x) 51 | // cout << y << " "; 52 | 53 | // cout << endl; 54 | // } 55 | 56 | for (char c : S) { 57 | auto advance = waiting[c]; 58 | waiting[c].clear(); 59 | for (auto it : advance) 60 | waiting[*++it].push_back(it); 61 | } 62 | return waiting[0].size(); 63 | } 64 | 65 | int main() { 66 | vector input = {"a","bb","acd","ace"}; 67 | string s = "abcde"; 68 | int output = NumberOfMatchingSubseq(s, input); 69 | cout << output << endl; 70 | return 0; 71 | } -------------------------------------------------------------------------------- /Trie/sorting_array_of_strings.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sorting_array_of_strings.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | #define CHARSET_SIZE 26 16 | 17 | struct TrieNode { 18 | struct TrieNode *children[CHARSET_SIZE]; 19 | int index; 20 | 21 | TrieNode() { 22 | for(int i = 0; i < CHARSET_SIZE; i++) 23 | this->children[i] = NULL; 24 | 25 | this->index = -1; 26 | } 27 | }; 28 | 29 | void insertIntoTrie(TrieNode *root, string key, int input_index) { 30 | int keyLength = key.length(); 31 | 32 | TrieNode *crawlerNode = root; 33 | 34 | for(int i = 0; i < keyLength; i++) { 35 | int ind = key[i] - 'a'; 36 | 37 | if(!crawlerNode->children[ind]) 38 | crawlerNode->children[ind] = new TrieNode(); 39 | 40 | crawlerNode = crawlerNode->children[ind]; 41 | } 42 | 43 | crawlerNode->index = input_index; 44 | } 45 | 46 | void preOrderInTrie(TrieNode *root, vector keychain) { 47 | if(root == NULL) 48 | return; 49 | 50 | for(int i = 0; i < CHARSET_SIZE; i++) { 51 | if(root->children[i] != NULL) { 52 | if(root->children[i]->index != -1) { 53 | cout << keychain[root->children[i]->index] << endl; 54 | } 55 | preOrderInTrie(root->children[i], keychain); 56 | } 57 | } 58 | } 59 | 60 | TrieNode *getTrieNode() { 61 | TrieNode *tmpNode = new TrieNode(); 62 | return tmpNode; 63 | } 64 | 65 | int main() { 66 | 67 | vector keychain = {"aditya", "rana", "is", "a", "billionare"}; 68 | 69 | TrieNode *root = new TrieNode(); 70 | 71 | for(int i = 0; i < keychain.size(); i++) { 72 | insertIntoTrie(root, keychain[i], i); 73 | } 74 | 75 | preOrderInTrie(root, keychain); 76 | return 0; 77 | } -------------------------------------------------------------------------------- /Trie/trie.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file trie.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | #define ALPHABET_SIZE 26 16 | 17 | struct TrieNode { 18 | struct TrieNode *children[ALPHABET_SIZE]; 19 | bool isEndOfWord; 20 | 21 | TrieNode() { 22 | isEndOfWord = false; 23 | for(int i = 0; i < ALPHABET_SIZE; i++) 24 | this->children[i] = NULL; 25 | } 26 | }; 27 | 28 | TrieNode *getTrieNode() { 29 | TrieNode *tmpNode = new TrieNode(); 30 | return tmpNode; 31 | } 32 | 33 | void insertIntoTrie(TrieNode *root, string key) { 34 | TrieNode *crawlerNode = root; 35 | int keyLength = key.length(); 36 | 37 | for(int i = 0; i < keyLength; i++) { 38 | int index = key[i] - 'a'; 39 | if(!crawlerNode->children[index]) { 40 | crawlerNode->children[index] = getTrieNode(); 41 | } 42 | 43 | crawlerNode = crawlerNode->children[index]; 44 | } 45 | 46 | crawlerNode->isEndOfWord = true; 47 | } 48 | 49 | bool searchInTrie(TrieNode *root, string key) { 50 | int keyLength = key.length(); 51 | TrieNode *crawlerNode = root; 52 | for(int i = 0; i < keyLength; i++) { 53 | int index = key[i] - 'a'; 54 | if(!crawlerNode->children[index]) 55 | return false; 56 | 57 | crawlerNode = crawlerNode->children[index]; 58 | } 59 | 60 | return crawlerNode->isEndOfWord; 61 | } 62 | 63 | int main() { 64 | vector keychain = {"hi", "there", "how", "are", "you"}; 65 | TrieNode *root = new TrieNode(); 66 | for(auto x : keychain) 67 | insertIntoTrie(root, x); 68 | 69 | for(auto y : keychain) 70 | cout << " IS " << y << " there in Trie: " << searchInTrie(root, y) << endl; 71 | 72 | cout << "random guess for \" timex \" : " << searchInTrie(root, "timex") << endl; 73 | return 0; 74 | } -------------------------------------------------------------------------------- /PatternSearching/Z_Algorithm.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Z_Algorithm.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-03 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | vector calculateZArray(string input) { 16 | int inputLength = input.length(); 17 | //cout << "length: " << inputLength; 18 | vector Z(inputLength, 0); 19 | int left = 0; 20 | int right = 0; 21 | 22 | for(int k = 1; k < inputLength; k++) { 23 | if(k > right) { 24 | left = right = k; 25 | while(right < inputLength && input[right] == input[right-left]) { 26 | right++; 27 | } 28 | Z[k] = right - left; 29 | right--; 30 | } 31 | else { 32 | int k1 = k - left; 33 | if(Z[k1] < right - k +1) { 34 | Z[k] = Z[k1]; 35 | } 36 | else { 37 | left = k; 38 | while(right < inputLength && input[right] == input[right-left]) { 39 | right++; 40 | } 41 | Z[k] = right - left; 42 | right--; 43 | } 44 | } 45 | } 46 | // for(auto x : Z) 47 | // cout << x << "\t"; 48 | return Z; 49 | } 50 | 51 | vector ZPatternMatching(string text, string pattern) { 52 | int patternLength = pattern.length(); 53 | string input = pattern + "$" + text; 54 | 55 | vector ZArray = calculateZArray(input); 56 | int ZArrayLength = ZArray.size(); 57 | vector ZIndices; 58 | 59 | for(int index = 0; index < ZArrayLength; index++) { 60 | if(ZArray[index] == patternLength) ZIndices.push_back(index - patternLength - 1); 61 | } 62 | return ZIndices; 63 | } 64 | 65 | int main() { 66 | string text = "foxfoxfox"; 67 | string pattern = "fox"; 68 | auto Z = ZPatternMatching(text, pattern); 69 | for(auto x : Z) 70 | cout << x << endl; 71 | return 0; 72 | } -------------------------------------------------------------------------------- /String/shortest_palindrome.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file shortest_palindrome.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-13 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | bool isValidPalindromeInBetween(string word, int start, int end) { 16 | while(start < end) { 17 | if(word[start] != word[end]) return false; 18 | else { 19 | start++; 20 | end--; 21 | } 22 | } 23 | return true; 24 | } 25 | 26 | string reverseString(string &str, int start, int end){ 27 | reverse(str.begin() + start, str.begin()+end); 28 | 29 | return str; 30 | } 31 | 32 | string shortestPalindrome(string input) { 33 | string output = ""; 34 | int ipLength = input.length(); 35 | int i = 0; 36 | 37 | for(i = 0; i < ipLength; i++) { 38 | if(isValidPalindromeInBetween(input, 0, ipLength-1-i)){ 39 | cout << "i: " << i << endl; 40 | break; 41 | } 42 | } 43 | 44 | if(i == ipLength) output = reverseString(input, 1, ipLength) + input; // input is non-palindromic 45 | else if(i == 0) output = input; // input is already palindromic 46 | else output = reverseString(input, ipLength-i, ipLength-1); 47 | return output; 48 | } 49 | 50 | // KMP lookup is used here 51 | string shortestPalindromeKMP(string input) { 52 | string output; 53 | int ipLength = input.length(); 54 | string rev(input); 55 | reverse(rev.begin(), rev.end()); 56 | //cout << "rev: " << rev << "\n"; 57 | string str = input + "#" + rev; 58 | int strLength = str.length(); 59 | 60 | vector f(strLength, 0); 61 | int t = 0; 62 | 63 | for(int i = 1; i < strLength; i++) { 64 | t = f[i-1]; 65 | 66 | while(t > 0 && str[i] != str[t]) { 67 | t = f[t-1]; 68 | } 69 | 70 | if(str[i] == str[t]) 71 | ++t; 72 | 73 | f[i] = t; 74 | } 75 | 76 | output = rev.substr(0, ipLength-f[strLength-1])+input; 77 | return output; 78 | } 79 | 80 | int main() { 81 | string str = "aacecaaa"; 82 | cout << shortestPalindromeKMP(str) << endl; 83 | return 0; 84 | } -------------------------------------------------------------------------------- /onsites-london/README.md: -------------------------------------------------------------------------------- 1 | # Meta London Onsite Interviews 2 | 3 | The number of interview rounds in the onsite (final round) varies according to the applicant to applicant, for me there were total 3 interview rounds : 4 | 1. Behavioural / Manager's round (known as JEDI Round in Facebook) 5 | 2. Coding round 6 | 3. Coding round 7 | 8 | ## JEDI Round 9 | This round mainly revolve around the **situation based problems**, usually a manager from an engineering team take your interview. You can think about it as a Rapid fire round with some situations that you can face while working in an engineering team (non-technical). You can take referrence from the resources, but questions varies according to the interviewer. 10 | 11 | Take good sleep and chill ! 12 | 13 | ## Coding Rounds 14 | Total 2 coding rounds were there, one by WhatsApp Engineer and other by Networking Technical Lead. 15 | 16 | Few observations: 17 | - You will get 15 mins to solve a problem (told by my recruiter and that's fukin true) 18 | - Don't waste time in telling / going from naive to best approach, as this gonna waste your time and you have limited time :'( 19 | - Take sometime to think about the problem, incase you are going blank or getting nervous (or even don't know the brute force) tell your interviewer, he/she will help you out by giving some hints 20 | - In the onsite level rounds interviewers are less interested into language based implementations rather they are more interested into the algorithms you are using to solve the problem or how you are solving or any particular observation / pattern you find 21 | - Think about the corner / edge cases where your solution might fail 22 | - Tell the Time and Space Complexity after solving the problem 23 | 24 | 25 | ### Interview Topics 26 | I am not allowed to reveal the actual questions ! 27 | 28 | Most of the interview questions were of Leetcode Hard level problems :) 29 | 30 | ### Ultimate resource to prepare for Coding rounds: 31 | - [Leetcode Facebook tagged questions](https://leetcode.com/company/facebook/) 32 | - [Frequently asked question in Facebook](https://leetcode.com/explore/interview/card/facebook/) 33 | - Read more about past onsite-interview experiences, [this article](https://yashsriv.org/posts/fb-interview-3/) helped me 34 | -------------------------------------------------------------------------------- /String/minimum_remove_make_valid_parantheses.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file minimum_remove_make_valid_parantheses.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-05 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * @link https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/ 16 | * 17 | * Given a string s of '(' , ')' and lowercase English characters. 18 | * 19 | * Your task is to remove the minimum number of parentheses ( '(' or ')', in any positions ) so that the resulting parentheses string is valid and return any valid string. 20 | * 21 | * Formally, a parentheses string is valid if and only if: 22 | * 23 | * It is the empty string, contains only lowercase characters, or 24 | * 25 | * It can be written as AB (A concatenated with B), where A and B are valid strings, or 26 | * 27 | * It can be written as (A), where A is a valid string. 28 | * 29 | * Test Cases: 30 | * 31 | * 32 | * #1: 33 | * 34 | * Input: s = "lee(t(c)o)de)" 35 | * 36 | * Output: "lee(t(c)o)de" 37 | * 38 | * Explanation: "lee(t(co)de)" , "lee(t(c)ode)" would also be accepted. 39 | * 40 | * #2: 41 | * 42 | * Input: s = "a)b(c)d" 43 | * 44 | * Output: "ab(c)d" 45 | * 46 | */ 47 | 48 | #include 49 | using namespace std; 50 | 51 | string makeValidString(string& str) { 52 | string ans; 53 | int len = str.length(); 54 | queue st; 55 | 56 | for(int i = 0; i < len;) { 57 | if(str[i] == '(') st.push(i); 58 | if(str[i] == ')'){ 59 | if(!st.empty())st.pop(); 60 | else { 61 | str.erase(str.begin()+i); 62 | len--; 63 | continue; 64 | } 65 | } 66 | i++; 67 | } 68 | 69 | //cout << "DEBUG MODE; INPUT: " << str << endl; 70 | 71 | if(!st.empty()) { 72 | int fact=0; 73 | while(!st.empty()) { 74 | int indx = st.front(); 75 | //cout << indx << endl; 76 | st.pop(); 77 | str.erase(str.begin()+indx-fact); 78 | fact++; 79 | } 80 | } 81 | return str; 82 | } 83 | 84 | int main() { 85 | string input = "((()))(("; 86 | string ip = "lee(t(c)o)de)"; 87 | cout << makeValidString(input) << endl; 88 | cout << makeValidString(ip) << endl; 89 | return 0; 90 | } -------------------------------------------------------------------------------- /MonotonicQueue/shortest_subarray_with_sum_atleast_k.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file shortest_subarray_with_sum_atleast_k.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-14 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * We will use prefix sumarray and then traverse it and hold a Increasing Monotonic Queue and on each insert 17 | * we will check if inserting is smaller that means we have a window of elements that have increasing sum but first 18 | * we will check if the last element is greater then the required sum `k` then we will start decreasing elements from 19 | * front of the queue till the sum of the window is still holding the condition of greater then the required `k`. 20 | * We will stop this process when the sum of the window is less than the `k`, just calculate the size of the window by 21 | * doing j-i+1, where `i` is the starting index of the window and `j` is the ending index of the window. Repeat this process 22 | * till the end of the prefix array. 23 | * 24 | * @param input 25 | * @param targetSum 26 | * @return int 27 | */ 28 | int shortestSubarrayWithSumAtleastK(vector input, int targetSum) { 29 | int inputLength = input.size(); 30 | int leastSum = inputLength+1; 31 | deque monoque; 32 | 33 | vector prefixSum(inputLength+1, 0); 34 | prefixSum[0] = input[0]; 35 | 36 | for(int i = 0; i < inputLength; i++) 37 | prefixSum[i+1] = prefixSum[i] + input[i]; 38 | 39 | //for(auto f : prefixSum) cout << f << "\t"; 40 | 41 | int prefixSumLength = prefixSum.size(); 42 | 43 | for(int i = 0; i < prefixSumLength; i++) { 44 | 45 | while(!monoque.empty() && prefixSum[i] <= prefixSum[monoque.back()]) 46 | monoque.pop_back(); 47 | 48 | while(!monoque.empty() && prefixSum[i] - prefixSum[monoque.front()] >= targetSum) { 49 | leastSum = min(leastSum, i-monoque.front()); 50 | // cout << "ls: " << leastSum << endl; 51 | monoque.pop_front(); 52 | } 53 | 54 | monoque.push_back(i); 55 | } 56 | 57 | return leastSum < inputLength+1 ? leastSum : -1; 58 | } 59 | 60 | int main() { 61 | //vector arr = {2,-1,2}; 62 | vector arr = {70,-50,50,50,-70,-10,30,20,30,20}; 63 | cout << shortestSubarrayWithSumAtleastK(arr, 100) << endl; 64 | return 0; 65 | } -------------------------------------------------------------------------------- /Arrays/kth_smallest_element_in_array.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file kth_smallest_element_in_array.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-06 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | int LomutoPartition(vector& ip, int low, int high) { 16 | int pivot = ip[high]; 17 | int i = low; 18 | 19 | for(int j = low; j < high; j++){ 20 | if(ip[j] < pivot){ 21 | if(i != j) { 22 | swap(ip[i], ip[j]); 23 | } 24 | i++; 25 | } 26 | } 27 | swap(ip[i], ip[high]); 28 | return i; 29 | } 30 | 31 | int HoaresPartition(vector ip, int low, int high) { 32 | int pivot = ip[low]; 33 | int i = low-1; 34 | int j = high+1; 35 | 36 | while(true) { 37 | do{ 38 | i++; 39 | }while(ip[i] < pivot); 40 | 41 | do{ 42 | j--; 43 | }while(ip[j] > pivot); 44 | 45 | if(i >= j){ 46 | return j; 47 | } 48 | 49 | swap(ip[i], ip[j]); 50 | } 51 | return -1; 52 | } 53 | 54 | int KthSmallestLomutoPartitioning(vector input, int left, int right, int k) { 55 | if(left == right) 56 | return input[left]; 57 | 58 | int pivotIndex = LomutoPartition(input, left, right); 59 | 60 | if(k-1 == pivotIndex) 61 | return input[pivotIndex]; 62 | 63 | else if(pivotIndex > k-1){ 64 | right = pivotIndex-1; 65 | } 66 | 67 | else { 68 | left = pivotIndex+1; 69 | } 70 | 71 | return KthSmallestLomutoPartitioning(input, left, right, k); 72 | } 73 | 74 | int KthSmallestHoaresPartitioning(vector input, int left, int right, int k) { 75 | if(left == right) 76 | return input[left]; 77 | 78 | int pivotIndex = HoaresPartition(input, left, right); 79 | 80 | if(k == pivotIndex) 81 | return input[pivotIndex]; 82 | 83 | else if(pivotIndex > k){ 84 | right = pivotIndex-1; 85 | } 86 | 87 | else { 88 | left = pivotIndex+1; 89 | } 90 | 91 | return KthSmallestHoaresPartitioning(input, left, right, k); 92 | } 93 | 94 | 95 | int main() { 96 | vector ip = {7,-2,5,8,1,6}; 97 | 98 | cout << KthSmallestLomutoPartitioning(ip, 0,5,2) << endl; 99 | cout << KthSmallestHoaresPartitioning(ip,0,5,2) << endl; 100 | return 0; 101 | } -------------------------------------------------------------------------------- /String/shortest_way_to_form_string.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file shortest_way_to_form_string.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-08 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * 17 | * @link https://leetcode.com/problems/shortest-way-to-form-string/ 18 | * 19 | * 20 | * Problem: 21 | * 22 | * A subsequence of a string is a new string that is formed from the original string by deleting some 23 | * (can be none) of the characters without disturbing the relative positions of the remaining 24 | * characters. (i.e., "ace" is a subsequence of "abcde" while "aec" is not). 25 | * 26 | * Given two strings source and target, return the minimum number of subsequences of source such that 27 | * their concatenation equals target. If the task is impossible, return -1. 28 | * 29 | * Example 1: 30 | * 31 | * Input: source = "abc", target = "abcbc" 32 | * 33 | * Output: 2 34 | * 35 | * Explanation: The target "abcbc" can be formed by "abc" and "bc", which are subsequences of source "abc". 36 | * 37 | * 38 | * Example 2: 39 | * 40 | * Input: source = "abc", target = "acdbc" 41 | * 42 | * Output: -1 43 | * 44 | * Explanation: The target string cannot be constructed from the subsequences of source string due to the character "d" in target string. 45 | * 46 | * 47 | * Example 3: 48 | * 49 | * Input: source = "xyz", target = "xzyxz" 50 | * 51 | * Output: 3 52 | * 53 | * Explanation: The target string can be constructed as follows "xz" + "y" + "xz". 54 | * 55 | * Constraints: 56 | * 57 | * 1 <= source.length, target.length <= 1000 58 | * 59 | * source and target consist of lowercase English letters. 60 | * 61 | */ 62 | 63 | int shortestForm(string source, string target) { 64 | int num = 0; 65 | 66 | int s = 0; 67 | int t = 0; 68 | 69 | int lenT = target.length(); 70 | int lenS = target.length(); 71 | 72 | while(t < lenT) { 73 | bool flag = false; 74 | s = 0; 75 | while(s < lenS && t < lenT) { 76 | if(source[s] == target[t]){ 77 | t++; 78 | flag = true; 79 | } 80 | s++; 81 | } 82 | if(!flag) return -1; 83 | num++; 84 | } 85 | return t == lenT ? num : -1; 86 | } 87 | int main() { 88 | string source = "abc"; 89 | string target = "abcbc"; 90 | cout << shortestForm(source, target) << endl; 91 | return 0; 92 | } -------------------------------------------------------------------------------- /Math/multiple_with_0_and_1.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file multiple_with_0_and_1.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-09 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * @brief You are given an integer N. You have to find smallest multiple of N which consists of digits 0 and 1 only. 17 | * Since this multiple could be large, return it in form of a string. 18 | * 19 | * TestCase: 20 | * 21 | * #1: 22 | * Input: n = 3 23 | * 24 | * Output: 111 25 | * 26 | * #2: 27 | * 28 | * Input: n = 18 29 | * 30 | * @param n 31 | * @return string 32 | */ 33 | // string smallestMultipleWithZeroAndOne(int n) { 34 | // string output = "1"; 35 | // string outputL = "1", outputR = "1"; 36 | // string left, right; 37 | // long long unsigned int leftLL, rightLL; 38 | // while(true) { 39 | // left.clear(); right.clear(); 40 | // left = outputL + "0"; 41 | // right = outputR + "1"; 42 | // leftLL = atoi(left.c_str()); 43 | // rightLL = atoi(right.c_str()); 44 | 45 | // cout << "DEBUG: \t" << "LEFT: " << leftLL << endl; 46 | // cout << "DEBUG: \t" << "RIGHT: " << rightLL << endl; 47 | 48 | // if(rightLL % n == 0) { 49 | // output = right; 50 | // break; 51 | // } 52 | // else if(leftLL % n == 0) { 53 | // output = left; 54 | // break; 55 | // } 56 | // outputL = left; 57 | // outputR = right; 58 | // } 59 | // return output; 60 | // } 61 | 62 | string multiple(int A) { 63 | queue> q; // {string, mod A} 64 | q.push({"1",1%A}); 65 | vector ss(A+1, 0); 66 | ss[1] = 1; 67 | while(!q.empty()){ 68 | if(q.front().second == 0) 69 | return q.front().first; 70 | int nextmod1 = (10*(q.front().second))%A; 71 | int nextmod2 = (nextmod1 + 1)%A; 72 | if(ss[nextmod1] == 0){ 73 | q.front().first.push_back('0'); 74 | q.push({q.front().first, nextmod1}); 75 | ss[nextmod1] = 1; 76 | q.front().first.pop_back(); 77 | } 78 | if(ss[nextmod2] == 0){ 79 | q.front().first.push_back('1'); 80 | q.push({q.front().first, nextmod2}); 81 | ss[nextmod2] = 1; 82 | } 83 | q.pop(); 84 | } 85 | return "-1"; 86 | } 87 | 88 | int main() { 89 | int n = 12; 90 | cout << multiple(n) << endl; 91 | return 0; 92 | } -------------------------------------------------------------------------------- /BinarySearch/random_pick_with_weights.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file random_pick_with_weights.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-11 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * You are given a 0-indexed array of positive integers w where w[i] describes the weight of the ith index. 16 | * 17 | * You need to implement the function pickIndex(), which randomly picks an index in the range [0, w.length - 1] (inclusive) and returns it. The probability of picking an index i is w[i] / sum(w). 18 | * 19 | * For example, if w = [1, 3], the probability of picking index 0 is 1 / (1 + 3) = 0.25 (i.e., 25%), and the probability of picking index 1 is 3 / (1 + 3) = 0.75 (i.e., 75%). 20 | * 21 | * TestCases: 22 | * 23 | * #1: 24 | * 25 | * Input: ["Solution","pickIndex"] 26 | * 27 | * [[[1]],[]] 28 | * 29 | * Output: [null,0] 30 | * 31 | * Explanation: 32 | * 33 | * Solution solution = new Solution([1]); 34 | * 35 | * solution.pickIndex(); // return 0. The only option is to return 0 since there is only one element in w. 36 | * 37 | * #2: 38 | * 39 | * Input: ["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"] 40 | * 41 | * [[[1,3]],[],[],[],[],[]] 42 | * 43 | * Output: [null,1,1,1,1,0] 44 | * 45 | */ 46 | #include 47 | using namespace std; 48 | 49 | float gerenrateRandom() { 50 | random_device rd; 51 | default_random_engine generator(rd()); 52 | uniform_real_distribution<> range(0,1); 53 | return (float)range(generator); 54 | } 55 | 56 | int pickRandom(vector nums) { 57 | int sum = 0; 58 | vector prefixSum; 59 | for(auto x : nums) { 60 | prefixSum.push_back(x + (prefixSum.empty() ? 0 : prefixSum.back())); 61 | } 62 | 63 | for(auto x : prefixSum) cout << x << "\t"; 64 | float randNum = (float) rand() / RAND_MAX; 65 | //cout << rand << endl; 66 | float target = gerenrateRandom() * prefixSum.back(); 67 | //cout << target << endl; 68 | 69 | //Need to find upper bound of target in prefixSum array 70 | // for(int i = 0 ; i < prefixSum.size(); i++){ 71 | // if(target < prefixSum[i]) 72 | // return i; 73 | // } 74 | 75 | //one liner using STL 76 | // return upper_bound(prefixSum.begin(), prefixSum.end(), target) - prefixSum.begin(); 77 | 78 | return prefixSum.size()-1; 79 | } 80 | 81 | int main() { 82 | vector nums = {1,2,3,4,3}; 83 | for(int i = 0 ; i < 5; i++) 84 | cout << pickRandom(nums) << endl; 85 | return 0; 86 | } -------------------------------------------------------------------------------- /Arrays/product_of_array-except_self.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file product_of_array-except_self.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-28 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i]. 15 | * The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer. 16 | * 17 | * You must write an algorithm that runs in O(n) time and without using the division operation. 18 | * 19 | * Test Cases: 20 | * 21 | * #1: 22 | * 23 | * Input: nums = [1,2,3,4] 24 | * Output: [24,12,8,6] 25 | * 26 | * #2: 27 | * 28 | * Input: nums = [-1,1,0,-3,3] 29 | * Output: [0,0,9,0,0] 30 | * 31 | */ 32 | 33 | #include 34 | using namespace std; 35 | 36 | /** 37 | * @brief 38 | * One pass solution. 39 | * 40 | * Simply find how many zeroes are there in the input array. 41 | * 42 | * If only one zero is there then all outputs will be zero except the zeroth index itself, it would be the product of all elements of input except the zero itself. 43 | * 44 | * If more than one zero is there then all elements of the output will be zero 45 | * 46 | * 47 | * Complexity Analysis: 48 | * 49 | * Time Complexity : O(N); N = length of input 50 | * 51 | * Space Complexity : O(N); output is fresh new array; we can also make this to O(1) by modifying the input array itself 52 | * 53 | * @param input 54 | * @return vector 55 | */ 56 | vector productOfArrayExceptSelf(vector& input) { 57 | int inputLength = input.size(); 58 | vector output(inputLength, 0), zeroIndex; 59 | int numOfZeroes = 0; 60 | long long int cummulativeProduct = 1; 61 | int index = 0; 62 | 63 | for(index = 0; index < inputLength; index++) { 64 | int x = input[index]; 65 | if(x != 0) { 66 | cummulativeProduct *= x; 67 | } else { 68 | numOfZeroes++; 69 | zeroIndex.push_back(index); 70 | } 71 | } 72 | 73 | if(numOfZeroes == 0 || numOfZeroes > 1) { 74 | for(auto y : input) { 75 | y = cummulativeProduct/y; 76 | } 77 | } else if(numOfZeroes == 1) { 78 | output[zeroIndex[0]] = cummulativeProduct; 79 | } 80 | 81 | return output; 82 | } 83 | int main() { 84 | vector input = {-1,1,0,-3,3}; 85 | auto output = productOfArrayExceptSelf(input); 86 | for(auto x : output) cout << x << " "; 87 | return 0; 88 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # facebook-london-interview 2 | 3 | [![forthebadge](https://forthebadge.com/images/badges/made-with-c-plus-plus.svg)](https://forthebadge.com) 4 | [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com) 5 | 6 | Preparation for Facebook (now Meta) London undergrad Full-Time job Interview. 7 | 8 | #### [Technical Screening round experience](https://github.com/ranaaditya/facebook-london-interview/tree/main/technical-screening-round) 9 | #### [Onsite interview experience](https://github.com/ranaaditya/facebook-london-interview/tree/main/onsites-london) 10 | 11 | 12 | Good problems to start: 13 | 14 | 1. [Next Permutation](https://leetcode.com/explore/interview/card/facebook/5/array-and-strings/3012/) 15 | 2. [Removing duplicates from a sorted array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) 16 | 3. [Kth largest / smallest element in unsorted array](https://leetcode.com/problems/kth-largest-element-in-an-array/) 17 | 4. [**Copy LinkedList with random pointer**](https://leetcode.com/problems/copy-list-with-random-pointer/) 18 | 5. [3 Sum closest sum](https://leetcode.com/problems/3sum-closest/) 19 | 6. [Trapping Rain Water - Medium](https://leetcode.com/problems/container-with-most-water/) 20 | 7. [Trapping Rain Water - **Hard**](https://leetcode.com/problems/trapping-rain-water/) 21 | 8. [Shortest way to form string](https://leetcode.com/problems/shortest-way-to-form-string/) 22 | 9. [Distinct Sunsequences - **Hard**](https://leetcode.com/problems/distinct-subsequences/) 23 | 10. [Group Shifted strings](https://leetcode.com/problems/group-shifted-strings/) 24 | 11. [Number of Unique Good Subsequences - **Hard**](https://leetcode.com/problems/number-of-unique-good-subsequences/) 25 | 12. [Number of Matching Subsequences - **Good**](https://leetcode.com/problems/number-of-matching-subsequences/) 26 | 13. [Merge Intervals - **short implemetation with STL**](https://leetcode.com/problems/merge-intervals) 27 | 14. [Random pick with weight - **Nice explanation of probability with prefix sum**](https://leetcode.com/problems/random-pick-with-weight/) 28 | 15. [Palindrome pairs - **hard**, **too long for interview but has good concept**](https://leetcode.com/problems/palindrome-pairs/) 29 | 30 | 31 | ### Behavioural Interview ( Jedi round) resources: 32 | - [Interview Sage's blog - good to start to know what exactly happens in JEDI / Behavioural Interviews](https://dev.to/theinterviewsage/top-facebook-behavioral-interview-questions-part-1-2a0o?signin=true) 33 | - [Concide Guide about the interviews at Meta](https://igotanoffer.com/blogs/tech/facebook-software-engineer-interview) 34 | 35 | -------------------------------------------------------------------------------- /StandardQuestions/DP/knapsack.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file knapsack.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-18 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | int knapsk[1024][1024]; 16 | 17 | int knapsack(vector weight, vector value, int capacity, int size) { 18 | if(size == 0 || capacity == 0) 19 | return 0; 20 | 21 | if(weight[size-1] <= capacity) { 22 | return max((value[size-1] + knapsack(weight, value, capacity - weight[size-1], size-1)), knapsack(weight, value, capacity, size-1)); 23 | } 24 | 25 | //else if(weight[size] > capacity) 26 | return knapsack(weight, value, capacity, size-1); 27 | } 28 | 29 | int knapsackMemoization(vector weight, vector value, int capacity, int size) { 30 | if(size == 0 || capacity == 0) 31 | return 0; 32 | 33 | if(knapsk[size][capacity] != -1) 34 | return knapsk[size][capacity]; 35 | 36 | if(weight[size-1] <= capacity) { 37 | return knapsk[size][capacity] = max((value[size-1] + knapsackMemoization(weight, value, capacity - weight[size-1], size-1)), knapsackMemoization(weight, value, capacity, size-1)); 38 | } 39 | 40 | //else if(weight[size] > capacity) 41 | return knapsk[size][capacity] = knapsackMemoization(weight, value, capacity, size-1); 42 | } 43 | 44 | int dp[1024][1024]; 45 | 46 | int knapsackDP(vector weight, vector value, int capacity, int size) { 47 | memset(dp, -1, sizeof(dp)); 48 | for(int i = 0; i <= size; i++) { 49 | dp[0][i] = 0; 50 | dp[i][0] = 0; 51 | } 52 | 53 | for(int i = 1; i <= size; i++) { 54 | for(int j = 1; j <= capacity; j++) { 55 | if(weight[i] <= capacity) 56 | dp[i][j] = max((value[i-1] + dp[i-1][j-weight[i-1]]), dp[i-1][j]); 57 | else dp[i][j] = dp[i-1][j]; 58 | } 59 | } 60 | 61 | // for(int i = 0; i <= size; i++){ 62 | // for(int j = 0; j <= capacity; j++) 63 | // cout << dp[i][j] << "\t"; 64 | 65 | // cout << endl; 66 | // } 67 | 68 | 69 | return dp[size][capacity]; 70 | } 71 | 72 | int main() { 73 | vector weight = {1,2,3,4,5}; 74 | vector value = {5,2,3,4,5}; 75 | int capacity = 8; 76 | int size = 5; 77 | 78 | cout << knapsack(weight, value, capacity, size) << endl; 79 | 80 | memset(knapsk, -1, sizeof(knapsk)); 81 | 82 | cout << knapsackMemoization(weight, value, capacity, size) << endl; 83 | 84 | cout << knapsackDP(weight, value, capacity, size); 85 | 86 | return 0; 87 | } -------------------------------------------------------------------------------- /Arrays/next_permutation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file next_permutation.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-25 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | /** 13 | * @link: https://leetcode.com/explore/interview/card/facebook/5/array-and-strings/3012/ 14 | * 15 | * Problem: 16 | * 17 | * Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. 18 | * If such an arrangement is impossible, it must rearrange it to the lowest possible order (i.e., sorted in ascending order). 19 | * The replacement must be in place and use only constant extra memory. 20 | * 21 | * Test Cases: 22 | * 23 | * #1: 24 | * Input: nums = [1,2,3] 25 | * Output: [1,3,2] 26 | * 27 | * #2: 28 | * Input: nums = [3,2,1] 29 | * Output: [1,2,3] 30 | * 31 | * #3: 32 | * Input: nums = [1,1,5] 33 | * Output: [1,5,1] 34 | * 35 | */ 36 | #include 37 | using namespace std; 38 | 39 | /** 40 | * @brief 41 | * 42 | * Solution: 43 | * 44 | * Relevant Image: https://leetcode.com/media/original_images/31_nums_graph.png 45 | * 46 | * 1. start iterating from last of the array 47 | * 2. Find an index such that: 48 | * 49 | * a. input[index1] < index[index+1] 50 | * b. input[index2] > input[index1] 51 | * 52 | * 3. swap(index1, index2) 53 | * 4. reverse all elements from index+1 to the end of the array 54 | * 55 | * @param input 56 | * @return vector 57 | */ 58 | vector nextPermutation(vector& input) { 59 | int length = input.size(); 60 | int index = length-2, index_reverse = length-2; 61 | 62 | for(index = length-2; index >=0; index--) 63 | if(input[index] < input[index+1]) break; 64 | 65 | if(index < 0) { sort(input.begin(), input.end()); return input; } // this is the case when array is sorted in descending order and no next permutation is there ! 66 | 67 | for( index_reverse = length-2; index_reverse >= 0; index_reverse--) 68 | if(input[index_reverse] > input[index]) break; 69 | 70 | swap(input[index], input[index_reverse]); 71 | reverse(input.begin() + index+1, input.end()); 72 | return input; 73 | } 74 | 75 | 76 | //hack using STL inbuilt functions 77 | vector nextPermutationHack(vector& input) { 78 | std::next_permutation(input.begin(), input.end()); 79 | return input; 80 | } 81 | 82 | int main() { 83 | vector input = {1,3,5,4,2}; 84 | //vector input = {3,2,1}; 85 | //auto output = nextPermutation(input); 86 | auto hackOutput = nextPermutationHack(input); 87 | for(auto x : hackOutput) cout << x; 88 | return 0; 89 | } -------------------------------------------------------------------------------- /MonotonicQueue/MonotonicQueue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MonotonicQueue.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-15 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | class MonotonicQueue { 16 | private: 17 | /** 18 | * @brief Deque has been used here just to have flexibility to add elements both from rear and front 19 | * 20 | * Deque is more flexible than Queue 21 | * 22 | */ 23 | deque dq; 24 | /** 25 | * @brief this flag is use to differentiate between the increasing or decreasing nature of the monotonic queue 26 | * 27 | */ 28 | bool isIncreasingSequence; 29 | 30 | public: 31 | MonotonicQueue(bool isIncreasing) { 32 | this->isIncreasingSequence = isIncreasing; 33 | } 34 | 35 | /** 36 | * @brief for inserting an element from the last of the queue 37 | * 38 | * @param value 39 | */ 40 | void push_back(int value) { 41 | if(isIncreasingSequence) { 42 | while(!dq.empty() && dq.back() >= value) 43 | dq.pop_back(); 44 | 45 | dq.push_back(value); 46 | } else { 47 | while(!dq.empty() && dq.back() <= value) 48 | dq.pop_back(); 49 | 50 | dq.push_back(value); 51 | } 52 | } 53 | 54 | /** 55 | * @brief for adding element from the starting of the queue 56 | * 57 | * @param value 58 | */ 59 | void push_front(int value) { 60 | if(isIncreasingSequence) { 61 | while(!dq.empty() && dq.front() <= value) 62 | dq.pop_front(); 63 | 64 | dq.push_front(value); 65 | } else { 66 | while(!dq.empty() && dq.front() >= value) 67 | dq.pop_front(); 68 | 69 | dq.push_front(value); 70 | } 71 | } 72 | 73 | /** 74 | * @brief for getting l-value of the last element in the queue 75 | * 76 | * @return int 77 | */ 78 | int back() { 79 | return dq.back(); 80 | } 81 | 82 | /** 83 | * @brief for getting the first element in the queue 84 | * 85 | * @return int 86 | */ 87 | int front() { 88 | return dq.front(); 89 | } 90 | 91 | /** 92 | * @brief prints the entire queue 93 | * 94 | */ 95 | void print() { 96 | for(auto x : dq) 97 | cout << x << "\t"; 98 | } 99 | }; 100 | 101 | int main() { 102 | MonotonicQueue mq(true); 103 | 104 | for(int i = 0; i < 6; i++) { 105 | mq.push_back(i); 106 | } 107 | 108 | mq.print(); // 0 1 2 3 4 5 109 | return 0; 110 | } -------------------------------------------------------------------------------- /LinkedList/reorder_list.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file reorder_list.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-05 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | 16 | struct LinkedListNode { 17 | int value; 18 | LinkedListNode* next; 19 | 20 | LinkedListNode(int val) { 21 | this->value = val; 22 | this->next = nullptr; 23 | } 24 | 25 | LinkedListNode(int val, LinkedListNode* nxt) { 26 | this->value = val; 27 | this->next = nxt; 28 | } 29 | }; 30 | 31 | void insert(LinkedListNode* head, int val) { 32 | if(head == nullptr) 33 | return; 34 | 35 | LinkedListNode* ptr = head; 36 | while(ptr->next != nullptr){ 37 | ptr = ptr->next; 38 | } 39 | 40 | LinkedListNode* tmp = new LinkedListNode(val); 41 | ptr->next = tmp; 42 | ptr = ptr->next; 43 | } 44 | 45 | void printLinkedList(LinkedListNode* head) { 46 | LinkedListNode* ptr = head; 47 | 48 | while(ptr != nullptr) { 49 | cout << ptr->value << "\n"; 50 | ptr = ptr->next; 51 | } 52 | } 53 | 54 | LinkedListNode* reverseList(LinkedListNode* head) { 55 | LinkedListNode *prev = nullptr, *current = head,* next = nullptr; 56 | 57 | while(current != nullptr) { 58 | next = current->next; 59 | current->next = prev; 60 | prev = current; 61 | current = next; 62 | } 63 | 64 | return prev; 65 | } 66 | 67 | 68 | LinkedListNode* reorderLinkedList(LinkedListNode* head) { 69 | LinkedListNode *current = head; 70 | 71 | LinkedListNode* ptr = head; 72 | int length = 0; 73 | 74 | while(ptr != nullptr) { 75 | length++; 76 | ptr = ptr->next; 77 | } 78 | 79 | int ltraverse = (length%2 == 0) ? length/2 : (length/2)+1 ; 80 | 81 | while( ltraverse > 0) { 82 | current = current->next; 83 | } 84 | 85 | 86 | LinkedListNode* lHead = reverseList(current); 87 | current = head; 88 | 89 | LinkedListNode *oldPtr = head, *newPtr = lHead; 90 | LinkedListNode *nextOld = head, *nextNew = lHead; 91 | 92 | while(oldPtr != nullptr && newPtr != nullptr) { 93 | nextOld = current->next; 94 | nextNew = newPtr->next; 95 | oldPtr->next = newPtr; 96 | oldPtr = nextOld; 97 | newPtr = nextNew; 98 | } 99 | 100 | return head; 101 | } 102 | int main() { 103 | LinkedListNode *ll = new LinkedListNode(0); 104 | for(int i = 1; i < 6; i++) 105 | insert(ll, i); 106 | 107 | // LinkedListNode *rl = reverseList(ll); 108 | // printLinkedList(rl); 109 | 110 | reorderLinkedList(ll); 111 | printLinkedList(ll); 112 | return 0; 113 | } -------------------------------------------------------------------------------- /Arrays/remove_duplicates_from_sorted_array.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file remove_duplicates_from_sorted_array.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-12-25 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | 13 | /** 14 | 15 | * Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that 16 | * each unique element appears only once. The relative order of the elements should be kept the same. 17 | 18 | * Since it is impossible to change the length of the array in some languages, you must instead have the 19 | * result be placed in the first part of the array nums. More formally, if there are k elements after removing 20 | * the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements. 21 | 22 | * Return "k" after placing the final result in the first k slots of nums. 23 | 24 | * Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory. 25 | 26 | * Test Cases: 27 | 28 | * #1 29 | Input: nums = [1,1,2] 30 | Output: 2, nums = [1,2,_] 31 | 32 | * #2 33 | Input: nums = [0,0,1,1,1,2,2,3,3,4] 34 | Output: 5, nums = [0,1,2,3,4,_,_,_,_,_] 35 | 36 | */ 37 | 38 | /** 39 | * Edge cases: 40 | * #1: 41 | * when array is empty 42 | * 43 | * #2: 44 | * when array has just one element 45 | * 46 | * #3: 47 | * when all elements of array are distinct -> this will become the WORST CASE SCENARIO with Time Complexity TC = O(n) 48 | * 49 | * #4: 50 | * when all elements of the array are same -> TC = O(n) 51 | * 52 | */ 53 | 54 | #include 55 | using namespace std; 56 | 57 | // input array is already sorted in non-descending(ascending) order. 58 | int removeDuplicates(vector& input) { 59 | 60 | if(input.size() == 0) return 0; 61 | if(input.size() == 1) return 1; 62 | 63 | int i = 0, j = 0, k = 0; 64 | int length = input.size(); 65 | 66 | while(i < length) { 67 | j = i; 68 | for(j = i+1; j < length; j++) { 69 | if(input[j] == input[i]) { continue; } 70 | else break; 71 | } 72 | input[k] = input[i]; 73 | k++; 74 | i = j; 75 | } 76 | 77 | //debuging input 78 | // for(auto x : input) { 79 | // cout << x; 80 | // } 81 | 82 | return k; 83 | } 84 | 85 | // STL hack 86 | int removeDuplicatesHack(vector& nums) { 87 | nums.erase( unique( nums.begin(), nums.end() ), nums.end() ); 88 | nums.shrink_to_fit(); 89 | return nums.size(); 90 | 91 | //return std::distance(nums.begin(), std::unique(nums.begin(), nums.end())); 92 | } 93 | 94 | int main() { 95 | //vector input = {1,1,2}; 96 | vector input = {0,0,1,1,1,2,2,3,3,4}; 97 | cout << removeDuplicates(input) << endl; 98 | // cout << removeDuplicatesHack(input); 99 | return 0; 100 | } -------------------------------------------------------------------------------- /Arrays/median_two_sorted_arryas.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file median_two_sorted_arryas.cpp 3 | * @author https://github.com/ranaaditya 4 | * @brief 5 | * @version 0.1 6 | * @date 2021-11-15 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | /** 13 | * @brief Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays. 14 | * 15 | * Test case 1: 16 | * Input: nums1 = [1,3], nums2 = [2] 17 | * Output: 2.00000 18 | * Explanation: merged array = [1,2,3] and median is 2. 19 | * 20 | * Test Case 2: 21 | * Input: nums1 = [1,2], nums2 = [3,4] 22 | * Output: 2.50000 23 | * Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5. 24 | * 25 | */ 26 | 27 | #include 28 | using namespace std; 29 | 30 | // 2-pointer algo 31 | int medianTwoSorted_twopointer(vector first, vector second) { 32 | int n = first.size(); 33 | int m = second.size(); 34 | int half = (n + m)/2; 35 | bool isDoubletRequired = false; 36 | 37 | if(half%2 != 0) isDoubletRequired = true; 38 | 39 | int i = 0, j = 0; 40 | 41 | while((i+j) < half-1) { 42 | if(first[i] <= second[j]) { 43 | if(i < n) i++; else j++; 44 | } 45 | else { 46 | if(j < m) j++; else i++; 47 | } 48 | } 49 | 50 | if(!isDoubletRequired) { return first[i] < second[j] ? first[i]: second[j];} 51 | 52 | int l ,r; 53 | if(first[i] < second[j]) { l = first[i]; i++; } else { l = second[j]; j++; } 54 | if(first[i] < second[j]) { r = first[i]; i++; } else { r = second[j]; j++; } 55 | return (l+r)/2; 56 | } 57 | 58 | // optimal solution using binary-search 59 | double findMedianSortedArrays(vector& nums1, vector& nums2) { 60 | if(nums2.size() < nums1.size()) return findMedianSortedArrays(nums2, nums1); 61 | int n1 = nums1.size(); 62 | int n2 = nums2.size(); 63 | int low = 0, high = n1; 64 | 65 | while(low <= high) { 66 | int cut1 = (low+high) >> 1; 67 | int cut2 = (n1 + n2 + 1) / 2 - cut1; 68 | 69 | 70 | int left1 = cut1 == 0 ? INT_MIN : nums1[cut1-1]; 71 | int left2 = cut2 == 0 ? INT_MIN : nums2[cut2-1]; 72 | 73 | int right1 = cut1 == n1 ? INT_MAX : nums1[cut1]; 74 | int right2 = cut2 == n2 ? INT_MAX : nums2[cut2]; 75 | 76 | 77 | if(left1 <= right2 && left2 <= right1) { 78 | if( (n1 + n2) % 2 == 0 ) 79 | return (max(left1, left2) + min(right1, right2)) / 2.0; 80 | else 81 | return max(left1, left2); 82 | } 83 | else if(left1 > right2) { 84 | high = cut1 - 1; 85 | } 86 | else { 87 | low = cut1 + 1; 88 | } 89 | } 90 | return 0.0; 91 | } 92 | 93 | int main() { 94 | vector first = {1,3,4,7,10,12}; 95 | vector second = {2,3,6,15}; 96 | cout << findMedianSortedArrays(first, second); 97 | return 0; 98 | } -------------------------------------------------------------------------------- /MonotonicQueue/daily_temperature.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file daily_temperature.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-14 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * Given an array of integers temperatures represents the daily temperatures, return an array answer such that answer[i] 16 | * is the number of days you have to wait after the ith day to get a warmer temperature. If there is no future day for 17 | * which this is possible, keep answer[i] == 0 instead. 18 | * 19 | * TestCases: 20 | * 21 | * #1: 22 | * 23 | * Input: temperatures = [73,74,75,71,69,72,76,73] 24 | * 25 | * Output: [1,1,4,2,1,1,0,0] 26 | * 27 | * #2: 28 | * 29 | * Input: temperatures = [30,40,50,60] 30 | * 31 | * Output: [1,1,1,0] 32 | * 33 | * #3: 34 | * 35 | * Input: temperatures = [30,60,90] 36 | * 37 | * Output: [1,1,0] 38 | * 39 | * 40 | * Constraints: 41 | * 42 | * 1 <= temperatures.length <= 105 43 | * 44 | * 30 <= temperatures[i] <= 100 45 | * 46 | */ 47 | #include 48 | using namespace std; 49 | /** 50 | * @brief Decreasing Monotonous Queue will be used. 51 | * 52 | * Time Complexity: O(N) 53 | * 54 | * Space Complexity: O(N) (worst case) 55 | * 56 | * @param temperatures 57 | * @return vector 58 | */ 59 | vector dailyTemperature(vector temperatures) { 60 | int numberOfDays = temperatures.size(); 61 | vector nextHighTemperatures(numberOfDays, 0); 62 | deque indices; 63 | indices.push_back(numberOfDays-1); 64 | 65 | for(int i = numberOfDays-2; i >= 0; i--) { 66 | 67 | while( !indices.empty() && temperatures[indices.back()] <= temperatures[i]) { 68 | indices.pop_back(); 69 | } 70 | 71 | if(!indices.empty()) 72 | nextHighTemperatures[i] = indices.back() - i; 73 | 74 | indices.push_back(i); 75 | } 76 | 77 | return nextHighTemperatures; 78 | } 79 | 80 | // space optimized solution O(1) 81 | vector dailyHighTemperatureOptimized(vector temperatures) { 82 | int length = temperatures.size(); 83 | vector nextHighTemperature(length, 0); 84 | int maxTemperature = 0; 85 | 86 | for(int i = length-1; i >= 0; i--) { 87 | int currentTemperature = temperatures[i]; 88 | 89 | if(currentTemperature >= maxTemperature){ 90 | maxTemperature = currentTemperature; 91 | continue; 92 | } 93 | 94 | int days = 1; 95 | while(temperatures[i + days] <= currentTemperature) { 96 | days += nextHighTemperature[i + days]; 97 | } 98 | 99 | nextHighTemperature[i] = days; 100 | } 101 | 102 | return nextHighTemperature; 103 | } 104 | int main() { 105 | vector temperatures = {73,74,75,71,69,72,76,73}; 106 | auto output = dailyHighTemperatureOptimized(temperatures); 107 | 108 | for(auto x : output) 109 | cout << x << "\t"; 110 | 111 | cout << endl; 112 | return 0; 113 | } -------------------------------------------------------------------------------- /String/encode_and_decode.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file encode_and_decode.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-13 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings. 16 | * 17 | * Machine 1 (sender) has the function: 18 | * 19 | * string encode(vector strs) { 20 | * 21 | * // ... your code 22 | * 23 | * return encoded_string; 24 | * 25 | * } 26 | * 27 | * Machine 2 (receiver) has the function: 28 | * 29 | * vector decode(string s) { 30 | * 31 | * //... your code 32 | * 33 | * return strs; 34 | * 35 | * } 36 | * 37 | * So Machine 1 does: 38 | * 39 | * string encoded_string = encode(strs); 40 | * 41 | * and Machine 2 does: 42 | * 43 | * 44 | * vector strs2 = decode(encoded_string); 45 | * 46 | * strs2 in Machine 2 should be the same as strs in Machine 1. 47 | * 48 | * Implement the encode and decode methods. 49 | * 50 | * 51 | * You are not allowed to solve the problem using any serialize methods (such as eval). 52 | * 53 | * TestCases: 54 | * 55 | * #1: 56 | * 57 | * Input: dummy_input = ["Hello","World"] 58 | * 59 | * Output: ["Hello","World"] 60 | * 61 | * 62 | * Explanation: 63 | * 64 | * Machine 1: 65 | * 66 | * Codec encoder = new Codec(); 67 | * 68 | * String msg = encoder.encode(strs); 69 | * 70 | * Machine 1 ---msg---> Machine 2 71 | * 72 | * 73 | * Machine 2: 74 | * 75 | * Codec decoder = new Codec(); 76 | * 77 | * String[] strs = decoder.decode(msg); 78 | * 79 | * #2: 80 | * 81 | * Input: dummy_input = [""] 82 | * 83 | * Output: [""] 84 | * 85 | * 86 | * Constraints: 87 | * 88 | * 1 <= strs.length <= 200 89 | * 90 | * 0 <= strs[i].length <= 200 91 | * 92 | * strs[i] contains any possible characters out of 256 valid ASCII characters. 93 | * 94 | */ 95 | #include 96 | using namespace std; 97 | 98 | string encodeInput(vector input) { 99 | string encodedString; 100 | 101 | for(auto part : input) { 102 | int partLength = part.length(); 103 | encodedString += to_string(partLength) + '#' + part; 104 | } 105 | return encodedString; 106 | } 107 | 108 | vector decodeInput(string input) { 109 | vector decodedStrings; 110 | int length = input.length(); 111 | int index = 0; 112 | while(index < length) { 113 | int len = input[index] - '0'; 114 | decodedStrings.push_back(input.substr(index+2, len)); 115 | index += (len + 2); 116 | } 117 | return decodedStrings; 118 | } 119 | 120 | int main() { 121 | vector words = {"Hello","World"}; 122 | string encstr = encodeInput(words); 123 | cout << encstr << endl; 124 | 125 | vector dcdstr = decodeInput(encstr); 126 | 127 | for(auto x : dcdstr) 128 | cout << x << "\n"; 129 | 130 | cout << endl; 131 | return 0; 132 | } -------------------------------------------------------------------------------- /Arrays/continous_subarray_sum.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file continous_subarray_sum.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-10 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * Given an integer array nums and an integer k, return true if nums has a continuous subarray of size at least two whose elements sum up to a multiple of k, or false otherwise. 16 | * 17 | * An integer x is a multiple of k if there exists an integer n such that x = n * k. 0 is always a multiple of k. 18 | * 19 | * TestCases: 20 | * 21 | * #1: 22 | * 23 | * Input: nums = [23,2,4,6,7], k = 6 24 | * 25 | * Output: true 26 | * 27 | * Explanation: [2, 4] is a continuous subarray of size 2 whose elements sum up to 6. 28 | * 29 | * #2: 30 | * 31 | * Input: nums = [23,2,6,4,7], k = 6 32 | * 33 | * Output: true 34 | * 35 | * Explanation: [23, 2, 6, 4, 7] is an continuous subarray of size 5 whose elements sum up to 42. 36 | * 42 is a multiple of 6 because 42 = 7 * 6 and 7 is an integer. 37 | * 38 | * #3: 39 | * 40 | * Input: nums = [23,2,6,4,7], k = 13 41 | * 42 | * Output: false 43 | * 44 | */ 45 | #include 46 | using namespace std; 47 | 48 | bool isSubarrayExist(vector nums, int k) { 49 | bool hasSubArray = false; 50 | int i = 0, j = 0; 51 | int length = nums.size(); 52 | int currentSum = 0; 53 | 54 | while(i < length && j < length) { 55 | currentSum = nums[i]; 56 | j = i+1; 57 | while(j < length) { 58 | currentSum += nums[j]; 59 | if(currentSum % k == 0 && (j-i) > 0) { 60 | cout << "i = " << i << "\nj = " << j << endl; 61 | return true; 62 | } 63 | j++; 64 | } 65 | i++; 66 | } 67 | return hasSubArray; 68 | } 69 | 70 | // Trick - unordered map 71 | bool checkSubarraySum(vector& nums, int k) { 72 | if(nums.size() == 1) return false; 73 | unordered_map mp; 74 | int sum = 0; 75 | for(int i=0; i= 1) return true; 79 | if(mp.find(mod) == mp.end()) mp[mod] = i; 80 | else if(mp.find(mod) != mp.end() && i - mp[mod] >= 2) return true; 81 | } 82 | return false; 83 | } 84 | 85 | bool checkSubarraySumPrefixArray(vector& nums, int k) { 86 | int n = nums.size(); 87 | vector preSum(n); 88 | preSum[0] = nums[0]%k; 89 | for(int i = 1;i lastInd; 94 | lastInd[0] = -1; 95 | 96 | for(int i = 0;i 1)return true; 99 | } else { 100 | lastInd[preSum[i]] = i; 101 | } 102 | } 103 | return false; 104 | } 105 | 106 | int main() { 107 | vector nums = {23,2,6,4,7}; 108 | int k = 6; 109 | cout << isSubarrayExist(nums, k); 110 | return 0; 111 | } -------------------------------------------------------------------------------- /FenwickTree/BinaryIndexTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file BinaryIndexTree.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-10 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * @brief Fenwick Tree or Binary Index Tree 17 | * 18 | * Height: maximum of log(n) 19 | * 20 | * GetSum(0, n): log(n) 21 | * 22 | * Updatevalue(index, newvalue): log(n) 23 | * 24 | * Size of internal array used to create BIT: O(n+1) 25 | * 26 | * 27 | * BIT are used to get sum of first i elements in log(n) 28 | * 29 | * These are better than Segment trees as they take less space / same as that of the input array 30 | * 31 | * Both BIT and Segement Trees have same time complexity for updation and getting sum operations. 32 | * 33 | */ 34 | class BinaryIndexTree { 35 | private: 36 | int length; 37 | vector bit; 38 | 39 | public: 40 | BinaryIndexTree(int treeLength){ 41 | this->length = treeLength + 1; 42 | bit.assign(treeLength, 0); 43 | } 44 | 45 | BinaryIndexTree(vector bitArray){ 46 | this->length = bitArray.size() + 1; 47 | bit.assign(this->length, 0); 48 | createBinaryIndexTreeFromArray(bitArray, this->length); 49 | } 50 | 51 | void createBinaryIndexTreeFromArray(vector arr, int length) { 52 | for(int i = 1; i < length; i++) { 53 | updateBinaryIndexTree(i, arr[i-1]); 54 | } 55 | } 56 | 57 | /** 58 | * @brief Get the Next object 59 | * 60 | * Steps: 61 | * 62 | * 1. 2's complement to get the minus index 63 | * 2. AND with this index 64 | * 3. Subtract that from index 65 | * 66 | * @param index 67 | * @return int 68 | */ 69 | int getNext(int index) { 70 | return index + (index & -index); 71 | } 72 | 73 | /** 74 | * @brief Get the Parent object 75 | * 76 | * Steps: 77 | * 78 | * 1. 2's complement to get the minus index 79 | * 2. AND this with index 80 | * 3. Subtract that from index 81 | * 82 | * @param index 83 | * @return int 84 | */ 85 | int getParent(int index) { 86 | return index - (index & -index); 87 | } 88 | 89 | int getSum(int index) { 90 | index = index + 1; 91 | int sum = 0; 92 | while(index > 0) { 93 | sum += bit[index]; 94 | index = getParent(index); 95 | } 96 | return sum; 97 | } 98 | 99 | vector getBinaryIndexTree() { 100 | return this->bit; 101 | } 102 | 103 | void updateBinaryIndexTree(int index, int updatedvalue) { 104 | while(index < this->length) { 105 | bit[index] += updatedvalue; 106 | index = getNext(index); 107 | } 108 | } 109 | 110 | }; 111 | 112 | int main() { 113 | //vector arr = {3,2,-1,6,5,4,-3,3,7,2,3}; 114 | vector arr = {0,1,2,3,4,5,6,7,8,9}; 115 | BinaryIndexTree bit = BinaryIndexTree(arr); 116 | auto x = bit.getBinaryIndexTree(); 117 | 118 | for(auto y : x) 119 | cout << y << "\t"; 120 | cout << endl; 121 | 122 | cout << "sum of first 5 elements: " << bit.getSum(5) << endl; 123 | return 0; 124 | } -------------------------------------------------------------------------------- /MonotonicQueue/shortest_unsorted_continouos_subarray.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file shortest_unsorted_continouos_subarray.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-14 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | // brute force solution 16 | // Time Complexity: O(N^2) 17 | // Space Complexity: O(1) 18 | int shortestUnsortedSubarrayBruteForce(vector input) { 19 | int inputLength = input.size(); 20 | int shortestLength = 0; 21 | int l = inputLength, r = 0; 22 | 23 | for(int i = 0; i < inputLength-1; i++) 24 | for(int j = i+1; j < inputLength; j++) { 25 | if(input[i] > input[j]) { 26 | l = min(l,i); 27 | r = max(r,j); 28 | } 29 | } 30 | return (r-l) < 0 ? 0 : (r-l+1); 31 | } 32 | 33 | // O(Nlog(N)) solution 34 | // if input is non negative then sort can be done using radix sort then TC = O(N) 35 | int solutionUsingSorting(vector input) { 36 | int length = input.size(); 37 | auto copyInput = input; 38 | sort(copyInput.begin(), copyInput.end()); 39 | int l = length, r = 0; 40 | for(int i = 0; i < length; i++) { 41 | if(input[i] != copyInput[i]) { 42 | l = min(i,l); 43 | } 44 | 45 | if(input[length-1-i] != copyInput[length-1-i]) { 46 | r = max(r,length-1-i); 47 | } 48 | } 49 | cout << l << "\t" << r << endl; 50 | return (r-l) > 0 ? (r-l+1) : 0; 51 | } 52 | 53 | 54 | // optimal solution 55 | // TimeComplexity: O(N) 56 | // Space Somplexity: O(1) 57 | // This solution is based on observation and visual representation of the problem 58 | // We need to find : 59 | // - from left: first element which breaking increasing slope sequence(ascending order) and minimum element from this element till last 60 | // - from right: first element breaking increasing slope sequence and maximu element from this element till first element of the input array 61 | // Then find the indices of - first element just greater than the minimum element and first element from last just lesser than the max element so far calculated. 62 | // answer is right - left + 1 if right >= left 63 | int shortestUnsortedSubarray(vector input) { 64 | int length = input.size(); 65 | int minE = INT_MAX, maxE = INT_MIN; 66 | int flag = false; 67 | int left = -1,right = -1; 68 | 69 | for(int i = 1; i < length; i++) { 70 | if(input[i] < input[i-1]) 71 | flag = true; 72 | 73 | if(flag) 74 | minE = min(minE, input[i]); 75 | } 76 | 77 | flag = false; 78 | 79 | for(int i = length-1; i > 0; i--) { 80 | if(input[i-1] > input[i]) 81 | flag = true; 82 | 83 | if(flag) 84 | maxE = max(maxE, input[i-1]); 85 | } 86 | 87 | for(left = 0; left < length; left++) { 88 | if(input[left] > minE) break; 89 | } 90 | 91 | for(right = length-1; right > 0; right--) { 92 | if(input[right] < maxE) break; 93 | } 94 | 95 | return (right - left) < 0 ? 0 : (right - left +1); 96 | } 97 | 98 | int main() { 99 | vector arr = {2,6,4,8,10,9,15}; 100 | int ans = shortestUnsortedSubarray(arr); 101 | cout << ans << endl; 102 | return 0; 103 | } -------------------------------------------------------------------------------- /Miscellneous/randomizer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file randomizer.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-11 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * std::random_device device 14 | * 15 | * This is a special class which produces uniformly-distributed unsigned integers with 32 bits of length. 16 | * It can produce random numbers either by accessing the operational system's entropy pool via system calls 17 | * or by using hardware random number generators such as Intel's RdRand when available 18 | * (but not all implementations of std::random_device allow this). Developers must be warned, however, that even 19 | * though 32-bit unsigned integers are generated, the entropy of this random number generator may be lower than 32 bits. 20 | * 21 | * Unfortunately, it is not advisable to use std::random_device repeatedly as this may quickly deplete the entropy 22 | * pool and therefore reduce the level of randomness available to the other processes running in the system. Additionally, 23 | * its reliance on system calls makes it a very slow random number generator. 24 | * 25 | * use std::random_device to generate a single random number which is then used as a seed for a pseudorandom number 26 | * generator (PRNG) and then use the PRNG itself to generate as many pseudorandom numbers as we wish. 27 | * 28 | * 29 | * std::uniform_int_distribution 30 | * 31 | * Produces random integer values i, uniformly distributed on the closed interval [a,b], 32 | * that is, distributed according to the discrete probability function. 33 | * 34 | * Using its overloaded operator(), an object of type std::uniform_int_distribution can take a random number generator and use 35 | * it to generate a number within its defined target interval. Indeed, the following expression in our code returns a number in [a,b] 36 | * 37 | */ 38 | #include 39 | using namespace std; 40 | 41 | int randomizer(int low, int high) { 42 | random_device rd; 43 | mt19937 generator(rd()); 44 | uniform_int_distribution distribution(low, high); 45 | 46 | return distribution(generator); 47 | } 48 | 49 | float randomizer (float low, float high) { 50 | random_device rd; 51 | default_random_engine dre(rd()); 52 | uniform_real_distribution uid(low, high); 53 | 54 | return (float) uid(dre); 55 | } 56 | 57 | double randomizer(double low, double high){ 58 | random_device rd; 59 | default_random_engine dre(rd()); 60 | uniform_real_distribution uid(low, high); 61 | 62 | return (float) uid(dre); 63 | } 64 | 65 | char randomizer(char low, char high) { 66 | int shiftLow = low - 'a'; 67 | int shiftHigh = high - 'a'; 68 | 69 | random_device rd; 70 | mt19937 generator(rd()); 71 | uniform_int_distribution distribution(shiftLow, shiftHigh); 72 | 73 | return distribution(generator) + 'a'; 74 | 75 | } 76 | 77 | int reproducibleRandomizer(int low, int high) { 78 | /* seed the PRNG (MT19937) using a fixed value (in our case, 0) */ 79 | mt19937 generator(0); 80 | uniform_int_distribution distribution(low, high); 81 | 82 | return distribution(generator); 83 | } 84 | 85 | int main() { 86 | double start = 0.00; 87 | double end = 10.00; 88 | 89 | char low = 'a'; 90 | char high = 'z'; 91 | 92 | for(int i = 0; i < 5; i++){ 93 | cout << randomizer(low, high) << endl; 94 | } 95 | 96 | return 0; 97 | } -------------------------------------------------------------------------------- /String/valid_number_hard.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file valid_number_hard.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-11 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * A valid number can be split up into these components (in order): 16 | * 17 | * - A decimal number or an integer. 18 | * 19 | * - (Optional) An 'e' or 'E', followed by an integer. 20 | * 21 | * - A decimal number can be split up into these components (in order): 22 | * 23 | * (Optional) A sign character (either '+' or '-'). 24 | * 25 | * One of the following formats: 26 | * 27 | * One or more digits, followed by a dot '.'. 28 | * 29 | * One or more digits, followed by a dot '.', followed by one or more digits. 30 | * 31 | * A dot '.', followed by one or more digits. 32 | * 33 | * 34 | * An integer can be split up into these components (in order): 35 | * 36 | * (Optional) A sign character (either '+' or '-'). 37 | * 38 | * One or more digits. 39 | * 40 | * 41 | * 42 | * For example, all the following are valid numbers: ["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"], while the following are not valid numbers: ["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]. 43 | * 44 | * Given a string s, return true if s is a valid number. 45 | * 46 | * TestCases: 47 | * 48 | * #1: 49 | * 50 | * Input: s = "0" 51 | * 52 | * Output: true 53 | * 54 | * #2: 55 | * 56 | * Input: s = "e" 57 | * 58 | * Output: false 59 | * #3: 60 | * 61 | * Input: s = "." 62 | * 63 | * Output: false 64 | * 65 | * 66 | * Constraints: 67 | * 68 | * 1 <= s.length <= 20 69 | * 70 | * s consists of only English letters (both uppercase and lowercase), digits (0-9), plus '+', minus '-', or dot 71 | * 72 | */ 73 | #include 74 | using namespace std; 75 | 76 | bool isValidNum(char ch) { 77 | return ((ch - '0') >= 0 && (ch - '0') <= 9); 78 | } 79 | 80 | bool isValidSign(char sign) { 81 | return (sign == '+' || sign == '-'); 82 | } 83 | 84 | bool isExponenetial(char exp) { 85 | return ((exp == 'e') || (exp == 'E')); 86 | } 87 | 88 | bool validNumberImproved(string num) { 89 | int index = 0; 90 | bool isSign = false; 91 | bool isE = false; 92 | bool isDecimal = false; 93 | int length = num.length(); 94 | 95 | if(length < 2) { 96 | return isValidNum(num[0]); 97 | } 98 | 99 | for(int i = 0; i < length ; i++) { 100 | if(isValidSign(num[i])){ 101 | if(i == 0) continue; 102 | else if((i > 0 && i <= length-2) && isExponenetial(num[i-1]))continue; 103 | else return false; 104 | } else if(isValidNum(num[i])) { 105 | continue; 106 | } else if(num[i] == '.') { 107 | if((i > 0 && i <= length-2) && (isValidNum(num[i-1]) && isValidNum(num[i+1]))) { 108 | continue; 109 | } else return false; 110 | } else if(isExponenetial(num[i])) { 111 | if((i > 0 && i <= length-2)) { 112 | if(isValidSign(num[i+1]) && isValidNum(num[i+2])) continue; 113 | else if(isValidNum(num[i+1]) && isValidNum(num[i-1])) continue; 114 | else return false; 115 | } else return false; 116 | } 117 | } 118 | 119 | return true; 120 | } 121 | 122 | int main() { 123 | string str = "1e-4"; 124 | cout << validNumberImproved(str) << endl; 125 | return 0; 126 | } -------------------------------------------------------------------------------- /Trie/palindrome_pairs_hard.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file palindrome_pairs_hard.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-12 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | /** 16 | * @brief brute force with nested loops 17 | * 18 | * Time complexity: O((N^2).K), where `K` is the length of the longest string in words 19 | * Space Complexity: O(N^2) (worst case), for storing the resultant palindromic vector of strings 20 | * 21 | * @param words 22 | * @return vector 23 | */ 24 | vector palindromePairs(vector words) { 25 | vector palindromicwords; 26 | int length = words.size(); 27 | string tempWord, reversedWord; 28 | 29 | for(int i = 0; i < length-1; i++) { 30 | for(int j = i+1; j < length; j++) { 31 | tempWord = words[i] + words[j]; 32 | reversedWord = tempWord; 33 | reverse(reversedWord.begin(), reversedWord.end()); 34 | if(reversedWord == tempWord) { 35 | palindromicwords.push_back(tempWord); 36 | } 37 | 38 | // reverse case when a + b si also palindromic for b + a 39 | tempWord = words[j] + words[i]; 40 | reversedWord = tempWord; 41 | reverse(reversedWord.begin(), reversedWord.end()); 42 | if(reversedWord == tempWord) { 43 | palindromicwords.push_back(tempWord); 44 | } 45 | } 46 | } 47 | return palindromicwords; 48 | } 49 | 50 | // optimal solution using valid prefixes and suffixes 51 | // Time Complexity: O((k^2)N), k is the length of the longest string in input array 52 | 53 | /** 54 | * @brief both start and end are inclusive -> [start, end] 55 | * 56 | * @param word 57 | * @param start 58 | * @param end 59 | * @return true 60 | * @return false 61 | */ 62 | bool isValidPalindromeInBetween(string word, int start, int end) { 63 | while(start < end) { 64 | if(word[start] != word[end]) return false; 65 | else { 66 | start++; 67 | end--; 68 | } 69 | } 70 | return true; 71 | } 72 | 73 | vector generateAllValidPrefixes(string word) { 74 | vector validPrefixes; 75 | int length = word.length(); 76 | 77 | for(int i = 0; i < length; i++) { 78 | if(isValidPalindromeInBetween(word, 0, i)) validPrefixes.push_back(word.substr(0,i+1)); 79 | } 80 | return validPrefixes; 81 | } 82 | 83 | vector generateAllValidSuffixes(string word) { 84 | vector validSuffixes; 85 | int length = word.length(); 86 | 87 | for(int i = 0; i < length; i++) { 88 | if(isValidPalindromeInBetween(word, length-1-i, length-1)) validSuffixes.push_back(word.substr(length-1-i, length)); 89 | } 90 | return validSuffixes; 91 | } 92 | 93 | vector palindromePairsImproved(vector words) { 94 | vector palindromicWords; 95 | map wordMap; 96 | int length = words.size(); 97 | 98 | for(auto x : words) { 99 | wordMap[x]++; 100 | } 101 | 102 | vector> allPrefixes(length), allSuffixes(length); 103 | 104 | for(int i = 0; i < length; i++) { 105 | allPrefixes[i] = generateAllValidPrefixes(words[i]); 106 | allSuffixes[i] = generateAllValidSuffixes(words[i]); 107 | } 108 | // find the remaining substring from prefixes and suffixes and reverse thema dn search in the map if they are in map then we have founf a palindromic pair else repeat the steps again to go over the words array 109 | return palindromicWords; 110 | } 111 | 112 | int main() { 113 | vector words = {"abcd","dcba","lls","s","sssll"}; 114 | auto output = palindromePairs(words); 115 | 116 | for(auto x : output) 117 | cout << x << "\t"; 118 | 119 | cout << endl; 120 | 121 | // string str = "banana"; 122 | // auto prfx = generateAllValidSuffixes(str); 123 | // for(auto x : prfx) 124 | // cout << x << "\t"; 125 | return 0; 126 | } -------------------------------------------------------------------------------- /Arrays/merge_intervals.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file merge_intervals.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-11 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | 13 | /** 14 | * Problem: 15 | * 16 | * Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, 17 | * and return an array of the non-overlapping intervals that cover all the intervals in the input. 18 | * 19 | * #1: 20 | * 21 | * Input: intervals = [[1,3],[2,6],[8,10],[15,18]] 22 | * 23 | * Output: [[1,6],[8,10],[15,18]] 24 | * 25 | * Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6]. 26 | * 27 | * #2: 28 | * 29 | * Input: intervals = [[1,4],[4,5]] 30 | * 31 | * Output: [[1,5]] 32 | * 33 | * Explanation: Intervals [1,4] and [4,5] are considered overlapping. 34 | * 35 | */ 36 | #include 37 | using namespace std; 38 | 39 | // vector> MergeIntervals(vector> intervals) { 40 | // int length = intervals.size(); 41 | // vector> mergedIntervals(length); 42 | // int i = 0, j = 1; 43 | // int index = 0; 44 | // int start = -1, end = -1; 45 | // while(i < length && j < length){ 46 | // start = intervals[i][1]; 47 | // end = intervals[j][0]; 48 | 49 | // cout << "start at " << j << " is:\t" << start << endl; 50 | // cout << "end at " << j << " is:\t" << end << endl; 51 | 52 | // // if(j == length-1) { 53 | // // mergedIntervals[index].push_back(intervals[i][0]); 54 | // // mergedIntervals[index].push_back(intervals[j][1]); 55 | // // index++; 56 | // // i = j; 57 | // // i++; 58 | // // j++; 59 | // // break; 60 | // // } 61 | // if(end <= start) { 62 | // j++; 63 | // continue; 64 | // } 65 | // else { 66 | // mergedIntervals[index].push_back(intervals[i][0]); 67 | // mergedIntervals[index].push_back(intervals[j-1][1]); 68 | // cout << "Inserted at: " << index << "\t [ " << intervals[i][0] << ", " << intervals[j-1][1] << " ]" << endl; 69 | // index++; 70 | // i = j; 71 | // j = i+1; 72 | // cout << "new i is: " << i << "\nnew j is: " << j << endl; 73 | // continue; 74 | // } 75 | // continue; 76 | // } 77 | 78 | // if(i < length) { 79 | // if(j > length) { 80 | // if(i == length-1) { 81 | // mergedIntervals[index].push_back(intervals[i][0]); 82 | // mergedIntervals[index].push_back(intervals[i][1]); 83 | // index++; 84 | // }else { 85 | // mergedIntervals[index].push_back(intervals[i][0]); 86 | // mergedIntervals[index].push_back(intervals[length-1][1]); 87 | // cout << "Inserted at: " << index << "\t [ " << intervals[i][0] << ", " << intervals[length-1][1] << " ]" << endl; 88 | // index++; 89 | // } 90 | // } 91 | // } 92 | // return mergedIntervals; 93 | // } 94 | 95 | 96 | bool compare(vector a, vector b) { 97 | return a[0] > b[0]; 98 | } 99 | 100 | vector> MergeIntervals(vector> intervals) { 101 | int index = 0; 102 | vector> merged; 103 | sort(intervals.begin(), intervals.end()); 104 | 105 | for(auto interval : intervals) { 106 | if(merged.empty() || merged.back()[1] < interval[0]) { 107 | merged.push_back(interval); 108 | }else { 109 | merged.back()[1] = max(merged.back()[1], interval[1]); 110 | } 111 | } 112 | 113 | return merged; 114 | } 115 | 116 | int main() { 117 | vector> v = {{1,3}, {2,6}, {8,10}, {15, 18}}; 118 | //cout << v.size() << endl; 119 | auto output = MergeIntervals(v); 120 | 121 | for(auto x : output) { 122 | for(auto y : x) { 123 | cout << y << "\t"; 124 | } 125 | cout << endl; 126 | } 127 | 128 | return 0; 129 | } -------------------------------------------------------------------------------- /LinkedList/copy_list_with_random-pointer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file copy_list_with_random-pointer.cpp 3 | * @author Aditya Rana 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-05 7 | * 8 | * @copyright Copyright (c) 2022 9 | * 10 | */ 11 | 12 | /** 13 | * Problem: 14 | * 15 | * A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or null. 16 | * 17 | * Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the next and random pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list. 18 | * 19 | * 20 | * For example, if there are two nodes X and Y in the original list, where X.random --> Y, then for the corresponding two nodes x and y in the copied list, x.random --> y. 21 | * 22 | * Return the head of the copied linked list. 23 | * 24 | * The linked list is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where: 25 | * 26 | * - val: an integer representing Node.val 27 | * 28 | * - random_index: the index of the node (range from 0 to n-1) that the random pointer points to, or null if it does not point to any node. 29 | * 30 | * 31 | * Your code will only be given the head of the original linked list. 32 | * 33 | */ 34 | #include 35 | using namespace std; 36 | 37 | struct LinkedListNode { 38 | int value; 39 | LinkedListNode* next; 40 | LinkedListNode* random; 41 | 42 | LinkedListNode(int val) { 43 | this->value = val; 44 | next = nullptr; 45 | random = nullptr; 46 | cout << "DEBUG : " << " VALUE : " << this->value << endl; 47 | } 48 | 49 | LinkedListNode(int val, LinkedListNode* nxt) { 50 | this->value = val; 51 | next = nxt; 52 | random = nullptr; 53 | } 54 | 55 | LinkedListNode(int val, LinkedListNode* nxt, LinkedListNode* rnd) { 56 | this->value = val; 57 | this->next = nxt; 58 | this->random = rnd; 59 | } 60 | }; 61 | 62 | void printLinkedList(LinkedListNode* head) { 63 | LinkedListNode* ptr = head; 64 | 65 | while(ptr != nullptr) { 66 | cout << ptr->value << "\n"; 67 | ptr = ptr->next; 68 | } 69 | } 70 | 71 | /** 72 | * @brief 73 | * This solution takes O(N) time and Space as well ! 74 | * 75 | * Doing it in O(1) is quite hard ! 76 | * 77 | * @param head 78 | */ 79 | void CopyLinkedListWithrandomPointer(LinkedListNode *head){ 80 | map hmap; 81 | 82 | LinkedListNode* ptr = head; 83 | 84 | while(ptr != nullptr) { 85 | LinkedListNode* nptr = new LinkedListNode(ptr->value); 86 | hmap.insert({ptr, nptr}); 87 | ptr = ptr->next; 88 | } 89 | 90 | for(auto x : hmap) { 91 | x.second->next = hmap[x.first->next]; 92 | x.second->random = hmap[x.first->random]; 93 | } 94 | 95 | cout << endl << "just before copy" << endl; 96 | printLinkedList(hmap[head]); 97 | } 98 | 99 | void insert(LinkedListNode* head, int val) { 100 | if(head == nullptr) 101 | return; 102 | 103 | LinkedListNode* ptr = head; 104 | while(ptr->next != nullptr){ 105 | ptr = ptr->next; 106 | } 107 | 108 | LinkedListNode* tmp = new LinkedListNode(val); 109 | ptr->next = tmp; 110 | ptr = ptr->next; 111 | } 112 | 113 | LinkedListNode* DeepCopy(LinkedListNode* oldHead) { 114 | if(oldHead == nullptr) return nullptr; 115 | LinkedListNode* newHead = new LinkedListNode(oldHead->value); 116 | LinkedListNode* ptr = oldHead->next; 117 | LinkedListNode* nptr = newHead; 118 | 119 | while(ptr != nullptr) { 120 | LinkedListNode* tmp = new LinkedListNode(ptr->value); 121 | nptr->next = tmp; 122 | nptr = nptr->next; 123 | ptr = ptr->next; 124 | } 125 | 126 | return newHead; 127 | } 128 | 129 | 130 | void DeepCopyEfficiently(LinkedListNode* head) { 131 | LinkedListNode* current = head, *tmp; 132 | 133 | while(current != nullptr) { 134 | tmp = current->next; 135 | current->next = new LinkedListNode(current->value); 136 | current->next->next = tmp; 137 | current = tmp; 138 | } 139 | 140 | current = head; 141 | 142 | while(current != nullptr) { 143 | current->next->random = current->random->next; 144 | current = current->next->next; 145 | } 146 | 147 | current = head; 148 | LinkedListNode* newHead = current->next, *nptr = current->next; 149 | 150 | while(current != nullptr) { 151 | nptr = current->next; 152 | current->next = current->next->next; 153 | current = current->next->next; 154 | nptr->next = current->next; 155 | } 156 | 157 | printLinkedList(newHead); 158 | } 159 | int main() { 160 | LinkedListNode* head = new LinkedListNode(0); 161 | for(int i = 1; i < 6; i++) 162 | insert(head, i); 163 | 164 | //printLinkedList(head); 165 | // LinkedListNode* ll = DeepCopy(head); 166 | // printLinkedList(ll); 167 | //CopyLinkedListWithrandomPointer(head); 168 | DeepCopyEfficiently(head); 169 | return 0; 170 | } --------------------------------------------------------------------------------