├── CrackingTheCodingInterview ├── ArraysAndStrings │ ├── URLify.java │ ├── check_permutation.java │ ├── check_permutation_2.java │ ├── is_unique.java │ ├── is_unique_2.java │ ├── oneAway.java │ ├── palindrome_ permutaion.java │ ├── rotate_matrix.java │ ├── string_compression.java │ ├── string_rotatiion.java │ └── zero_matrix.java ├── LinkedListSolutions │ ├── delete_middle_node.java │ ├── intersection_of_linked_list.java │ ├── loop_detection.java │ ├── palindrome_linked_list.java │ ├── partition_linked_list.java │ ├── remove_duplicates_from_linked_list.java │ ├── return_kth_to_last_node_from_linked_list.java │ └── sum_lists.java ├── StacksAndQueues │ ├── animal_shelter.java │ ├── queue_via_stacks.java │ ├── sort_a_stack.java │ └── stack_min.java └── TreesAndGraphs │ ├── balanced_binary_tree.java │ ├── check_subtree.java │ ├── first_common_ancestor.java │ ├── random_node.java │ ├── route_between_two_nodes.java │ └── topological_sort.java ├── Easy ├── 03_04_2020_closest_value_bst.java ├── 03_06_2020_single_number.java ├── 03_09_2020_branch_sums_recursion.java ├── 03_26_2020_valid_parentheses.java ├── 04_10_2020_product_and_sum.java ├── 04_15_2020_binary_search.java ├── 08_02_2020_bubble_sort.java ├── 08_05_2020_insertion_sort.java ├── 08_09_2020_selection_sort.java ├── 08_21_2022_merge_two_sorted_lists.java ├── 08_21_2022_search_insert_position.java ├── 09_14_2020_intersection_of_two_linked_lists.java ├── 09_15_2020_diameter_of_binary_tree.java ├── 09_16_2020__kadanes_algorithm_maximum_subarray.java ├── 09_16_2020_maximum_subarray.java ├── 09_17_2020_maximum_depth_of_binary_tree.java ├── 09_21_2020_symmetric_tree.java ├── 09_26_2020_atm_queue_google_kickstart.java ├── 09_29_2022_climbing_stairs.java ├── 10_06_2020_convert_sorted_array_to_bst.java ├── 10_25_2020_path_sum.java ├── 11_27_2020_majority_element_boyer_moore_voting_algorithm.java ├── 11_29_2020_merge_sorted_array.java ├── 12_03_2020_valid_perfect_square.java ├── 2022_08_28_best_time_to_buy_and_sell_stock.java └── 2022_09_29_binary_tree_inorder_traversal.java ├── Hard ├── 07_27_2020_trapping_rain_water.java └── 08_11_2020_quick_sort.java ├── Medium ├── 02_01_2020_surrounded_regions.java ├── 02_05_2021_valid_sudoku.java ├── 02_07_2020_binary_tree_zigzag_level_order_traversal.java ├── 02_17_2020_maxim_subset_no_adjacent.java ├── 03_03_2020_array_duplicates.java ├── 03_04_2021_binary_search_tree_iterator.java ├── 03_04_2021_binary_tree_right_side_view.java ├── 03_11_2020_move_arrray_elements.java ├── 03_29_2020_implement_a_set.java ├── 04_27_2020_invert_binary_tree.java ├── 05_07_2021_number_of_closed_islands.java ├── 06_01_2020_remove_nth_node_from_end.java ├── 06_04_2020_longest_palindromic_substring.java ├── 06_13_2020_3_sum.java ├── 07_27_2020_group_anagrams.java ├── 07_31_2020_longest_common_subsequence.java ├── 09_03_2020_power_set.java ├── 09_18_2020_two_city_scheduling.java └── 11_07_2021_odd_even_linked_list.java └── README.md /CrackingTheCodingInterview/ArraysAndStrings/URLify.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | String str = "Mr John Smith "; 5 | System.out.println(URLify2(str.toCharArray(), 13)); 6 | 7 | } 8 | /* 9 | Approach 1: Using regex 10 | */ 11 | public static String URLify(String url) { 12 | return url.replaceAll("[ ]+", "%20"); 13 | } 14 | /* 15 | Approach 2: Using true length 16 | */ 17 | public static String URLify2(char[] url, int trueLength) { 18 | int spaceCount = 0; 19 | int index; 20 | int i = 0; 21 | for (i = 0; i < trueLength; i++) { 22 | // Count the number of spaces 23 | if (url[i] == ' ') { 24 | spaceCount++; 25 | } 26 | } 27 | index = trueLength + spaceCount * 2; 28 | System.out.println("Index : " + index); 29 | if (trueLength < url.length) { 30 | url[trueLength] = '\0'; // Mark the end of the array 31 | System.out.println("yes"); 32 | System.out.println(Arrays.toString(url)); 33 | } 34 | for (i = trueLength - 1; i >= 0; i--) { 35 | if (url[i] == ' ') { 36 | // Replace the 3 consecutive characters backwards with %20 37 | url[index - 1] = '0'; 38 | url[index - 2] = '2'; 39 | url[index - 3] = '%'; 40 | // Update the new index 41 | index = index - 3; 42 | 43 | System.out.println("New Index: " + index); 44 | System.out.println(Arrays.toString(url)); 45 | } else { 46 | // Move the prev character one place up 47 | url[index - 1] = url[i]; 48 | // Update the index 49 | System.out.println("New Index: " + index); 50 | System.out.println(Arrays.toString(url)); 51 | index--; 52 | } 53 | } 54 | return new String(url); 55 | } 56 | 57 | 58 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/check_permutation.java: -------------------------------------------------------------------------------- 1 | /**These are mostly my own solutions, sometimes I put the solutions in the book too, but you get the idea */ 2 | import java.util.*; 3 | public class MyClass { 4 | public static void main(String args[]) { 5 | System.out.println(checkPermutation2("abc", "bac")); 6 | } 7 | /* 8 | Sorting approach 9 | Time: O(n log n) 10 | */ 11 | public static boolean checkPermutation(String a, String b) { 12 | // if one is a permutation of the other, they have the same characters 13 | // you can sort them and check for equality 14 | // you can count the occurence of each character 15 | String nA = sort(a); 16 | String nB = sort(b); 17 | return nA.equals(nB); 18 | 19 | } 20 | /* 21 | Count each occurence approach O(n) 22 | */ 23 | public static boolean checkPermutation2(String a, String b) { 24 | Map map = new HashMap<>(); 25 | for (int i = 0; i < a.length(); i++) { 26 | char current = a.charAt(i); 27 | // Increment this character's occurences or put 1 if it's the first occurence 28 | map.put(current, map.getOrDefault(current, 0) + 1); 29 | } 30 | // Now go through b and make sure it's the same or subtract one 31 | for (int i = 0; i < b.length(); i++) { 32 | char current = b.charAt(i); 33 | if (!map.containsKey(current)) { 34 | return false; 35 | } 36 | // if it's there subtract it 37 | map.put(current, map.get(current) - 1); 38 | } 39 | for (char ch : map.keySet()) { 40 | if (map.get(ch) != 0) { 41 | // Something went wrong return false 42 | return false; 43 | } 44 | } 45 | return true; 46 | } 47 | public static String sort(String s) { 48 | char[] array = s.toCharArray(); 49 | Arrays.sort(array); 50 | return new String(array); 51 | } 52 | 53 | // Did not compile the following method but should be conceptually 54 | // understandable 55 | public static boolean isPermutation2(String a, String b) { 56 | // Count the characters at each ascii index 57 | boolean[] ascii = new boolean[128]; 58 | for (char ca : a.toCharArray()) { 59 | int asciiVal = (int) ca; 60 | ascii[asciiVal]++; 61 | } 62 | // Now iterate through ascii with b and subtract 63 | for (char cb : b.toCharArray()) { 64 | int asciiVal = (int) cb; 65 | ascii[asciiVal]--; 66 | if (ascii[asciiVal] < 0) return false; 67 | } 68 | return true; 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/check_permutation_2.java: -------------------------------------------------------------------------------- 1 | public static boolean isPermutation(String a, String b) { 2 | char[] charactersInA = a.toCharArray(); 3 | char[] charactersInB = b.toCharArray(); 4 | 5 | Arrays.sort(charactersInA); 6 | Arrays.sort(charactersInB); 7 | 8 | String sortedA = charArrayToString(charactersInA); 9 | String sortedB = charArrayToString(charactersInB); 10 | 11 | return sortedA.equals(sortedB); 12 | 13 | 14 | } 15 | public static String charArrayToString(char[] array) { 16 | StringBuilder sb = new StringBuilder(); 17 | for (char c : array) { 18 | sb.add(c); 19 | } 20 | return sb.toString(); 21 | } 22 | 23 | // A more optimal approach 24 | 25 | public static boolean isPermutation2(String a, String b) { 26 | // Count the characters at each ascii index 27 | boolean[] ascii = new boolean[128]; 28 | for (char ca : a.toCharArray()) { 29 | int asciiVal = (int) ca; 30 | ascii[asciiVal]++; 31 | } 32 | // Now iterate through ascii with b and subtract 33 | for (char cb : b.toCharArray()) { 34 | int asciiVal = (int) cb; 35 | ascii[asciiVal]--; 36 | if (ascii[asciiVal] < 0) return false; 37 | } 38 | return true; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/is_unique.java: -------------------------------------------------------------------------------- 1 | public class MyClass { 2 | public static void main(String args[]) { 3 | System.out.println(hasUniqueCharsOptimized("abc")); 4 | } 5 | /* 6 | Time: O(n) -> check if the "contains" method in a string runs in O(n) time, 7 | in that case it will be O(n^2) 8 | Space: O(1) 9 | */ 10 | public static boolean hasUniqueChars(String s) { 11 | // Approach: Go through s, at every index. 12 | // Check the left and right sides to see if the same char is present 13 | // We may only need to check the left side even 14 | if (s.length() == 0 || s == null) { 15 | return true; 16 | } 17 | for (int i = 0; i < s.length(); i++) { 18 | String current = String.valueOf(s.charAt(i)); 19 | String leftSide = s.substring(0, i); 20 | if (leftSide.contains(current)) { 21 | // We've seen this before, return false 22 | return false; 23 | } 24 | } 25 | // If we did not see a repeating character 26 | return true; 27 | } 28 | 29 | // Alternatively, each character has a unique asc code. We can create an array of all possible 30 | // asc codes and enter true or false when we see a character 31 | public static boolean hasUniqueCharsOptimized(String s) { 32 | boolean[] contains = new boolean[128]; // Assuming alpha numeric only 33 | // You can also do 26 and convert the letter to it's alphabetical number 34 | for (int i = 0; i < s.length(); i++) { 35 | int value = s.charAt(i); 36 | if (contains[value]) { 37 | return false; 38 | } 39 | // Else, put this value in the contains array 40 | contains[value] = true; 41 | } 42 | // If we did not see a repeating character 43 | return true; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/is_unique_2.java: -------------------------------------------------------------------------------- 1 | // First algo: increment a certain number 2 | 3 | 4 | 5 | public static boolean isUnique(String str) { 6 | Set mySet = new HashSet<>(); 7 | for (int i = 0; i < str.length; i++) { 8 | char ch = str.charAt(i); 9 | if (mySet.contains(ch)) return false; 10 | mySet.add(ch); 11 | } 12 | return true; 13 | } 14 | 15 | public static boolean isUnique(String str) { 16 | Set mySet = new HashSet<>(); 17 | int stringLength = str.length(); 18 | int counter = stringLength; 19 | for (int i = 0; i < str.length; i++) { 20 | char ch = str.charAt(i); 21 | if (mySet.contains(ch)) counter--; 22 | mySet.add(ch); 23 | } 24 | return counter == stringLength; 25 | } 26 | 27 | public static boolean isUnique(String str) { 28 | boolean[] contains = new boolean[128]; 29 | for (int i = 0; i < str.length; i++) { 30 | int ascValue = str.charAt(i); 31 | if (contains[ascValue]) return false; 32 | contains[ascValue] = true; 33 | } 34 | return true; 35 | 36 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/oneAway.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | System.out.println(oneAway("bakes", "bale")); 5 | System.out.println(oneAwayOptimized("bakes", "bale")); 6 | 7 | } 8 | public static boolean oneAway(String a, String b) { 9 | if (a.length() == b.length()) { 10 | return isOneReplacementAway(a, b); 11 | } else if (a.length() - 1 == b.length()) { 12 | return isOneEditOrDeleteAway(a, b); 13 | } else if (b.length() - 1 == a.length()) { 14 | return isOneEditOrDeleteAway(b, a); 15 | } 16 | // return false if the two strings have more than one character difference, etc. 17 | return false; 18 | } 19 | public static boolean isOneReplacementAway(String a, String b) { 20 | // The differ by only one character 21 | boolean differenceFound = false; 22 | for (int i = 0; i < a.length(); i++) { 23 | // check for only one difference 24 | if (a.charAt(i) != b.charAt(i)) { 25 | // The first differnce will get a pass 26 | if (differenceFound) { 27 | return false; 28 | } 29 | differenceFound = true; 30 | } 31 | } 32 | return true; 33 | } 34 | public static boolean isOneEditOrDeleteAway(String a, String b) { 35 | // Assuming a is the longer string 36 | int index1 = 0; 37 | int index2 = 0; 38 | while (index1 < a.length() && index2 < b.length()) { 39 | // Compare their characters to make sure they are at least one edit or delete away 40 | if (a.charAt(index1) != b.charAt(index2)) { 41 | // They are different, move the longer string one place up 42 | // if indices 1 and 2 are the same, it means this is the first edit or delete 43 | // instance that we have come across, so it gets a pass. if indices 1 and 2 44 | // are different, then we have more than one edit or delete instances 45 | if (index1 != index2) { 46 | return false; 47 | } 48 | index1 += 1; 49 | } else { 50 | // If they are the same, move on to check the i + 1th characters in both strings 51 | index1 += 1; 52 | index2 += 1; 53 | } 54 | } 55 | return true; 56 | } 57 | /* 58 | 59 | The following is the optimized function that merges all 3 conditions to one function 60 | */ 61 | 62 | 63 | public static boolean oneAwayOptimized(String a, String b) { 64 | // Check that the lengths of the strings differ by at most 1 65 | if (Math.abs(a.length() - b.length()) > 1) return false; 66 | 67 | // Determine which string is longer or shorter 68 | String longer = (a.length() > b.length()) ? a : b; 69 | String shorter = (a.length() < b.length()) ? a : b; 70 | 71 | // Now check for all 3 conditions in one function 72 | int indexLong = 0; 73 | int indexShort = 0; 74 | boolean differenceFound = false; 75 | 76 | while (indexLong < longer.length() && indexShort < shorter.length()) { 77 | if (longer.charAt(indexLong) != shorter.charAt(indexShort)) { 78 | // Check if we have more than one replace (first condition) 79 | if (differenceFound) { 80 | return false; 81 | } 82 | differenceFound = true; 83 | // Now check for the delete and edit case 84 | if (longer.length() == shorter.length()) { 85 | // Move the shorter pointer forward 86 | indexShort += 1; 87 | indexLong += 1; 88 | // We're always moving the longer pointer at the end of the loop 89 | } else { 90 | // The lengths are different, move the longer one 91 | indexLong += 1; 92 | } 93 | } else { 94 | // The characters are the same, move the shorter pointer 95 | indexShort += 1; 96 | indexLong += 1; 97 | 98 | } 99 | } 100 | return true; 101 | 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/palindrome_ permutaion.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | String str = "Mr John Smith "; 5 | System.out.println(isPermutationOfPalindrome("Tact Coa")); 6 | 7 | } 8 | public static boolean isPermutationOfPalindrome(String s) { 9 | s = s.toLowerCase(); 10 | Map map = new HashMap<>(); 11 | for (int i = 0; i < s.length(); i++) { 12 | char current = s.charAt(i); 13 | // update it's occurence in the map 14 | if (current == ' ') { 15 | continue; 16 | } 17 | map.put(current, map.getOrDefault(current, 0) + 1); 18 | 19 | } 20 | // Check that no character has more than 1 odd occurence 21 | boolean foundOdd = false; 22 | for (char c : map.keySet()) { 23 | System.out.println(c + " -> " + map.get(c)); 24 | if (map.get(c) % 2 == 1) { 25 | // it has an odd occurence 26 | // If we've foundOdd before we return false; 27 | if (foundOdd) { 28 | return false; 29 | } 30 | // otherwise we havent found odd before, set to true 31 | foundOdd = true; 32 | } 33 | } 34 | return true; 35 | } 36 | 37 | 38 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/rotate_matrix.java: -------------------------------------------------------------------------------- 1 | public class rotate_matrix { 2 | 3 | } 4 | import java.util.*; 5 | public class MyClass { 6 | public static void main(String args[]) { 7 | 8 | int[][] matrix = new int[][] { 9 | {1, 2, 3}, 10 | {4, 5, 6}, 11 | {7, 8, 9} 12 | }; 13 | int[][] ans = rotateMatrix(matrix); 14 | for (int[] row: ans) { 15 | System.out.println(Arrays.toString(row)); 16 | } 17 | 18 | 19 | } 20 | public static int[][] rotateMatrix(int[][] matrix) { 21 | // Step 1: Transpose matrix 22 | for (int i = 0; i < matrix.length; i++) { 23 | for (int j = i; j < matrix[i].length; j++) { 24 | int temp = matrix[i][j]; 25 | matrix[i][j] = matrix[j][i]; 26 | matrix[j][i] = temp; 27 | } 28 | } 29 | 30 | // Step 2: Flip horizontally 31 | for (int[] row : matrix) { 32 | int left = 0; 33 | int right = row.length - 1; 34 | while (left < right) { 35 | int temp = row[left]; 36 | row[left] = row[right]; 37 | row[right] = temp; 38 | left++; 39 | right--; 40 | } 41 | } 42 | return matrix; 43 | 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/string_compression.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | System.out.println(compress("aabcccccaaa")); 5 | 6 | } 7 | public static String compress(String s) { 8 | // TODO: Check for edge cases 9 | int count = 0; 10 | StringBuilder sb = new StringBuilder(); 11 | for (int i = 0; i < s.length(); i++) { 12 | // System.out.println("Current : " + s.charAt(i)); 13 | count += 1; 14 | // We get the current character 15 | char thisChar = s.charAt(i); 16 | // System.out.println(i + " : " + thisChar + " : " + count); 17 | if (i == s.length() - 1 || s.charAt(i) != s.charAt(i + 1)) { 18 | // reset 19 | // System.out.println("should append " + i + " : " + s.charAt(i) + " : " + count); 20 | sb.append(s.charAt(i)); 21 | sb.append(count); 22 | count = 0; 23 | 24 | } 25 | 26 | } 27 | 28 | 29 | return sb.toString().length() < s.length() ? sb.toString() : s; 30 | } 31 | 32 | }public class string_compression { 33 | 34 | } 35 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/string_rotatiion.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | System.out.println(isRotation("waterbottle", "erbottlewat")); 5 | } 6 | public static boolean isRotation(String s1, String s2) { 7 | if (s1.length() == s2.length() && s1.length() > 0) { 8 | String s1s1 = s1 + s1; 9 | return s1s1.contains(s2); 10 | } 11 | return false; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/ArraysAndStrings/zero_matrix.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | } 5 | public static void zeroMatrix(int[][] matrix) { 6 | // Keep tract of whether a row or col has 0 with these boolean arrays 7 | boolean[] rows = new boolean[matrix.length]; 8 | boolean[] cols = new boolean[matrix[0].length]; 9 | 10 | for (int i = 0; i < matrix.length; i++) { 11 | for (int j = 0; j < matrix[i].length; j++) { 12 | if (matrix[i][j] == 0) { 13 | // This row and col should be nullified 14 | rows[i] = true; 15 | cols[j] = true; 16 | } 17 | } 18 | } 19 | // Now iterate through rows and cols and nullify them 20 | for (int i = 0; i < rows.length; i++) { 21 | if (rows[i] == true) { 22 | // Set this row to 0's 23 | nullifyRow(matrix, i); 24 | } 25 | } 26 | 27 | for (int i = 0; i < cols.length; i++) { 28 | if (cols[i] == true) { 29 | // Set this col to 0's 30 | nullifyCol(matrix, i); 31 | } 32 | } 33 | 34 | 35 | 36 | } 37 | /* 38 | 39 | The following is the optimized function 40 | */ 41 | public static void zeroMatrixOptimized(int[][] matrix) { 42 | boolean firstRowHasZero = false; 43 | boolean firstColHasZero = false; 44 | 45 | // Check whether first row and col have 0; 46 | for (int i = 0; i < matrix[0].length; i++) { 47 | if (matrix[0][i] == 0) { 48 | // This row has 0 49 | firstRowHasZero = true; 50 | break; 51 | } 52 | } 53 | 54 | for (int i = 0; i < matrix.length; i++) { 55 | if (matrix[i][0] == 0) { 56 | // This col has 0 57 | firstColHasZero = true; 58 | break; 59 | } 60 | } 61 | // Now check for zeros in the rest of the array and store the state in the first 62 | // Row and col 63 | for (int i = 0; i < matrix.length; i++) { 64 | for (int j = 0; j < matrix[i].length; j++) { 65 | if (matrix[i][j] == 0) { 66 | // This row and col should be nullified 67 | matrix[i][0] = 0; 68 | matrix[0][j] = 0; 69 | } 70 | } 71 | } 72 | // Then we can nullify the rows and cols based on the values of the first row 73 | // And first col 74 | for (int i = 1; i < matrix[0].length; i++) { 75 | if (matrix[0][i] == 0) { 76 | // Nullify this row 77 | nullifyRow(matrix, i); 78 | } 79 | } 80 | 81 | for (int i = 1; i < matrix.length; i++) { 82 | if (matrix[i][0] == 0) { 83 | // Nullify this col 84 | nullifyCol(matrix, i); 85 | } 86 | } 87 | 88 | // Now check if first row and col had 0 initially and nullify them as well 89 | if (firstRowHasZero) { 90 | nullifyRow(matrix, 0); 91 | } 92 | if (firstColHasZero) { 93 | nullifyCol(matrix, 0); 94 | } 95 | 96 | } 97 | public static void nullifyRow(int[][] matrix, int row) { 98 | for (int col = 0; col < matrix[row].length; col++) { 99 | matrix[row][col] = 0; 100 | } 101 | } 102 | public static void nullifyCol(int[][] matrix, int col) { 103 | for (int row = 0; row < matrix.length; row++) { 104 | matrix[row][col] = 0; 105 | } 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/delete_middle_node.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(1) 3 | * Space: O(1) 4 | */ 5 | boolean deleteNode(LinkedListNode n) { 6 | if (n == null || n.next == nUll) { 7 | return false; // Failure 8 | } 9 | LinkedListNode next = n.next; 10 | n.data = next.data; 11 | n.next = next.next; 12 | return true; 13 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/intersection_of_linked_list.java: -------------------------------------------------------------------------------- 1 | // Refer to "./../Easy/09_14_2020_intersection_of_two_linked_lists.java" -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/loop_detection.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | // System.out.println(isRotation("waterbottle", "erbottlewat")); 5 | } 6 | public static boolean loopDetection(ListNode head) { 7 | 8 | // Make sure head.next != null 9 | ListNode fast = head; 10 | ListNode slow = head.next.next; 11 | 12 | while (fast != slow) { 13 | if (slow == null || slow.next == null) return null; 14 | fast = fast.next; 15 | slow = slow.next.next; 16 | } 17 | // When we break they intersect 18 | fast = head; 19 | while (fast != slow) { 20 | fast = fast.next; 21 | slow = slow.next; 22 | } 23 | return fast; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/palindrome_linked_list.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public boolean isPalindrome(ListNode head) { 3 | // Move two pointers together. 4 | // Ptr one moves one step and Ptr 2 moves two steps. When ptr2 is null, ptr1 5 | // will be in the middle of the list 6 | // reset ptr2 to head, and reverse list starting at ptr1 (middle) 7 | // Move both pointers in tandem and check for equality 8 | 9 | ListNode fast = head; 10 | // Reverse the second list 11 | ListNode slow = head; 12 | while (fast != null && fast.next != null) { 13 | fast = fast.next.next; 14 | slow = slow.next; 15 | } 16 | fast = head; 17 | slow = reverse(slow); 18 | // Now check them in tandem for equality 19 | while (slow != null) { 20 | if (fast.val != slow.val) return false; 21 | fast = fast.next; 22 | slow = slow.next; 23 | } 24 | return true; 25 | } 26 | public ListNode reverse(ListNode head) { 27 | ListNode prev = null; 28 | ListNode current = head; 29 | while (current != null) { 30 | ListNode next = current.next; 31 | current.next = prev; 32 | prev = current; 33 | current = next; 34 | } 35 | return prev; 36 | } 37 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/partition_linked_list.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) 3 | * Space: O(n) 4 | */ 5 | public ListNode partition(ListNode node, int x) { 6 | // Create two lists. One for nodes less than x and the other 7 | // For nodes greater than x. Iterate through the input list 8 | // building the lesser and greater list and merge at the end 9 | ListNode beforeStart = null; 10 | ListNode afterStart = null; 11 | ListNode beforeEnd = null; 12 | ListNode afterEnd = null; 13 | 14 | while (node != null) { 15 | // Let us insert into the before and after lists 16 | ListNode next = node.next; 17 | node.next = null; // Cut off the connection to the other nodes 18 | if (node.val < x) { 19 | // Insert into before list 20 | if (beforeStart == null) { 21 | beforeStart = node; 22 | beforeEnd = beforeStart; 23 | } else { 24 | beforeEnd.next = node; 25 | beforeEnd = node; 26 | } 27 | } else { 28 | // Insert into after list 29 | if (afterStart == null) { 30 | afterStart = node; 31 | afterEnd = afterStart; 32 | } else { 33 | afterEnd.next = node; 34 | afterEnd = node; 35 | } 36 | } 37 | node = next; 38 | } 39 | // Now we check if our before list == null, meaning we only 40 | // Have nodes that are greater so we return after 41 | if (beforeStart == null) return afterStart; 42 | 43 | // Merge both before and after lists 44 | beforeEnd.next = afterStart; 45 | return beforeStart; 46 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/remove_duplicates_from_linked_list.java: -------------------------------------------------------------------------------- 1 | 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | 5 | } 6 | public static boolean isRotation(String s1, String s2) { 7 | 8 | } 9 | public void deleteDups(ListNode n) { 10 | HashSet set = new HashSet<>(); 11 | ListNode prev = null; 12 | while (n != null) { 13 | if (set.contains(n.val) { 14 | prev.next = n.next; 15 | } else { 16 | set.add(n.val); 17 | previous = n; 18 | } 19 | n = n.next; 20 | } 21 | } 22 | public void deleteDups(ListNode n) { 23 | ListNode current = n; 24 | while (current != null) { 25 | // Remove all future nodes that have the same value 26 | ListNode runner = current; 27 | while (runner.next != null) { 28 | if (runner.next.val == current.val) { 29 | runner.next = runner.next.next; 30 | } else { 31 | runner = runner.next; 32 | } 33 | } 34 | current = current.next; 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/return_kth_to_last_node_from_linked_list.java: -------------------------------------------------------------------------------- 1 | // This is almost identical to the remove kth node from end question (in the Medium folder) 2 | /** 3 | * Time: O(n) 4 | * Space: O(1) 5 | */ 6 | public ListNode nthToLast(ListNode head, int k) { 7 | ListNode p1 = head; 8 | ListNode p2 = head; 9 | // Move p1 k nodes ahead 10 | for (int i = 0; i < k; i++) { 11 | if (p1 == null) return null; // Out of bounds 12 | p1 = p1.next; 13 | } 14 | // Move both pointers in tandem until p1 reaches the end 15 | while (p1 != null) { 16 | p1 = p1.next; 17 | p2 = p2.next; 18 | } 19 | return p2; 20 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/LinkedListSolutions/sum_lists.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class MyClass { 3 | public static void main(String args[]) { 4 | // System.out.println(isRotation("waterbottle", "erbottlewat")); 5 | } 6 | public static ListNode sumList(ListNode l1, ListNode l2, int carry) { 7 | if (l1 == null && l2 == null && carry == 0) return null; 8 | ListNode result = new ListNode(); 9 | // Now we can add 10 | int value = 0; 11 | if (l1 != null) { 12 | value += l1.data; 13 | } 14 | if (l2 != null) { 15 | value += l2.data; 16 | } 17 | // Now we can add carry 18 | value += carry; 19 | // determine what carry will be 20 | result.data = value & 10; 21 | // Recurse on the next addition if one of l1 or l2 is not null 22 | if (l1 != null || l2 != null) { 23 | ListNode next = sumList(l1 == null ? null : l1, 24 | l2 == null ? null : l2, 25 | value / 10); 26 | result.next = next; 27 | } 28 | return result; 29 | 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/StacksAndQueues/animal_shelter.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | /** 3 | * PSA: I apologize if there are typos here; I did not run this to check, 4 | * but it looks intuitively fine, in the actual interview, you don't run code on the 5 | * whiteboard just make sure it makes sense. love :) 6 | */ 7 | abstract class Animal { 8 | private int order; 9 | protected String name; 10 | public Animal (String name) { 11 | this.name = name; 12 | } 13 | // The order in which the animal was received 14 | public void setOrder(int order) { 15 | this.order = order; 16 | } 17 | public int gerOrder() { 18 | return order; 19 | } 20 | // Compare which animal is older than which 21 | public boolean isOlderThan (Animal a) { 22 | // Means this came in earlier than a so it has a lesser order 23 | return this.order < a.getOrder; 24 | } 25 | } 26 | 27 | class AnimalQueue { 28 | Queue cats = new ArrayDeque<>(); 29 | Queue dogs = new ArrayDeque<>(); 30 | public int order; // Maintains the timestamp, you can also choose to peek from 31 | // either dog or cat and increment +1 for the order but that is a whole other step 32 | // It is easier this way 33 | 34 | // Instantiate the two queues 35 | public AnimalQueue () { 36 | 37 | } 38 | public void enqueue (Animal a) { 39 | a.setOrder(order); 40 | order++; 41 | 42 | if (a.instanceof Dog) { 43 | // Add to dog queue 44 | dogs.push(a); 45 | } else { 46 | // There is only one option left 47 | cats.push(a); 48 | } 49 | } 50 | 51 | public Animal dequeueAny() { 52 | // Looks at the top of both cats and dogs and return the oldest 53 | if (dogs.size() == 0) { 54 | // If there are no dogs we can only afford to give out cats, mean cats 55 | return dequeueCats(); 56 | } 57 | if (cats.size() == 0) { 58 | // If we have no cats, yaaay! Who let the dogs out??? 59 | return dequeueDogs(); 60 | } 61 | // If we have both dogs and cats, let us pick the oldest 62 | Dog dog = dogs.peek(); 63 | Cat cat = cats.peek(); 64 | if (dog.isOlderThan(cat)) { 65 | return dequeueDogs(); 66 | } else { 67 | return dequeueCats(); 68 | } 69 | } 70 | public Cat dequeueCats () { 71 | // Remove the oldest in cat 72 | return cats.poll(); 73 | } 74 | public Dog dequeueDogs () { 75 | // Remove the oldest in dogs 76 | return dogs.poll(); 77 | } 78 | } 79 | 80 | public class Dog extends Animal { 81 | public Dog (String name) { 82 | super(name); 83 | } 84 | } 85 | 86 | public class Cat extends Animal { 87 | public Cat (String name) { 88 | super(name); 89 | } 90 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/StacksAndQueues/queue_via_stacks.java: -------------------------------------------------------------------------------- 1 | public class MyClass { 2 | public static void main(String args[]) { 3 | } 4 | 5 | } 6 | public class MyQueue { 7 | Stack stackNewest = new Stack<>(); 8 | Stack stackOldest = new Stack<>(); 9 | 10 | public int peek(){ 11 | // Return from the oldest stack 12 | shiftStacks(); 13 | int newestNum = stackOldest.peek(); 14 | return newestNum; 15 | } 16 | public void push(int num) { 17 | // Push to the newest 18 | stackNewest.push(num); 19 | } 20 | public int pop() { 21 | // Remove from the oldest stack but make sure oldest 22 | // has something in it 23 | shiftStacks(); 24 | int value = stackOldest.pop(); 25 | return value; 26 | } 27 | public void shiftStacks() { 28 | if (stackOldest.isEmpty()) { 29 | while (!stackNewest.isEmpty()) { 30 | stackOldest.push(stackNewest.pop()); 31 | } 32 | } 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/StacksAndQueues/sort_a_stack.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n^2) 3 | * Space: O(n) 4 | */ 5 | import java.util.*; 6 | 7 | public class MyClass { 8 | public static void main(String args[]) { 9 | // Create an example stack and add items to it 10 | Stack s = new Stack<>(); 11 | int[] numbers = new int[]{5, 7, 3, 6, 7, 3, 27, 4}; 12 | for (int num : numbers) { 13 | s.push(num); 14 | } 15 | // Call the sorting function we created below 16 | sort(s); 17 | while (!s.isEmpty()) { 18 | // Print to see that the sorting actually worked 19 | System.out.print(s.pop() + ","); 20 | } 21 | 22 | } 23 | 24 | /* 25 | The idea is to create an additional stack 26 | which will be sorted and we maintain it's state by 27 | popping larger elements out and pushing smaller elements in 28 | 29 | */ 30 | public static void sort(Stack main) { 31 | Stack temp = new Stack<>(); 32 | // While there are elements in main 33 | while (!main.isEmpty()) { 34 | // Pick a pivot value 35 | int pivot = main.pop(); 36 | // While we have bigger values in temp, pop em out 37 | while (!temp.isEmpty() && temp.peek() > pivot) { 38 | main.push(temp.pop()); 39 | } 40 | // otherwise, push pivot in 41 | temp.push(pivot); 42 | 43 | } 44 | // Add the elements back into main so that they appear in 45 | // Ascending order 46 | while (!temp.isEmpty()) { 47 | main.push(temp.pop()); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/StacksAndQueues/stack_min.java: -------------------------------------------------------------------------------- 1 | public import java.util.*; 2 | class MinStack { 3 | 4 | /** initialize your data structure here. */ 5 | List stack = new ArrayList<>(); 6 | List minStack = new ArrayList<>(); 7 | public MinStack() { 8 | 9 | } 10 | 11 | public void push(int x) { 12 | int min = x; 13 | if (stack.size() > 0) { 14 | // Means there are items here and we need to calculate the curr min 15 | int lastMin = minStack.get(minStack.size() - 1); 16 | min = Math.min(lastMin, min); 17 | } 18 | minStack.add(min); 19 | stack.add(x); 20 | System.out.print(x + " -> "); 21 | System.out.println("Min : " + min); 22 | } 23 | 24 | public void pop() { 25 | minStack.remove(minStack.size() - 1); 26 | stack.remove(stack.size() - 1); 27 | } 28 | 29 | public int top() { 30 | return stack.get(stack.size() - 1); 31 | } 32 | 33 | public int getMin() { 34 | return minStack.get(minStack.size() - 1); 35 | } 36 | } 37 | 38 | /** 39 | * Your MinStack object will be instantiated and called as such: 40 | * MinStack obj = new MinStack(); 41 | * obj.push(x); 42 | * obj.pop(); 43 | * int param_3 = obj.top(); 44 | * int param_4 = obj.getMin(); 45 | */class stack_min { 46 | 47 | } 48 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TreesAndGraphs/balanced_binary_tree.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public boolean isBalanced(TreeNode root) { 3 | if (root == null) return true; 4 | int leftDepth = getDepth(root.left); 5 | int rightDepth = getDepth(root.right); 6 | int heightDiff = Math.abs(leftDepth - rightDepth); 7 | if (heightDiff > 1) { 8 | return false; 9 | } else { 10 | return isBalanced(root.left) && isBalanced(root.right); 11 | } 12 | } 13 | public int getDepth(TreeNode root) { 14 | if (root == null) return -1; 15 | // System.out.println(root.val); 16 | int depthHere = Math.max(getDepth(root.left), getDepth(root.right)) + 1; 17 | return depthHere; 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TreesAndGraphs/check_subtree.java: -------------------------------------------------------------------------------- 1 | public class MyClass { 2 | public static void main(String args[]) { 3 | 4 | } 5 | 6 | // Check subtree, do a preorder traversal, adding 7 | // all nodes to a string including null nodes 8 | // and check the emerging strings for equality 9 | public void checkSubtree(TreeNode a, TreeNode b) { 10 | String a = getString(a, ""); 11 | String b = getString(b, ""); 12 | 13 | return a.contains(b); 14 | 15 | } 16 | public String getString(TreeNode node, String str) { 17 | if (node == null) { 18 | // You can optimze this with a String builder 19 | str += "X"; 20 | return str; 21 | } 22 | // If the node is not null, add it's value to the str 23 | str += node.val.toString(); 24 | // Now visit the left and right children nodes 25 | str += getString(node.left, str); 26 | str += getString(node.right, str); 27 | return str; 28 | } 29 | 30 | /* 31 | Alternative approach: only call the match function 32 | when you find b's root in a 33 | */ 34 | public boolean isSubTree(TreeNode a, TreeNode b) { 35 | if (a == null) return false; 36 | // a is not null 37 | if (a.val = b.val) { 38 | // Call the match function 39 | String aStr = getString(a, ""); 40 | String bStr = getString(b, ""); 41 | if (aStr.contains(bStr) return true; 42 | } 43 | // if a is not equal to b, check other nodes in a 44 | return isSubTree(a.left, b) || isSubTree(a.right, b); 45 | } 46 | 47 | // You can also make a match function that compares nodes 48 | // in tandem like so 49 | 50 | public boolean match(TreeNode a, TreeNode b) { 51 | if (a == null && b == null) { 52 | return true; 53 | } else if (a == null || b == null) { 54 | return false; // Only one tree is null 55 | } else if (a.val != b.val) { 56 | return false; 57 | } else { 58 | // These current nodes are equal, check others 59 | return match(a.left, b.left) && 60 | match(a.right, b.right); 61 | } 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TreesAndGraphs/first_common_ancestor.java: -------------------------------------------------------------------------------- 1 | public class MyClass { 2 | public static void main(String args[]) { 3 | 4 | } 5 | 6 | // Traverse from one node upwards 7 | public findAncestor(TreeNode p, TreeNode q) { 8 | 9 | } 10 | public findAncestor(TreeNode child, TreeNode parent, 11 | TreeNode q) { 12 | if (child == q) { 13 | // Q has been found 14 | } 15 | if (parent.left == child) { 16 | // Newly uncovered tree is the right 17 | // Find q in this tree rooted at this parent 18 | if (findChild(parent.right, q)) return parent; 19 | // We did not find q on this subtree, so we 20 | // move up 21 | return findAncestor(parent, parent.parent, q); 22 | 23 | } else { 24 | // Newly uncovered tree is the left 25 | if (findChild(parent.right, q)) return parent; 26 | return findAncestor(parent, parent.parent, q); 27 | 28 | } 29 | } 30 | public boolean findChild(TreeNode parent, 31 | TreeNode child) { 32 | // Use a simple dfs algorithm to search 33 | if (parent == null) { 34 | return false; 35 | } 36 | // Visit this node. 37 | if (parent == child) { 38 | return true; 39 | } 40 | return findChild(parent.left, child) || 41 | findChild(parent.right, child); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TreesAndGraphs/random_node.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This code has been checked for syntax errors and typos, 3 | * some of the code in CTCI folder haven't. Hit me up if you want to run them 4 | * and check for typos :) love 5 | */ 6 | import java.util.*; 7 | public class MyClass { 8 | public static void main(String args[]) { 9 | int[] nums = new int[] { 10 | 1, 2, 4, 6, 8, 10, 12, 14, 16 11 | }; 12 | TreeNode node = new TreeNode(0); 13 | for (int num : nums) { 14 | node.insert(num); 15 | } 16 | // Now we can use the get random node function 17 | for (int i = 0; i < 10; i++) { 18 | TreeNode random = node.getRandomNode(); 19 | System.out.println(random.data); 20 | } 21 | 22 | } 23 | 24 | } 25 | class TreeNode { 26 | int data; 27 | int size; 28 | TreeNode left; 29 | TreeNode right; 30 | 31 | public TreeNode(int d) { 32 | this.data = d; 33 | this.size = 1; 34 | } 35 | // Get Random node 36 | public TreeNode getRandomNode() { 37 | int leftSize = this.left == null ? 0 : this.left.size; 38 | // Generate a Random 39 | Random random = new Random(); 40 | // Get a random node the size of this subtree 41 | int index = random.nextInt(this.size); 42 | // Now we can check if this random index is to the left 43 | // or right 44 | if (index < leftSize) { 45 | return this.left.getRandomNode(); 46 | } else if (index == leftSize) { 47 | return this; 48 | } else { 49 | return this.right.getRandomNode(); 50 | } 51 | 52 | 53 | } 54 | 55 | // Insert 56 | public void insert(int val) { 57 | if (val < this.data) { 58 | // Go left 59 | if (this.left == null) { 60 | // set it to this.left 61 | TreeNode node = new TreeNode(val); 62 | this.right = node; 63 | } else { 64 | // recurse on the left side 65 | this.left.insert(val); 66 | } 67 | } else { 68 | // Go right 69 | if (this.right == null) { 70 | // set it to this.right 71 | TreeNode node = new TreeNode(val); 72 | this.right = node; 73 | } else { 74 | this.right.insert(val); 75 | } 76 | } 77 | this.size += 1; 78 | } 79 | // Return size and data 80 | public int size() { 81 | return this.size; 82 | } 83 | public int data() { 84 | return this.data; 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TreesAndGraphs/route_between_two_nodes.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | /** 3 | * PSA: I apologize if there are typos here; I did not run this to check, 4 | * but it looks intuitively fine, in the actual interview, you don't run code on the 5 | * whiteboard just make sure it makes sense. love :) 6 | */ 7 | // Find out whether there is a route between two nodes 8 | // Shortest way to do that is with bfs 9 | 10 | public class MyClass { 11 | public static void main(String args[]) { 12 | Graph graph = new Graph(); 13 | 14 | for (int i = 0; i < 9; i++) { 15 | Node node = new Node(String.valueOf(i)); 16 | for (int j = 10; j < 20; j++) { 17 | Node child = new Node(String.valueOf(j)); 18 | node.addChild(child); 19 | } 20 | graph.addNode(node); 21 | } 22 | } 23 | public boolean bfs findNode(Graph graph, Node start, Node end) { 24 | // Add all the start children to a queue 25 | Queue queue = new ArrayDeque<>(); 26 | 27 | for (Node node : graph.getNodes()) { 28 | node.state = "unvisited"; 29 | } 30 | start.state = "visiting"; 31 | queue.add(start); 32 | while (!q.isEmpty()) { 33 | // Get the current node 34 | Node node = q.poll(); 35 | // visit this node, and add it's children to the q 36 | if (node != null) { 37 | for (Node child : node.children()) { 38 | if (child.state.equals("unvisited")) { 39 | // Visit child 40 | if (child == end) { 41 | return true; 42 | } else { 43 | // visit this child's children 44 | child.state = "visiting"; 45 | // Add it's nodes to the queue 46 | queue.offer(child); 47 | } 48 | } 49 | } 50 | } 51 | node.state = "visited"; 52 | } 53 | return false; 54 | } 55 | } 56 | 57 | public class Graph { 58 | public ArrayList nodes; 59 | public Graph() { 60 | this.nodes = new ArrayList(); 61 | } 62 | public void addNode(Node node) { 63 | this.nodes.add(node); 64 | } 65 | } 66 | public class Node { 67 | public String name; 68 | public ArrayList children; 69 | 70 | public Node(String name) { 71 | this.name = name; 72 | this.children = new ArrayList(); 73 | } 74 | public void addChild(Node node) { 75 | this.children.add(node); 76 | } 77 | } -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TreesAndGraphs/topological_sort.java: -------------------------------------------------------------------------------- 1 | public class MyClass { 2 | public static void main(String args[]) { 3 | // Create a Task Graph 4 | String[][] dependencies = 5 | new String[][] {{"a", "d"}, {"f", "b"}, {"b", "d"}, 6 | {"f", "a"}, {"d", "c"}}; 7 | 8 | // Then we can create the graph 9 | TaskGraph graph = new TaskGraph(); 10 | for (String[] dep : dependencies) { 11 | graph.addDependencies(dep[1], dep[0]); 12 | } 13 | // Now we can get the order 14 | List result = getTaskOrder(graph); 15 | System.out.println(Arrays.toString(result.toArray())); 16 | 17 | } 18 | 19 | public List getTaskOrder(TaskGraph graph) { 20 | // Get the list of tasks 21 | List tasks = new ArrayList(graph.tasks); 22 | // Then the result to return 23 | List result = new ArrayList(); 24 | for (Task task : tasks) { 25 | // Loop through each task and check that 26 | // there are no cycles and we've performed 27 | // All the dependencies 28 | boolean cycle = dfs(task, result); 29 | if (cycle) return new ArrayList(); 30 | 31 | } 32 | return result; 33 | } 34 | public boolean dfs(Task task, List result) { 35 | if (task.visiting) return true; 36 | // Return true is a cycle exists 37 | if (task.visited) return false; 38 | // We have performed this task 39 | task.visiting = true; 40 | // Go through all it's depenencies 41 | for (Task dep : task.deps) { 42 | boolean cycle = dfs(dep, result); 43 | // if contains cycle return false w/o adding 44 | // anything to the order 45 | if (cycle) return false; 46 | } 47 | // No deps and no cycle 48 | result.add(task.taskName); 49 | task.visiting = false; 50 | task.visited = true; 51 | return false; 52 | } 53 | 54 | } 55 | public class Task { 56 | String taskName; 57 | List deps; 58 | boolean visited; 59 | boolean visiting; 60 | public Task(String taskName) { 61 | this.taskName = taskName; 62 | deps = new ArrayList<>(); 63 | visited = false; 64 | visiting = false; 65 | } 66 | 67 | } 68 | public class TaskGraph { 69 | String taskName; 70 | List tasks; 71 | // First String is for graph name and the next 72 | // String list is for the dependencies 73 | Map map; 74 | public TaskGraph(List taskList) { 75 | tasks = new ArrayList(); 76 | map = new HashMap(); 77 | for (String task : taskList) { 78 | addTask(task); 79 | } 80 | } 81 | public void addTask(String name) { 82 | Task task = new Task(name); 83 | // Add it to the list 84 | tasks.add(task); 85 | // Add it to the map. 86 | map.put(name, task); 87 | } 88 | public void addDependencies(String a, String b) { 89 | // First of all we get the task 90 | // b is dependent on a 91 | Task a_ = getTask(a); 92 | Task b_ = getTask(b); 93 | // Add this dependency to the list 94 | b_.dep.add(a_); 95 | } 96 | public Task getTask(String task) { 97 | if (map.containsKey(task)) { 98 | return map.get(task); 99 | } else { 100 | // Create a new task? 101 | addTask(task); 102 | } 103 | } 104 | 105 | 106 | } -------------------------------------------------------------------------------- /Easy/03_04_2020_closest_value_bst.java: -------------------------------------------------------------------------------- 1 | // Time: O(log(n)) | Space: O(log(n)) {AVERAGE CASE} 2 | // Time: O(n) | Space: O(n) {WORST CASE} 3 | public int closestValueInBST (BST tree, int target, double closest) { 4 | if (tree == null) { 5 | return 0; 6 | } 7 | // Calculate the difference between the target and the current node's value 8 | if (Math.abs(target - closest) > Math.abs(target - tree.value)) { 9 | closest = tree.value; 10 | } 11 | // You could also do the previous statement like this 12 | // closest = Math.abs(target - closest) > Math.abs(target - tree.value) ? tree.value : closest; 13 | if (target < tree.value && tree.left != null) { 14 | // Then we search on the left sub tree 15 | return closestValueInBST (tree.left, target, closest) 16 | } 17 | if (target > tree.value && tree.right != null) { 18 | // Then we search on the right sub tree 19 | return closestValueInBST (tree.right, target, closest) 20 | } 21 | return int(closest); 22 | } 23 | 24 | // public static void main (String args[] ) { 25 | // int closestValue = closestValueInBST(tree, 60, Double.MAX_VALUE); 26 | // } 27 | -------------------------------------------------------------------------------- /Easy/03_06_2020_single_number.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | class Solution { 3 | public int singleNumber(int[] nums) { 4 | Set set = new HashSet<>(); 5 | 6 | for (int num : nums) { 7 | if (set.contains(num)) { 8 | // This is the second occurence, remove num from hash set 9 | set.remove(num); 10 | } else { 11 | // This is the first occurence, add it to a hashset 12 | set.add(num); 13 | } 14 | } 15 | // Go through all the values in set and return the first value 16 | for (int num : set) { 17 | return num; 18 | } 19 | return 0; 20 | } 21 | } -------------------------------------------------------------------------------- /Easy/03_09_2020_branch_sums_recursion.java: -------------------------------------------------------------------------------- 1 | // Time: O(n) | Space: O(n) 2 | public List branchSums (BinaryTree root) { 3 | List sumsList = new ArrayList<>(); 4 | return branchSums(root, 0, sumsList); 5 | } 6 | public List branchSums (BinaryTree root, int sum, List sumsList) { 7 | if (root == null) { 8 | return sumsList; 9 | } 10 | // sum = sum + root.value 11 | sum += root.value; 12 | if (root.left == null && root.right == null) { 13 | // Then we've hit a leaf node 14 | sumsList.add(sum); 15 | } 16 | if (root.left != null) { 17 | branchSums(root.left, sum, sumsList); 18 | } 19 | if (root.right != null) { 20 | branchSums (root.right, sum, sumsList); 21 | } 22 | // When everything's done, return sumsList 23 | return sumsList; 24 | 25 | } -------------------------------------------------------------------------------- /Easy/03_26_2020_valid_parentheses.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Prompt: Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 3 | An input string is valid if: 4 | 1. Open brackets must be closed by the same type of brackets. 5 | 2. Open brackets must be closed in the correct order. 6 | */ 7 | 8 | class Solution { 9 | public boolean isValid(String s) { 10 | 11 | Stack stack = new Stack<>(); 12 | String openingBraces = "({["; 13 | String closingBraces = "]})"; 14 | Map combinations = new HashMap<>(); 15 | combinations.put(")", "("); 16 | combinations.put("}", "{"); 17 | combinations.put("]", "["); 18 | // Iterate through the string 19 | for (int i = 0; i < s.length(); i++) { 20 | 21 | String currentChar = String.valueOf(s.charAt(i)); 22 | if(openingBraces.contains(currentChar)){ 23 | // Then we know its an opening brace 24 | stack.push(currentChar); 25 | } 26 | else if (closingBraces.contains(currentChar)){ 27 | // Then we know its a closing brace 28 | if (stack.isEmpty()){ 29 | return false; 30 | } 31 | if (stack.peek().equals(combinations.get(currentChar))){ 32 | // Do something 33 | stack.pop(); 34 | } 35 | else { 36 | return false; 37 | } 38 | } 39 | } 40 | return stack.isEmpty() ? true : false; 41 | } 42 | } -------------------------------------------------------------------------------- /Easy/04_10_2020_product_and_sum.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int subtractProductAndSum(int n) { 3 | int product = 1; 4 | int sum = 0; 5 | while (n >= 1) { 6 | int lastDigit = n % 10; 7 | product = product * lastDigit; 8 | sum += lastDigit; 9 | n = n / 10; 10 | } 11 | return product - sum; 12 | } 13 | } -------------------------------------------------------------------------------- /Easy/04_15_2020_binary_search.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int search(int[] nums, int target) { 3 | int left = 0; 4 | int right = nums.length - 1; 5 | 6 | while (left <= right) { 7 | int center = (left + right) / 2; 8 | if (nums[center] == target) { 9 | // Amazing! 10 | return center; 11 | } else if (target < nums[center]) { 12 | // Look on the left side 13 | right = center - 1; 14 | } else if (target > nums[center]) { 15 | // Look on the right side 16 | left = center + 1; 17 | } 18 | } 19 | return -1; 20 | } 21 | } -------------------------------------------------------------------------------- /Easy/08_02_2020_bubble_sort.java: -------------------------------------------------------------------------------- 1 | /* 2 | Time: 3 | Best = O(n), Average = O(n^2), Worst = O(n^2) 4 | Space: O(1) 5 | */ 6 | class Solution { 7 | public int[] sortArray(int[] nums) { 8 | // Assume the array is not sorted 9 | boolean isSorted = false; 10 | while (!isSorted) { 11 | isSorted = true; 12 | for (int i = 0; i < nums.length - 1; i++) { 13 | // If current number is greater than the next 14 | if (nums[i] > nums[i + 1]) { 15 | // Swap them 16 | swap(nums, i, i + 1); 17 | // If we made a swap, then let's go through one more iteration 18 | isSorted = false; 19 | } 20 | } 21 | } 22 | return nums; 23 | } 24 | public void swap(int[] array, int i, int j) { 25 | int temp = array[i]; 26 | array[i] = array[j]; 27 | array[j] = temp; 28 | } 29 | } -------------------------------------------------------------------------------- /Easy/08_05_2020_insertion_sort.java: -------------------------------------------------------------------------------- 1 | /* 2 | Time: 3 | Best = O(n), Average = O(n^2), Worst = O(n^2) 4 | Space: O(1) 5 | */ 6 | class Solution { 7 | public int[] sortArray(int[] nums) { 8 | // The very first number by itself is sorted 9 | for (int i = 0; i < nums.length; i++) { 10 | int j = i; 11 | while (j > 0) { 12 | // Insert nums j into its rightful position in the sorted array 13 | if (nums[j] < nums[j - 1]) { 14 | // Swap them 15 | swap(nums, j, j - 1); 16 | } 17 | j--; 18 | } 19 | 20 | } 21 | 22 | return nums; 23 | } 24 | public void swap(int[] array, int i, int j) { 25 | int temp = array[i]; 26 | array[i] = array[j]; 27 | array[j] = temp; 28 | } 29 | } -------------------------------------------------------------------------------- /Easy/08_09_2020_selection_sort.java: -------------------------------------------------------------------------------- 1 | /* 2 | Time: 3 | Best = O(n^2), Average = O(n^2), Worst = O(n^2) 4 | Space: O(1) 5 | */ 6 | class Solution { 7 | public int[] sortArray(int[] nums) { 8 | // Method 1 9 | // The very first number should be the first smallest element 10 | // for (int i = 0; i < nums.length - 1; i++) { 11 | // int smallest = i; 12 | // for (int j = i + 1; j < nums.length; j++) { 13 | // // if this number is smaller than curr smallest update smallest 14 | // if (nums[j] < nums[smallest]) { 15 | // smallest = j; 16 | // } 17 | // } 18 | // // Swap them 19 | // swap(nums, i, smallest); 20 | // } 21 | 22 | // Method 2 23 | int index = 0; 24 | while (index < nums.length - 1) { 25 | int smallest = index; 26 | for (int j = index; j < nums.length; j++) { 27 | if (nums[j] < nums[smallest]) { 28 | smallest = j; 29 | } 30 | } 31 | swap(nums, index, smallest); 32 | index++; 33 | } 34 | 35 | return nums; 36 | } 37 | public void swap(int[] array, int i, int j) { 38 | int temp = array[i]; 39 | array[i] = array[j]; 40 | array[j] = temp; 41 | } 42 | } -------------------------------------------------------------------------------- /Easy/08_21_2022_merge_two_sorted_lists.java: -------------------------------------------------------------------------------- 1 | /** 2 | LeetCode 21 3 | Time: O(n) 4 | Space: O(n) 5 | */ 6 | 7 | class Solution { 8 | public ListNode mergeTwoLists(ListNode list1, ListNode list2) { 9 | ListNode head1 = list1; 10 | ListNode head2 = list2; 11 | 12 | ListNode newList = new ListNode(0); 13 | ListNode newListHead = newList; 14 | 15 | while (head1 != null && head2 != null) { 16 | int num1 = head1.val; 17 | int num2 = head2.val; 18 | if (num1 < num2) { 19 | newList.next = head1; 20 | newList = newList.next; 21 | head1 = head1.next; 22 | } else { 23 | // num 1 >= num2 24 | newList.next = head2; 25 | newList = newList.next; 26 | head2 = head2.next; 27 | } 28 | } 29 | if (head1 != null) { 30 | newList.next = head1; 31 | } 32 | if (head2 != null) { 33 | newList.next = head2; 34 | } 35 | return newListHead.next; 36 | } 37 | } -------------------------------------------------------------------------------- /Easy/08_21_2022_search_insert_position.java: -------------------------------------------------------------------------------- 1 | /** 2 | LeetCode 35 3 | Time: O(n) 4 | Space: O(1) 5 | */ 6 | class Solution { 7 | public int searchInsert(int[] nums, int target) { 8 | if (nums.length == 1) { 9 | if (nums[0] == target) return 0; 10 | if (nums[0] < target) return 1; 11 | if (nums[0] > target) return 0; 12 | } 13 | 14 | for (int i = 0; i < nums.length - 1; i++) { 15 | int current = nums[i]; 16 | int next = nums[i + 1]; 17 | if (current == target) return i; 18 | if (target >= current && target <= next) { 19 | return (i + 1); 20 | } 21 | } 22 | // Did not find position in array. It could be first or last 23 | if (nums[0] >= target) { 24 | return 0; 25 | } 26 | return nums.length; 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /Easy/09_14_2020_intersection_of_two_linked_lists.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { 7 | * val = x; 8 | * next = null; 9 | * } 10 | * } 11 | */ 12 | /* 13 | Time: O(A + B) 14 | Spae: O(1) 15 | */ 16 | public class Solution { 17 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 18 | ListNode l1 = headA; 19 | ListNode l2 = headB; 20 | int len1 = 0; 21 | int len2 = 0; 22 | while(l1 != null) { 23 | l1 = l1.next; 24 | len1++; 25 | } 26 | while(l2 != null) { 27 | l2 = l2.next; 28 | len2++; 29 | } 30 | // Now we have the lenggth the two lists 31 | if (len1 > len2) { 32 | // List 1 is longer 33 | int diff = len1 - len2; 34 | for (int i = 0; i < diff; i++) { 35 | headA = headA.next; 36 | } 37 | 38 | } else { 39 | int diff = len2 - len1; 40 | for (int i = 0; i < diff; i++) { 41 | headB = headB.next; 42 | } 43 | } 44 | while (headA != headB) { 45 | headA = headA.next; 46 | headB = headB.next; 47 | } 48 | return headA; 49 | } 50 | } 51 | 52 | // Hash Set Solution 53 | // Time: O(A + B) 54 | // Spae: O(A) 55 | 56 | // import java.util.*; 57 | // public class Solution { 58 | // public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 59 | // Set visited = new HashSet<>(); 60 | // while (headA != null) { 61 | // visited.add(headA); 62 | // headA = headA.next; 63 | // } 64 | // // Traverse head B to see if we have seen that node 65 | // while (headB != null) { 66 | // if (visited.contains(headB)) { 67 | // return headB; 68 | // } 69 | // headB = headB.next; 70 | // } 71 | // return null; 72 | // } 73 | // } -------------------------------------------------------------------------------- /Easy/09_15_2020_diameter_of_binary_tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode() {} 8 | * TreeNode(int val) { this.val = val; } 9 | * TreeNode(int val, TreeNode left, TreeNode right) { 10 | * this.val = val; 11 | * this.left = left; 12 | * this.right = right; 13 | * } 14 | * } 15 | */ 16 | /** 17 | * Time: O(n) 18 | * Space: O(d) where d is the depth of the deepest branch 19 | */ 20 | class Solution { 21 | int ans; 22 | public int diameterOfBinaryTree(TreeNode root) { 23 | ans = 1; 24 | getDiameter(root); 25 | return ans - 1; 26 | 27 | } 28 | public int getDiameter(TreeNode root) { 29 | if (root == null) { 30 | return 0; 31 | } 32 | // Get the length of the left child path 33 | int left = getDiameter(root.left); 34 | // Get the length of the right child path 35 | int right = getDiameter(root.right); 36 | // Update the answer 37 | ans = Math.max(ans, left + right + 1); 38 | // return the max of (left and right path) + 1 39 | return Math.max(left, right) + 1; 40 | } 41 | } -------------------------------------------------------------------------------- /Easy/09_16_2020__kadanes_algorithm_maximum_subarray.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) 3 | * Space:O(1) 4 | */ 5 | class Solution { 6 | public int maxSubArray(int[] nums) { 7 | int maxHere = nums[0]; 8 | int runningMax = nums[0]; 9 | 10 | for (int i = 1; i < nums.length; i++) { 11 | maxHere = Math.max(nums[i], nums[i] + maxHere); 12 | runningMax = Math.max(runningMax, maxHere); 13 | } 14 | return runningMax; 15 | } 16 | } -------------------------------------------------------------------------------- /Easy/09_16_2020_maximum_subarray.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) 3 | * Space:O(1) 4 | */ 5 | class Solution { 6 | public int maxSubArray(int[] nums) { 7 | int maxHere = nums[0]; 8 | int runningMax = nums[0]; 9 | 10 | for (int i = 1; i < nums.length; i++) { 11 | maxHere = Math.max(nums[i], nums[i] + maxHere); 12 | runningMax = Math.max(runningMax, maxHere); 13 | } 14 | return runningMax; 15 | } 16 | } -------------------------------------------------------------------------------- /Easy/09_17_2020_maximum_depth_of_binary_tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) 3 | * Space: O(d) where d is the depth of the deepest path 4 | */ 5 | class Solution { 6 | public int maxDepth(TreeNode root) { 7 | if (root == null) return 0; 8 | // Find the length of the left and right children paths 9 | int left = maxDepth(root.left); 10 | int right = maxDepth(root.right); 11 | // return the max of left and right length plus 1 12 | return Math.max(left, right) + 1; 13 | } 14 | } -------------------------------------------------------------------------------- /Easy/09_21_2020_symmetric_tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) 3 | * Space: O(n) 4 | */ 5 | class Solution { 6 | public boolean isSymmetric(TreeNode root) { 7 | if (root == null) { 8 | return true; 9 | } 10 | return isSymmetric(root.left, root.right); 11 | } 12 | public boolean isSymmetric(TreeNode left, TreeNode right) { 13 | if (left == null || right == null) { 14 | return left == right; 15 | } 16 | if (left.val != right.val) { 17 | return false; 18 | } 19 | return isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left); 20 | } 21 | } -------------------------------------------------------------------------------- /Easy/09_26_2020_atm_queue_google_kickstart.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.*; 3 | import java.io.*; 4 | public class Solution { 5 | public static void main(String args[]) { 6 | 7 | // int[] order = new int[] {2, 7, 4}; 8 | // int max = 3; 9 | // List findOrder = orderCalculator(order, max); 10 | // for (int num: findOrder) { 11 | // System.out.println(num); 12 | // } 13 | Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in))); 14 | int t = in.nextInt(); // Scanner has functions to read ints, longs, strings, chars, etc. 15 | // int t = 1; 16 | for (int i = 1; i <= t; ++i) { 17 | // Reading the test cases 18 | int n = in.nextInt(); // Number of people standing in the queue 19 | int m = in.nextInt(); // Max amount 20 | int[] order = new int[n]; 21 | for (int j = 0; j < n; j++) { 22 | // add next int to array 23 | order[j] = in.nextInt(); 24 | // System.out.println("Order at " + j + " " + order[j]); 25 | } 26 | List result = orderCalculator(order, m); 27 | StringBuilder answer = new StringBuilder(); 28 | answer.append("Case #" + i + ": "); 29 | 30 | result.forEach(nb -> answer.append(nb + " ")); 31 | System.out.println(answer.toString()); 32 | } 33 | } 34 | public static List orderCalculator(int[] order, int x) { 35 | // Create an actual queue; 36 | Queue queue = new ArrayDeque<>(); 37 | List result = new ArrayList<>(); 38 | for (int i = 1; i <= order.length; i++) { 39 | // Add i to the queue 40 | queue.offer(i); 41 | } 42 | // Now that we have built the queue, we can process getting peeps out 43 | while (!queue.isEmpty()) { 44 | // While we still have people in the queue 45 | int index = queue.poll(); 46 | int amount = order[index - 1]; 47 | // Let us process this person 48 | 49 | if (amount <= x) { 50 | // this person is cleared to go 51 | result.add(index); 52 | 53 | } else { 54 | // The amount is greater 55 | order[index - 1] = amount - x; 56 | // Add this person back to the queue 57 | queue.offer(index); 58 | } 59 | } 60 | return result; 61 | 62 | } 63 | } 64 | 65 | 66 | // import java.util.*; 67 | // import java.io.*; 68 | // public class Solution { 69 | // public static void main(String[] args) { 70 | 71 | // } 72 | // } 73 | 74 | -------------------------------------------------------------------------------- /Easy/09_29_2022_climbing_stairs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Time: O(n) 3 | * Space: O(n) 4 | */ 5 | 6 | public int climbStairs(int n) { 7 | 8 | int ways[] = new int[n + 1]; 9 | ways[0] = 1; 10 | ways[1] = 1; 11 | 12 | for (int i = 2; i <= n; i++) { 13 | ways[i] = ways[i - 1] + ways[i - 2]; 14 | } 15 | 16 | return ways[n]; 17 | 18 | } -------------------------------------------------------------------------------- /Easy/10_06_2020_convert_sorted_array_to_bst.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(log (n)) 3 | * Space: O(n) 4 | */ 5 | class Solution { 6 | public TreeNode sortedArrayToBST(int[] nums) { 7 | if (nums.length == 0 || nums == null) return null; 8 | return convert(nums, 0, nums.length - 1); 9 | } 10 | public TreeNode convert(int[] array, int start, int end) { 11 | if (start > end) return null; 12 | // Calculate median index 13 | int mid = start + (end - start) / 2; 14 | // Set median val to root 15 | TreeNode root = new TreeNode(array[mid]); 16 | // Determine left and right children 17 | // S for 'start', m for 'mid' and e for 'end' 18 | // s m e 19 | // x - x - x - x - x - x - x 20 | // You can see that the left side ranges from start to mid 21 | // And right side ranges from mid to end 22 | root.left = convert(array, start, mid - 1); 23 | root.right = convert(array, mid + 1, end); 24 | return root; 25 | } 26 | 27 | 28 | } -------------------------------------------------------------------------------- /Easy/10_25_2020_path_sum.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) or O(2^d) -> where d is the depth of the binary tree 3 | * Space: O(d) -> where d is the depth of the binary tree 4 | */ 5 | class Solution { 6 | public boolean hasPathSum(TreeNode root, int sum) { 7 | if (root == null) { 8 | return false; 9 | } 10 | return hasPathSum(root, sum, 0); 11 | 12 | } 13 | public boolean hasPathSum(TreeNode root, int target, int running) { 14 | if (root == null) { 15 | return false; 16 | } 17 | // Add current value to running sum 18 | running += root.val; 19 | // Check if we are at a leaf node 20 | if (root.left == null && root.right == null) { 21 | // return whether this path adds up to target 22 | return running == target; 23 | } 24 | // Go to the left and right paths 25 | return hasPathSum(root.left, target, running) || 26 | hasPathSum(root.right, target, running); 27 | } 28 | } -------------------------------------------------------------------------------- /Easy/11_27_2020_majority_element_boyer_moore_voting_algorithm.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) 3 | * Space: O(1) 4 | */ 5 | class Solution { 6 | public int majorityElement(int[] nums) { 7 | int count = 0; 8 | Integer candidate = null; 9 | for (int num : nums) { 10 | if (count == 0) { 11 | candidate = num; 12 | } 13 | count += (num == candidate) ? 1 : - 1; 14 | } 15 | return candidate; 16 | } 17 | } -------------------------------------------------------------------------------- /Easy/11_29_2020_merge_sorted_array.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Time: O(n + m) 3 | * Space: O(1) 4 | */ 5 | class Solution { 6 | public void merge(int[] nums1, int m, int[] nums2, int n) { 7 | int i = m + n - 1; 8 | int p1 = m - 1; 9 | int p2 = n - 1; 10 | 11 | while (p1 >= 0 && p2 >= 0) { 12 | if (nums1[p1] > nums2[p2]) { 13 | // Set nums1[i] to the bigger number and decrement the pointers 14 | nums1[i--] = nums1[p1--]; 15 | } else { 16 | // Set nums1[i] to the bigger number and decrement the pointers 17 | nums1[i--] = nums2[p2--]; 18 | } 19 | } 20 | // While there are left over numbers from nums1, insert them into the final merged array 21 | while (p1 >= 0) { 22 | nums1[i--] = nums1[p1--]; 23 | } 24 | // While there are left over numbers from nums2, insert them into the final merged array 25 | while (p2 >= 0) { 26 | nums1[i--] = nums2[p2--]; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Easy/12_03_2020_valid_perfect_square.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(log n) 3 | * Space: O(1) 4 | */ 5 | class Solution { 6 | public boolean isPerfectSquare(int num) { 7 | if (num < 2) return true; 8 | int left = 1; 9 | int right = num; 10 | while (right - left > 1) { 11 | long mid = left + (right - left) / 2; 12 | if (mid * mid == num) { 13 | return true; 14 | } else if (mid * mid < num) { 15 | left = (int) mid; 16 | } else { 17 | right = (int) mid; 18 | } 19 | } 20 | return false; 21 | } 22 | } -------------------------------------------------------------------------------- /Easy/2022_08_28_best_time_to_buy_and_sell_stock.java: -------------------------------------------------------------------------------- 1 | // Time: O(n) 2 | // Space: O(1) 3 | class Solution { 4 | public int maxProfit(int[] prices) { 5 | // We look for the minimum price we have seen so far 6 | int minPriceSeen = Integer.MAX_VALUE; 7 | int maxProfit = 0; 8 | for (int price : prices) { 9 | if (price < minPriceSeen) { 10 | // This price is smaller than the minimum we've seen 11 | // It's now the new minimum 12 | minPriceSeen = price; 13 | } else { 14 | // This price is greater than the minimum we've seen 15 | // we might make a prifit here 16 | maxProfit = Math.max(maxProfit, price - minPriceSeen); 17 | } 18 | } 19 | return maxProfit; 20 | } 21 | } -------------------------------------------------------------------------------- /Easy/2022_09_29_binary_tree_inorder_traversal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Time: O(n) or O(2^d) where n is the number of nodes and d is the depth of the binary tree 3 | * Space: O(n) n frames on the call stack and also n total nodes stored in the answer 4 | */ 5 | class Solution { 6 | public List answer = new ArrayList<>(); 7 | public List inorderTraversal(TreeNode root) { 8 | 9 | inorderTraversal(root.left); 10 | answer.add(root.val); 11 | inorderTraversal(root.right); 12 | 13 | return answer; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Hard/07_27_2020_trapping_rain_water.java: -------------------------------------------------------------------------------- 1 | // Time: O(n) 2 | // Space: O(n) 3 | import java.util.*; 4 | class Solution { 5 | public int trap(int[] height) { 6 | int[] dp = new int[height.length]; 7 | int leftMax = 0; 8 | // Populating left max 9 | for (int i = 0; i < height.length; i++) { 10 | dp[i] = leftMax; 11 | leftMax = Math.max(leftMax, height[i]); 12 | } 13 | // Populating the right max array 14 | int rightMax = 0; 15 | for (int i = height.length - 1; i >= 0; i--) { 16 | int minMaxVal = Math.min(dp[i], rightMax); 17 | dp[i] = height[i] > minMaxVal ? 0 : minMaxVal - height[i]; 18 | rightMax = Math.max(rightMax, height[i]); 19 | } 20 | return Arrays.stream(dp).sum(); 21 | } 22 | } -------------------------------------------------------------------------------- /Hard/08_11_2020_quick_sort.java: -------------------------------------------------------------------------------- 1 | /* 2 | Time: 3 | Best = O(n log(n)), Average = O(n log(n)), Worst = O(n^2) 4 | Space: O(1) 5 | */ 6 | class Solution { 7 | public int[] sortArray(int[] nums) { 8 | 9 | applyQuickSort(nums, 0, nums.length - 1); 10 | return nums; 11 | } 12 | public void applyQuickSort(int[] array, int start, int end) { 13 | if (start >= end) return; 14 | int pointer = start; 15 | int left = start + 1; 16 | int right = end; 17 | while (left <= right) { 18 | // Left and right pointers are not in place so we swap them 19 | if (array[left] > array[pointer] && array[right] < array[pointer]) { 20 | swap(array, left, right); 21 | } 22 | // Left and right pointers are both in place 23 | if (array[left] <= array[pointer]) left++; 24 | if (array[right] >= array[pointer]) right--; 25 | } 26 | swap(array, right, pointer); 27 | // Determine which sub array is smaller and apply quick sort to the smaller one first 28 | boolean leftIsSmaller = (right - 1) - start < end - (right + 1); 29 | if (leftIsSmaller) { 30 | // Apply quick sort on the left sub array first 31 | applyQuickSort(array, start, right - 1); 32 | applyQuickSort(array, right + 1, end); 33 | } else { 34 | // Apply quick sort on the right sub array first 35 | applyQuickSort(array, right + 1, end); 36 | applyQuickSort(array, start, right - 1); 37 | } 38 | 39 | 40 | } 41 | 42 | public void swap(int[] array, int i, int j) { 43 | int temp = array[i]; 44 | array[i] = array[j]; 45 | array[j] = temp; 46 | } 47 | } -------------------------------------------------------------------------------- /Medium/02_01_2020_surrounded_regions.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n * m) 3 | * Space: O(1) 4 | */ 5 | class Solution { 6 | public void solve(char[][] board) { 7 | if (board.length == 0 || board == null) return; 8 | // Change all the O's connected on the edges of the board to a special character because 9 | // They can never be captured since they can never be completely surrounded. (they are on the edge) 10 | for (int row = 0; row < board.length; row++) { 11 | // Checking left edge 12 | if (board[row][0] == 'O') { 13 | change(board, row, 0); 14 | } 15 | // Checking right edge 16 | if(board[row][board[0].length - 1] == 'O') { 17 | change(board, row, board[0].length - 1); 18 | } 19 | } 20 | for (int col = 0; col < board[0].length; col++) { 21 | // Checking top edge 22 | if (board[0][col] == 'O') { 23 | change(board, 0, col); 24 | } 25 | // Checking bottom edge 26 | if(board[board.length - 1][col] == 'O') { 27 | change(board, board.length - 1, col); 28 | } 29 | } 30 | // Finally we capture the remaining O's 31 | for (int row = 0; row < board.length; row++) { 32 | for (int col = 0; col < board[row].length; col++) { 33 | if (board[row][col] == 'O') { 34 | board[row][col] = 'X'; 35 | } 36 | if (board[row][col] == '_') { 37 | board[row][col] = 'O'; 38 | } 39 | } 40 | } 41 | } 42 | /** 43 | * DFS function to recursively check the connected neighboring cells and change them to a special character 44 | * if they are O's 45 | */ 46 | public void change(char[][] board, int row, int col) { 47 | if (row < 0|| row >= board.length || col < 0 || col >= board[row].length 48 | || board[row][col] == 'X' || board[row][col] == '_') { 49 | return; 50 | } 51 | board[row][col] = '_'; 52 | // Change all the connected O's to _'s 53 | change(board, row, col + 1); 54 | change(board, row, col - 1); 55 | change(board, row - 1, col); 56 | change(board, row + 1, col); 57 | 58 | } 59 | } -------------------------------------------------------------------------------- /Medium/02_05_2021_valid_sudoku.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(1) -> There are 81 total cells to iterate over and in Big-O notation, we drop constants 3 | * Space: O(1) -> Our hash maps all have a finite number of elements they can store (we drop constants) 4 | */ 5 | class Solution { 6 | public boolean isValidSudoku(char[][] board) { 7 | Map [] rows = new HashMap[9]; 8 | Map [] columns = new HashMap[9]; 9 | Map [] boxes = new HashMap[9]; 10 | 11 | for (int i = 0; i < 9; i++) { 12 | // Initialize one hash map for each row and column and sub grid 13 | rows[i] = new HashMap(); 14 | columns[i] = new HashMap(); 15 | boxes[i] = new HashMap(); 16 | 17 | } 18 | for (int i = 0; i < board.length; i++) { 19 | for (int j = 0; j < board[i].length; j++) { 20 | char current = board[i][j]; 21 | if (current != '.') { 22 | int num = (int) current; 23 | int boxIndex = (i / 3) * 3 + j / 3; 24 | 25 | 26 | // Update how many times weve seen this num in this row and col 27 | rows[i].put(num, rows[i].getOrDefault(num, 0) + 1); 28 | columns[j].put(num, columns[j].getOrDefault(num, 0) + 1); 29 | boxes[boxIndex].put(num, boxes[boxIndex].getOrDefault(num, 0) + 1); 30 | 31 | // Checking whether this number is duplicated 32 | if (rows[i].get(num) > 1 || columns[j].get(num) > 1 || 33 | boxes[boxIndex].get(num) > 1) { 34 | return false; 35 | } 36 | 37 | // this code is theoretically faster 38 | // int subGridRowStart = (i / 3) * 3; 39 | // int subGridColStart = (j / 3) * 3; 40 | // for (int l = 0; l < 3; l++){ 41 | // for (int m = 0; m < 3; m++) { 42 | // if (i != subGridRowStart + l && j != subGridColStart + m && 43 | // board[subGridRowStart + l][subGridColStart + m] == board[i][j]) { 44 | // // We've seen this char 45 | // return false; 46 | // } 47 | // } 48 | // } 49 | 50 | } 51 | } 52 | } 53 | return true; 54 | } 55 | } 56 | 57 | // Visualizing an array of maps 58 | // [ 59 | // ( (x:y), (x:y), (x:y) ), // row[0] 60 | // ( (x:y), (x:y), (x:y) ), // row[1] 61 | // ( (x:y), (x:y), (x:y) ), // row[2] 62 | // ] -------------------------------------------------------------------------------- /Medium/02_07_2020_binary_tree_zigzag_level_order_traversal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode() {} 8 | * TreeNode(int val) { this.val = val; } 9 | * TreeNode(int val, TreeNode left, TreeNode right) { 10 | * this.val = val; 11 | * this.left = left; 12 | * this.right = right; 13 | * } 14 | * } 15 | */ 16 | /** 17 | * Time: O(n) 18 | * Space: O(n) 19 | */ 20 | class Solution { 21 | public List> zigzagLevelOrder(TreeNode root) { 22 | List> levels = new ArrayList<>(); 23 | 24 | if (root == null) { 25 | return levels; 26 | } 27 | ArrayDeque queue = new ArrayDeque<>(); 28 | queue.add(root); 29 | // Do a regular level order traversal 30 | 31 | while (!queue.isEmpty()) { 32 | int size = queue.size(); 33 | List thisLevel = new ArrayList<>(); 34 | 35 | for (int i = 0; i < size; i++) { 36 | TreeNode current = queue.remove(); 37 | thisLevel.add(current.val); 38 | if (current.left != null) { 39 | queue.add(current.left); 40 | } 41 | if (current.right != null) { 42 | queue.add(current.right); 43 | } 44 | 45 | } 46 | levels.add(thisLevel); 47 | } 48 | 49 | boolean leftToRight = true; 50 | for (int i = 0; i < levels.size(); i++) { 51 | List thisLevel = levels.get(i); 52 | if (leftToRight) { 53 | // This level is already ordered from left to right 54 | leftToRight = !leftToRight; 55 | } else { 56 | // reverse this order (right to left) to mimic the zigzag pattern 57 | Collections.reverse(thisLevel); 58 | leftToRight = !leftToRight; 59 | } 60 | } 61 | return levels; 62 | 63 | } 64 | } -------------------------------------------------------------------------------- /Medium/02_17_2020_maxim_subset_no_adjacent.java: -------------------------------------------------------------------------------- 1 | public int maxSubSetNoAdj(int[] array) { 2 | 3 | } -------------------------------------------------------------------------------- /Medium/03_03_2020_array_duplicates.java: -------------------------------------------------------------------------------- 1 | // Time: O(n) | Space: O(d) where d is te numbher of duplicates that we found. 2 | import java.util.*; 3 | class Solution { 4 | public List findDuplicates(int[] nums) { 5 | Arrays.sort(nums); 6 | ArrayList answer = new ArrayList<>(); 7 | int left = 0; 8 | while (left < nums.length - 1) { 9 | if (nums[left] == nums[left + 1]) { 10 | answer.add(nums[left]); 11 | left ++; 12 | } 13 | left ++; 14 | } 15 | return answer; 16 | } 17 | } -------------------------------------------------------------------------------- /Medium/03_04_2021_binary_search_tree_iterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode() {} 8 | * TreeNode(int val) { this.val = val; } 9 | * TreeNode(int val, TreeNode left, TreeNode right) { 10 | * this.val = val; 11 | * this.left = left; 12 | * this.right = right; 13 | * } 14 | * } 15 | */ 16 | class BSTIterator { 17 | // First solution flatten the bst 18 | // List list; 19 | // int index; 20 | Stack stack; 21 | 22 | // public void inOrderTraversal(TreeNode root) { 23 | // if (root == null) { 24 | // return; 25 | // } 26 | // // Check left node 27 | // inOrderTraversal(root.left); 28 | // // Process this node 29 | // list.add(root.val); 30 | // // Check right node 31 | // inOrderTraversal(root.right); 32 | // } 33 | 34 | public BSTIterator(TreeNode root) { 35 | this.stack = new Stack(); 36 | // index = -1; 37 | // // Do the inOrderTraversal 38 | // inOrderTraversal(root); 39 | // Add all the leftmost elements to a stack so the smallest will be on top 40 | addLeftmost(root); 41 | 42 | } 43 | public void addLeftmost(TreeNode node) { 44 | while (node != null) { 45 | stack.push(node); 46 | node = node.left; 47 | } 48 | } 49 | 50 | public int next() { 51 | // // Return the value at index + 1 52 | // if (hasNext()) { 53 | // index += 1; 54 | // return list.get(index); 55 | // } else { 56 | // return -1; 57 | // } 58 | TreeNode top = stack.pop(); 59 | if (top.right != null) { 60 | // We have a right branch, add the leftmost element in this right branch 61 | // To maintain the smallest at top property 62 | addLeftmost(top.right); 63 | } 64 | return top.val; 65 | } 66 | 67 | public boolean hasNext() { 68 | return stack.size() > 0; 69 | } 70 | } 71 | 72 | /** 73 | * Your BSTIterator object will be instantiated and called as such: 74 | * BSTIterator obj = new BSTIterator(root); 75 | * int param_1 = obj.next(); 76 | * boolean param_2 = obj.hasNext(); 77 | */ -------------------------------------------------------------------------------- /Medium/03_04_2021_binary_tree_right_side_view.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode() {} 8 | * TreeNode(int val) { this.val = val; } 9 | * TreeNode(int val, TreeNode left, TreeNode right) { 10 | * this.val = val; 11 | * this.left = left; 12 | * this.right = right; 13 | * } 14 | * } 15 | */ 16 | class Solution { 17 | public List rightSideView(TreeNode root) { 18 | List answer = new ArrayList<>(); 19 | if (root == null) return answer; 20 | // Do a level order traversal 21 | ArrayDeque queue = new ArrayDeque<>(); 22 | queue.add(root); 23 | while (!queue.isEmpty()) { 24 | // pop this element from the queue and add it's children 25 | List thisLevel = new ArrayList<>(); 26 | int size = queue.size(); 27 | for (int i = 0; i < size; i++) { 28 | // Remove elements from this Level 29 | TreeNode node = queue.poll(); 30 | // Add this to this level 31 | thisLevel.add(node.val); 32 | // Then add the children of this node to the queue 33 | if (node.left != null) { 34 | queue.offer(node.left); 35 | } 36 | if (node.right != null) { 37 | queue.offer(node.right); 38 | } 39 | 40 | } 41 | // Add this list to the main list. but we don't need to we 42 | // Just need to get the last element in this level 43 | answer.add(thisLevel.get(thisLevel.size() - 1)); 44 | } 45 | return answer; 46 | } 47 | } -------------------------------------------------------------------------------- /Medium/03_11_2020_move_arrray_elements.java: -------------------------------------------------------------------------------- 1 | // Time: O(n) | Space: O(1) 2 | public void moveElementsToEnd(int[] nums, int toMove) { 3 | // Initialize left and right pointers 4 | int left = 0; 5 | int right = nums.length - 1; 6 | for (int i = 0; i < nums.length; i++) { 7 | // Already in position, don't swap 8 | if(nums[right] == toMove) { 9 | right--; 10 | } 11 | if (nums[left] != toMove) { 12 | // It's not the element we want to swap 13 | left++; 14 | } 15 | if (nums[left] == toMove && nums[right] != toMove) { 16 | swap(left, right, nums); 17 | // Move pointers together 18 | left++; 19 | right--; 20 | } 21 | } 22 | } 23 | public void swap(int i, int j, int[] array) { 24 | int temp = array[i]; 25 | array[i] = array[j]; 26 | array[j] = temp; 27 | } -------------------------------------------------------------------------------- /Medium/03_29_2020_implement_a_set.java: -------------------------------------------------------------------------------- 1 | // Implement a data structure that supports insert, delete, get random element and search in 0(1) constant time 2 | // Time: 0(1) 3 | // Space: 0(n) -> Where n is the number of elements inserted into the data structure 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | class CustomSet { 9 | 10 | private List list; 11 | // Map values to their index 12 | private Map map; 13 | public CustomSet() { 14 | 15 | this.list = new ArrayList<>(); 16 | this.map = new HashMap<>(); 17 | 18 | } 19 | 20 | // Implement adding 21 | 22 | public void add(int ele) { 23 | if (map.containsKey(ele)) return; 24 | // If the element is not present 25 | int index = list.size(); 26 | this.list.add(ele); 27 | // add to map 28 | this.map.put(ele, index); 29 | } 30 | 31 | public void remove(int ele) { 32 | // Index of element 33 | Integer index = this.map.get(ele); 34 | if (index == null) { 35 | return; 36 | } 37 | // remove it 38 | this.map.remove(ele); 39 | 40 | // get the size of the array list 41 | int size = this.list.size(); 42 | Integer last = this.list.get(size - 1); 43 | Collections.swap(this.list, size - 1, index); 44 | 45 | // remove the last element 46 | this.list.remove(size - 1); 47 | this.map.put(last, index); 48 | } 49 | public int getRandom() { 50 | int rand = (int) Math.random() * this.list.size(); 51 | return this.list.get(rand); 52 | } 53 | // return the index of the lement if it is present 54 | public int search(int x) { 55 | if (this.map.containsKey(x)) { 56 | return map.get(x); 57 | } 58 | return -1; 59 | } 60 | } -------------------------------------------------------------------------------- /Medium/04_27_2020_invert_binary_tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * int val; 5 | * TreeNode left; 6 | * TreeNode right; 7 | * TreeNode(int x) { val = x; } 8 | * } 9 | */ 10 | class Solution { 11 | public TreeNode invertTree(TreeNode root) { 12 | if (root == null) { 13 | return root; 14 | } 15 | // swap left and right children 16 | swapNodes(root); 17 | if (root.left != null) invertTree(root.left); 18 | if (root.right != null) invertTree(root.right); 19 | return root; 20 | } 21 | public void swapNodes(TreeNode root) { 22 | TreeNode temp = root.left; 23 | root.left = root.right; 24 | root.right = temp; 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /Medium/05_07_2021_number_of_closed_islands.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) -> where n is the number of cells in the grid 3 | * Space: O(d) -> where d is the depth of the deepest path 4 | */ 5 | class Solution { 6 | public int closedIsland(int[][] grid) { 7 | int count = 0; 8 | for (int i = 0; i < grid.length; i++) { 9 | for (int j = 0; j < grid[i].length; j++) { 10 | if (grid[i][j] == 0) { 11 | // Run a dfs on this instance of 0 because it could be a 12 | // Potential island 13 | boolean closed = isClosed(grid, i, j); 14 | if (closed) count += 1; 15 | } 16 | } 17 | } 18 | return count; 19 | } 20 | public boolean isClosed(int[][] grid, int row, int col) { 21 | // Base case: If we're out of bounds, return false. 22 | if (row < 0 || row >= grid.length || col < 0 || 23 | col >= grid[row].length) { 24 | return false; 25 | } 26 | // Stop traversing this path and return true if we see 1 27 | if (grid[row][col] == 1) return true; 28 | 29 | // Change the value to 1, so we don't come here again 30 | grid[row][col] = 1; 31 | 32 | // Check this cell's 4 neighbors 33 | boolean bottom = isClosed(grid, row + 1, col); // bottom 34 | boolean right = isClosed(grid, row, col + 1); // right 35 | boolean left = isClosed(grid, row, col - 1); // left 36 | boolean top = isClosed(grid, row - 1, col); // top; 37 | 38 | // Check that all 4 neighbors (paths) return true 39 | return bottom && right && top && left; 40 | } 41 | } -------------------------------------------------------------------------------- /Medium/06_01_2020_remove_nth_node_from_end.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode() {} 7 | * ListNode(int val) { this.val = val; } 8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 9 | * } 10 | */ 11 | class Solution { 12 | public ListNode removeNthFromEnd(ListNode head, int n) { 13 | ListNode first = head; 14 | ListNode second = head; 15 | // Move second pointer n nodes ahead 16 | for (int i = 0; i < n; i++) { 17 | second = second.next; 18 | } 19 | // Edge case if the head of the list is the node to remove 20 | if (second == null) { 21 | return head.next; 22 | } 23 | // Move both pointers in tandem until the second pointer is pointing to the last element in the list 24 | while (second.next != null) { 25 | first = first.next; 26 | second = second.next; 27 | } 28 | // First.next will now be the node to overwrite 29 | first.next = first.next.next; 30 | return head; 31 | } 32 | } -------------------------------------------------------------------------------- /Medium/06_04_2020_longest_palindromic_substring.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | // Time = O(n^2) 3 | // Space = O(n) 4 | public String longestPalindrome(String s) { 5 | if (s.length() > 0) { 6 | // Loop through the str 7 | String currentLongest = String.valueOf(s.charAt(0)); 8 | for (int i = 1; i < s.length(); i++) { 9 | // For palindrome pivoted at i 10 | int[] odd = getPalindrome(s, i - 1, i + 1); 11 | // For palindrome pivoted between i - 1 and i 12 | int[] even = getPalindrome(s, i - 1, i); 13 | int[] longest = odd[1] - odd[0] > even[1] - even[0] ? odd : even; 14 | currentLongest = currentLongest.length() > longest[1] - longest[0] ? 15 | currentLongest : s.substring(longest[0], longest[1]); 16 | 17 | } 18 | return currentLongest; 19 | } 20 | return s; 21 | } 22 | public int[] getPalindrome(String s, int left, int right) { 23 | while (left >= 0 && right < s.length()) { 24 | if (s.charAt(left) == s.charAt(right)) { 25 | left--; 26 | right++; 27 | } else { 28 | break; 29 | } 30 | } 31 | return new int[] {left + 1, right}; 32 | } 33 | } -------------------------------------------------------------------------------- /Medium/06_13_2020_3_sum.java: -------------------------------------------------------------------------------- 1 | // Time: O(n ^2 ) 2 | // Space: O(n) 3 | import java.util.*; 4 | class Solution { 5 | public List> threeSum(int[] nums) { 6 | Arrays.sort(nums); 7 | List> triplets = new ArrayList<>(); 8 | for (int i = 0; i < nums.length - 2; i++) { 9 | if (i == 0 || ( i > 0 && nums[i] != nums[i - 1])) { 10 | int left = i + 1; 11 | int right = nums.length - 1; 12 | while (left < right) { 13 | int sum = nums[i] + nums[left] + nums[right]; 14 | if (sum > 0) { 15 | // look in the left side 16 | right--; 17 | } else if (sum < 0) { 18 | // Look on the right side 19 | left++; 20 | 21 | } else { 22 | triplets.add(Arrays.asList(nums[i], nums[left], nums[right])); 23 | while(left < right && nums[left] == nums[left + 1]) left++; 24 | while(left < right && nums[right] == nums[right - 1]) right--; 25 | left++; 26 | right--; 27 | } 28 | 29 | } 30 | } 31 | 32 | } 33 | return triplets; 34 | } 35 | } -------------------------------------------------------------------------------- /Medium/07_27_2020_group_anagrams.java: -------------------------------------------------------------------------------- 1 | // Time: O(n * s log s) where n is the number of strings and s 2 | // is the length of the longest string 3 | // Space: O(ns) 4 | class Solution { 5 | public List> groupAnagrams(String[] strs) { 6 | List> anagrams = new ArrayList<>(); 7 | Map> map = new HashMap<>(); 8 | for (String str : strs) { 9 | char[] sorted = str.toCharArray(); 10 | Arrays.sort(sorted); 11 | String sortedStr = new String(sorted); 12 | if (!map.containsKey(sortedStr)) { 13 | map.put(sortedStr, new ArrayList()); 14 | } 15 | // Add to the list of anagrams for this sorted key 16 | map.get(sortedStr).add(str); 17 | } 18 | anagrams.addAll(map.values()); 19 | return anagrams; 20 | } 21 | } -------------------------------------------------------------------------------- /Medium/07_31_2020_longest_common_subsequence.java: -------------------------------------------------------------------------------- 1 | // Time: O(AB) 2 | // Space: O(AB) 3 | class Solution { 4 | public int longestCommonSubsequence(String text1, String text2) { 5 | int[][] sequenceLengths = new int[text1.length() + 1][text2.length() + 1]; 6 | // Fill top row 7 | for (int i = 0; i < sequenceLengths[0].length; i++) { 8 | sequenceLengths[0][i] = 0; 9 | } 10 | // Fill top col 11 | for (int i = 0; i < sequenceLengths.length; i++) { 12 | sequenceLengths[i][0] = 0; 13 | } 14 | // Fill in the middle cells 15 | for (int i = 1; i < text1.length() + 1; i++) { 16 | for (int j = 1; j < text2.length() + 1; j++) { 17 | if (text1.charAt(i - 1) == text2.charAt(j - 1)) { 18 | sequenceLengths[i][j] = sequenceLengths[i - 1][j - 1] + 1; 19 | } else { 20 | // If immediate top is greater than imediate left, take immediate top 21 | // otherwise take immediate left 22 | sequenceLengths[i][j] = sequenceLengths[i - 1][j] > sequenceLengths[i][j - 1] ? 23 | sequenceLengths[i - 1][j] : sequenceLengths[i][j - 1]; 24 | } 25 | } 26 | } 27 | return sequenceLengths[text1.length()][text2.length()]; 28 | } 29 | } -------------------------------------------------------------------------------- /Medium/09_03_2020_power_set.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Prompt: Prompt: Given an integer array nums of unique elements, return all possible subsets (the power set). 3 | The solution set must not contain duplicate subsets. Return the solution in any order. 4 | */ 5 | 6 | class Solution { 7 | public List> subsets(int[] nums) { 8 | List> powerset = new ArrayList<>(); 9 | // Add and empty subset 10 | powerset.add(new ArrayList()); 11 | for (int num : nums) { 12 | int length = powerset.size(); 13 | for (int i = 0; i < length; i++) { 14 | // Copy the current subset 15 | List current = new ArrayList<>(powerset.get(i)); 16 | // Add current num to the current subset 17 | current.add(num); 18 | // Add new subset to the powerset 19 | powerset.add(current); 20 | } 21 | } 22 | return powerset; 23 | } 24 | } 25 | 26 | 27 | // Recursive Solution 28 | // class Solution { 29 | // public List> subsets(int[] nums) { 30 | // List> subsets = new ArrayList<>(); 31 | // generateSubsets(subsets, new ArrayList(), nums, 0); 32 | // return subsets; 33 | 34 | 35 | // } 36 | // public void generateSubsets(List> result, 37 | // List subset, int[] nums, int index) { 38 | // result.add(new ArrayList<>(subset)); 39 | // // Then we generate the remaining subsets and increment i for next iteration 40 | // for (int i = index; i < nums.length; i++) { 41 | // subset.add(nums[i]); 42 | // generateSubsets(result, subset, nums, i + 1); 43 | // subset.remove(subset.size() - 1); 44 | // } 45 | // } 46 | // } 47 | /* 48 | [] 49 | 50 | Iter val subsize curr subset 51 | 1 1 1 [] ->[1] [ [], [1] ] 52 | 2 2 2 [2], [1, 2] [[], [1], [2], [1, 2]] 53 | 3 3 4 [3], [1, 3], [2, 3] [1, 2, 3]; 54 | 55 | 56 | */ 57 | -------------------------------------------------------------------------------- /Medium/09_18_2020_two_city_scheduling.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time: O(n) 3 | * Space: O(1) 4 | */ 5 | class Solution { 6 | public int twoCitySchedCost(int[][] costs) { 7 | int sum = 0; 8 | int n = costs.length / 2; 9 | int countA = 0; 10 | int countB = 0; 11 | 12 | int index = 0; 13 | Arrays.sort(costs, (a, b) -> Math.abs(b[0] - b[1]) - Math.abs(a[0] - a[1])); 14 | while (countA != n || countB != n) { 15 | // We still have people to send 16 | int costA = costs[index][0]; 17 | int costB = costs[index][1]; 18 | if (countA == n) { 19 | countB++; 20 | sum += costB; 21 | } else if (countB == n) { 22 | countA++; 23 | sum += costA; 24 | } else if (costA < costB) { 25 | countA++; 26 | sum += costA; 27 | } else if (costB < costA) { 28 | countB++; 29 | sum += costB; 30 | } 31 | index++; 32 | } 33 | return sum; 34 | } 35 | } -------------------------------------------------------------------------------- /Medium/11_07_2021_odd_even_linked_list.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Time Complexity: O(n) 3 | * Space Complexity: O(1) 4 | * 5 | * Description: Given the head of a singly linked list, group all the nodes with odd indices together followed by the 6 | * nodes with even indices, and return the reordered list. The first node is considered odd, and the 7 | * second node is even, and so on. Note that the relative order inside both the even and odd groups 8 | * should remain as it was in the input. You must solve the problem in O(1) extra space complexity 9 | * and O(n) time complexity. 10 | */ 11 | 12 | class Solution { 13 | public ListNode oddEvenList(ListNode head) { 14 | if (head == null) return null; 15 | ListNode odd = head; 16 | ListNode even = head.next; 17 | ListNode evenHead = even; 18 | while (odd.next != null && even.next != null) { 19 | // Do stuff. 20 | odd.next = even.next; 21 | odd = odd.next; 22 | 23 | // Do the same thing fo reven 24 | even.next = odd.next; 25 | even = even.next; 26 | } 27 | odd.next = evenHead; 28 | return head; 29 | } 30 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Your Ultimate FREE Coding Interview Prep 2 | 3 | Read about me here: [mvandi.com](https://mvandi.com) 4 | 5 | Drop a shout out or Follow on [Twitter](https://twitter.com/michael_vandi)? No? 6 | 7 | ## See Full Video Whiteboard and Live Coding explanations on my [YouTube channel](https://www.youtube.com/channel/UCZOiUkaF2fy8Mn0gZiKiDyQ/videos) 8 | 9 | Please consider subscribing. 10 | 11 | ![YouTube Channel Homepage](https://drive.google.com/uc?export=view&id=1gGa6eKCMgiaXNpm4nRy78ei-he1yyjmE) 12 | 13 | ## Difficulty Levels 14 | 15 | 1. Easy [(go to folder)](Easy/) 16 | 2. Medium [(go to folder)](Medium/) 17 | 3. Hard [(go to folder)](Medium/) 18 | 19 | ## Enjoy Questions and Solutions from 20 | 21 | 1. LeetCode 22 | 2. Cracking The Coding Interview [go to folder](CrackingTheCodingInterview/) 23 | 24 | ## Topics Include 25 | 26 | - Arrays and Strings 27 | - Linked Lists and Dynamic Arrays 28 | - Graphs (BFS, DFS) and Trees 29 | - Recursion 30 | - Dynamic Programming 31 | - Stacks and Queues 32 | - Heaps 33 | - Searching Algorithms 34 | - Sorting Algorithms 35 | - Greedy Algorithms 36 | - Famous Algorithms 37 | - String Manipulation 38 | - etc. 39 | 40 | ## Data Structures Covered 41 | 42 | - Array 43 | - ArrayList (Dynamic Array) 44 | - Hash Table 45 | - Linked List 46 | - Stack 47 | - Queues, Priority Queues 48 | - Binary Trees, Binary Search Trees 49 | - Graphs 50 | - Heaps (Min Heaps and Max Heaps) 51 | - Tries 52 | 53 | ## Link to solutions from Cracking The Coding Interview 54 | 55 | - [Arrays and Strings](CrackingTheCodingInterview/ArraysAndStrings/) 56 | - [Linked List Solutions](CrackingTheCodingInterview/LinkedListSolutions/) 57 | - [Stacks and Queues Solutions](CrackingTheCodingInterview/StacksAndQueues/) 58 | - [Trees and Graphs Solutions](CrackingTheCodingInterview/TreesAndGraps/) 59 | --------------------------------------------------------------------------------