├── .gitignore ├── java ├── AllBSTOrders.java ├── ArrayOfArrays.java ├── BinarySearch.java ├── Combinations.java ├── CombinationsOfLength.java ├── ConsultantSchedule.java ├── CountEven.java ├── DFSCombinations.java ├── DFSEditDistance.java ├── DFSGraph.java ├── DFSKnapsack.java ├── DFSTree.java ├── Decode.java ├── EditDistance.java ├── EggDrop.java ├── Fibonacci.java ├── FilterBuiltinList.java ├── FilterList.java ├── FlattenArrays.java ├── GCD.java ├── GreatestProductPath.java ├── InsertAtBottom.java ├── InterleaveStrings.java ├── IsPalindrome.java ├── Iteration.java ├── IterativeDFS.java ├── Knapsack.java ├── LongestConsecutivePath.java ├── LongestIncreasingSubsequence.java ├── MakingChange.java ├── MinMax.java ├── MinimumCompression.java ├── NDigitNumbers.java ├── NQueens.java ├── Parentheses.java ├── Permutations.java ├── PermutationsOfLength.java ├── PermutationsWithDuplicates.java ├── PrintReversedLinkedList.java ├── RotatedArray.java ├── SeatingArrangement.java ├── SortedPermutations.java ├── SquareSubmatrix.java ├── StairStep.java ├── Sublists.java ├── Substrings.java ├── TargetSum.java ├── TowersOfHanoi.java ├── TreeDiameter.java ├── TreeNextNode.java ├── TreeToLinkedList.java ├── UniqueBSTs.java └── WordBreak.java └── python3 ├── AllBSTOrders.py ├── ArrayOfArrays.py ├── Combinations.py ├── CombinationsOfLength.py ├── ConsultantSchedule.py ├── DFSGraph.py ├── DFSTree.py ├── Decode.py ├── GreatestProductPath.py ├── InsertAtBottom.py ├── IsPalindrome.py ├── Iteration.py ├── LongestIncreasingSubsequence.py ├── LowestCommonAncestor.py ├── StairStep.py └── TowerOfHanoi.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.class 3 | *~ 4 | -------------------------------------------------------------------------------- /java/AllBSTOrders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: All BST Orders 3 | * Author: Sam Gavis-Hughson 4 | * Date: 10/1/2018 5 | * 6 | * A binary search tree is constructed by inserting nodes into a tree in a set 7 | * order. Depending on the order that nodes are inserted, the resulting tree 8 | * may be different. Given a BST, write a function to determine all of the ways 9 | * you can insert nodes into the BST to get that exact tree 10 | * 11 | * eg. 12 | * Input: 13 | * 2 14 | * / \ 15 | * 1 3 16 | * \ 17 | * 4 18 | * 19 | * Output: 20 | * 21 | * 22 | * Given an array of integers, write a function to compute the total number of 23 | * combinations of integers. 24 | * 25 | * eg. 26 | * combos({1, 2, 3, 4, 5}) = 32 27 | * 28 | * Execution: javac ArrayCombinations.java && java ArrayCombinations 29 | */ 30 | 31 | import java.util.ArrayList; 32 | import java.util.Arrays; 33 | import java.util.HashSet; 34 | import java.util.List; 35 | import java.util.Set; 36 | 37 | public class AllBSTOrders { 38 | public static class Node { 39 | int val; 40 | Node left; 41 | Node right; 42 | } 43 | 44 | public static List> allBSTOrdersDC(Node root) { 45 | if (root == null) { 46 | List> toReturn = new ArrayList>(); 47 | toReturn.add(new ArrayList()); 48 | return toReturn; 49 | } 50 | 51 | List> left = allBSTOrdersDC(root.left); 52 | List> right = allBSTOrdersDC(root.right); 53 | 54 | List> merged = mergeAll(left, right); 55 | 56 | for (List l : merged) { 57 | l.add(0, root.val); 58 | } 59 | 60 | return merged; 61 | } 62 | 63 | private static List> mergeAll(List> first, 64 | List> second) { 65 | List> result = new ArrayList>(); 66 | for (List f : first) { 67 | for (List s : second) { 68 | merge(f, s, 0, 0, new ArrayList(), result); 69 | } 70 | } 71 | return result; 72 | } 73 | 74 | private static void merge(List first, List second, 75 | int i, int j, List path, 76 | List> result) { 77 | if (i == first.size() && j == second.size()) { 78 | result.add(new ArrayList(path)); 79 | return; 80 | } 81 | 82 | if (i != first.size()) { 83 | path.add(first.get(i)); 84 | merge(first, second, i+1, j, path, result); 85 | path.remove(path.size() - 1); 86 | } 87 | 88 | if (j != second.size()) { 89 | path.add(second.get(j)); 90 | merge(first, second, i, j+1, path, result); 91 | path.remove(path.size() - 1); 92 | } 93 | } 94 | 95 | public static List> allBSTOrdersOrdering(Node root) { 96 | List> results = new ArrayList>(); 97 | allBSTOrdersOrdering(new HashSet(Arrays.asList(root)), 98 | new ArrayList(), results); 99 | return results; 100 | } 101 | 102 | private static void allBSTOrdersOrdering(Set available, List path, 103 | List> results) { 104 | if (available.isEmpty()) { 105 | results.add(new ArrayList(path)); 106 | return; 107 | } 108 | 109 | for (Node n : available.toArray(new Node[]{})) { 110 | available.remove(n); 111 | if (n.left != null) available.add(n.left); 112 | if (n.right != null) available.add(n.right); 113 | path.add(n.val); 114 | 115 | allBSTOrdersOrdering(available, path, results); 116 | 117 | path.remove(path.size() - 1); 118 | if (n.left != null) available.remove(n.left); 119 | if (n.right != null) available.remove(n.right); 120 | available.add(n); 121 | } 122 | } 123 | 124 | public static void main(String[] args) { 125 | Node root = new Node(); 126 | root.val = 2; 127 | root.left = new Node(); 128 | root.left.val = 1; 129 | root.right = new Node(); 130 | root.right.val = 3; 131 | root.right.right = new Node(); 132 | root.right.right.val = 4; 133 | System.out.println(allBSTOrdersDC(root)); 134 | System.out.println(allBSTOrdersOrdering(root)); 135 | } 136 | } -------------------------------------------------------------------------------- /java/ArrayOfArrays.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class ArrayOfArrays { 5 | public static List> arrayOfArrays(int[][] arr) { 6 | List> results = new LinkedList>(); 7 | arrayOfArrays(arr, 0, new LinkedList(), results); 8 | return results; 9 | } 10 | 11 | private static void arrayOfArrays(int[][] arr, int i, List path, 12 | List> results) { 13 | if (i == arr.length) { 14 | results.add(new LinkedList(path)); 15 | return; 16 | } 17 | 18 | for (int j : arr[i]) { 19 | path.add(j); 20 | arrayOfArrays(arr, i+1, path, results); 21 | path.remove(path.size() - 1); 22 | } 23 | } 24 | 25 | public static void main(String[] args) { 26 | System.out.println(arrayOfArrays(new int[][]{new int[]{1,2}, new int[]{3}, new int[]{4,5}})); 27 | } 28 | } -------------------------------------------------------------------------------- /java/BinarySearch.java: -------------------------------------------------------------------------------- 1 | public class BinarySearch { 2 | public static boolean contains(int[] arr, int x) { 3 | return contains(arr, x, 0, arr.length - 1); 4 | } 5 | 6 | private static boolean contains(int[] arr, int x, int min, int max) { 7 | if (min == max) return arr[min] == x; 8 | 9 | int mid = (min + max) / 2; 10 | 11 | if (arr[mid] > x) return contains(arr, x, min, mid-1); 12 | if (arr[mid] < x) return contains(arr, x, mid+1, max); 13 | return true; 14 | } 15 | 16 | public static void main(String[] args) { 17 | System.out.println(contains(new int[]{1,2,3,4,5,6}, 1)); 18 | System.out.println(contains(new int[]{1,2,3,4,5,6}, 7)); 19 | } 20 | } -------------------------------------------------------------------------------- /java/Combinations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Combinations 3 | * Author: Sam Gavis-Hughson 4 | * Date: 2/15/19 5 | * 6 | * Given an array, write a function to find all combinations (powerset) of 7 | * the elements in the array 8 | * 9 | * eg. 10 | * combinations({1, 2, 3}) = [[1], [1,2], [1,3], [1,2,3], [2], [2,3], [3], []] 11 | * 12 | * Execution: javac Combinations.java && java Combinations 13 | */ 14 | 15 | import java.util.List; 16 | import java.util.LinkedList; 17 | 18 | public class Combinations { 19 | 20 | // Global variable to store result 21 | static List> results; 22 | 23 | // Compute all combinations using a global variable 24 | public static void combinationsGlobal(int[] n) { 25 | results = new LinkedList>(); 26 | combinationsGlobal(n, 0, new LinkedList()); 27 | } 28 | 29 | // Recursive inner function 30 | private static void combinationsGlobal(int[] n, int i, List path) { 31 | // If we reach the end of the array, add the current path to the result 32 | if (i == n.length) { 33 | results.add(path); 34 | return; 35 | } 36 | 37 | // Make one copy of the path that includes the current item 38 | List pathWithCurrent = new LinkedList(path); 39 | pathWithCurrent.add(n[i]); 40 | 41 | // Find all the combinations that exclude current item 42 | combinationsGlobal(n, i+1, path); 43 | 44 | // Find all the combinations that include current item 45 | combinationsGlobal(n, i+1, pathWithCurrent); 46 | } 47 | 48 | // Find all combinations using a passed variable 49 | public static List> combinationsPassed(int[] n) { 50 | // Initialize the result list and pass to our recursive function 51 | List> results = new LinkedList(); 52 | combinationsPassed(n, 0, results, new LinkedList()); 53 | 54 | return results; 55 | } 56 | 57 | // Recursive inner function 58 | private static void combinationsPassed(int[] n, int i, List> results, 59 | List path) { 60 | // If we reach the end of the array, add the current path to the result 61 | if (i == n.length) { 62 | results.add(path); 63 | return; 64 | } 65 | 66 | // Make one copy of the path that includes the current item 67 | List pathWithCurrent = new LinkedList(path); 68 | pathWithCurrent.add(n[i]); 69 | 70 | // Find all the combinations that exclude current item 71 | combinationsPassed(n, i+1, results, path); 72 | 73 | // Find all the combinations that include current item 74 | combinationsPassed(n, i+1, results, pathWithCurrent); 75 | } 76 | 77 | // Find all combinations by building up the results 78 | public static List> combinationsBuiltUp(int[] n) { 79 | return combinationsBuiltUp(n, 0); 80 | } 81 | 82 | // Recursive inner function 83 | private static List> combinationsBuiltUp(int[] n, int i) { 84 | // When we reach the end of our array, we have a single result 85 | // -- An empty list 86 | if (i == n.length) { 87 | List> toReturn = new LinkedList>(); 88 | toReturn.add(new LinkedList()); 89 | 90 | // Return [[]] 91 | return toReturn; 92 | } 93 | 94 | // Create a new list to save the new result 95 | List> toReturn = new LinkedList>(); 96 | 97 | // Get all combinations from i+1 to the end of the list. Then for each 98 | // of those, both include and exclude the current item 99 | for (List result : combinationsBuiltUp(n, i+1)) { 100 | // Exclude current item 101 | toReturn.add(new LinkedList(result)); 102 | 103 | // Include current item 104 | result.add(0, n[i]); 105 | toReturn.add(new LinkedList(result)); 106 | } 107 | 108 | return toReturn; 109 | } 110 | 111 | // Count the number of unique combinations of an array 112 | public static int countCombinations(int[] n) { 113 | return countCombinations(n, 0); 114 | } 115 | 116 | // Recursive inner function 117 | private static int countCombinations(int[] n, int i) { 118 | // When we hit our ase case we've found one valid combination 119 | if (i == n.length) { 120 | return 1; 121 | } 122 | 123 | // Otherwise try including and excluding the current item 124 | int include = countCombinations(n, i+1); 125 | int exclude = countCombinations(n, i+1); 126 | 127 | return include + exclude; 128 | } 129 | 130 | public static void main(String[] args) { 131 | combinationsGlobal(new int[]{1,2,3}); 132 | System.out.println(results); 133 | System.out.println(combinationsPassed(new int[]{1,2,3,4})); 134 | System.out.println(combinationsPassed(new int[]{1,2,3,4,5})); 135 | System.out.println(countCombinations(new int[]{1,2,3})); 136 | } 137 | } -------------------------------------------------------------------------------- /java/CombinationsOfLength.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class CombinationsOfLength { 5 | public static List> combinationsOfLengthBruteForce(int[] n, int length) { 6 | List> allCombinations = Combinations.combinationsBuiltUp(n); 7 | 8 | List> filtered = new LinkedList>(); 9 | for (List l : allCombinations) { 10 | if (l.size() == length) filtered.add(l); 11 | } 12 | 13 | return filtered; 14 | } 15 | 16 | public static List> combinationsOfLengthBacktracking(int[] n, int length) { 17 | return combinationsOfLengthBacktracking(n, 0, length, 0); 18 | } 19 | 20 | private static List> combinationsOfLengthBacktracking(int[] n, int i, 21 | int targetLength, 22 | int currentLength) { 23 | if (currentLength > targetLength) return new LinkedList>(); 24 | if (i == n.length && currentLength != targetLength) return new LinkedList>(); 25 | if (i == n.length) { 26 | List> toReturn = new LinkedList>(); 27 | toReturn.add(new LinkedList()); 28 | return toReturn; 29 | } 30 | 31 | List> include = combinationsOfLengthBacktracking(n, i+1, targetLength, currentLength + 1); 32 | List> exclude = combinationsOfLengthBacktracking(n, i+1, targetLength, currentLength); 33 | 34 | List> toReturn = new LinkedList>(); 35 | for (List result : include) { 36 | result.add(0, n[i]); 37 | toReturn.add(result); 38 | } 39 | 40 | toReturn.addAll(exclude); 41 | 42 | return toReturn; 43 | } 44 | 45 | // private static List> combinationsBuiltUp(int[] n, int i) { 46 | // if (i == n.length) { 47 | // List> toReturn = new LinkedList>(); 48 | // toReturn.add(new LinkedList()); 49 | // return toReturn; 50 | // } 51 | // 52 | // List> toReturn = new LinkedList>(); 53 | // for (List result : combinationsBuiltUp(n, i+1)) { 54 | // // Exclude current item 55 | // toReturn.add(new LinkedList(result)); 56 | // // Include current item 57 | // result.add(0, n[i]); 58 | // toReturn.add(new LinkedList(result)); 59 | // } 60 | // 61 | // return toReturn; 62 | // } 63 | 64 | public static void main(String[] args) { 65 | System.out.println(combinationsOfLengthBruteForce(new int[]{1,2,3,4,5}, 3)); 66 | System.out.println(combinationsOfLengthBacktracking(new int[]{1,2,3,4,5}, 3)); 67 | } 68 | } -------------------------------------------------------------------------------- /java/ConsultantSchedule.java: -------------------------------------------------------------------------------- 1 | public class ConsultantSchedule { 2 | public static class Schedule { 3 | String schedule; 4 | int value; 5 | 6 | public Schedule(String schedule, int value) { 7 | this.schedule = schedule; 8 | this.value = value; 9 | } 10 | } 11 | 12 | public static String consultantSchedule(int[] ny, int[] bos) { 13 | Schedule newYork = consultantScheduleNewYork(ny, bos, 0); 14 | Schedule boston = consultantScheduleBoston(ny, bos, 0); 15 | 16 | if (newYork.value > boston.value) return newYork.schedule; 17 | return boston.schedule; 18 | } 19 | 20 | private static Schedule consultantScheduleBoston(int[] ny, int[] bos, int i) { 21 | if (i >= ny.length) return new Schedule("", 0); 22 | Schedule stay = consultantScheduleBoston(ny, bos, i+1); 23 | Schedule move = consultantScheduleNewYork(ny, bos, i+1); 24 | 25 | if (stay.value + bos[i] > move.value) 26 | return new Schedule("B" + stay.schedule, stay.value + bos[i]); 27 | return new Schedule("T" + move.schedule, move.value); 28 | } 29 | 30 | private static Schedule consultantScheduleNewYork(int[] ny, int[] bos, int i) { 31 | if (i >= ny.length) return new Schedule("", 0); 32 | Schedule stay = consultantScheduleNewYork(ny, bos, i+1); 33 | Schedule move = consultantScheduleBoston(ny, bos, i+1); 34 | 35 | if (stay.value + ny[i] > move.value) 36 | return new Schedule("N" + stay.schedule, stay.value + ny[i]); 37 | return new Schedule("T" + move.schedule, move.value); 38 | } 39 | 40 | public static void main(String[] args) { 41 | System.out.println(consultantSchedule(new int[]{1,2,3,4,4,3,2,1}, new int[]{4,3,2,1,1,2,3,4})); 42 | } 43 | } -------------------------------------------------------------------------------- /java/CountEven.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Count Even 3 | * Author: Sam Gavis-Hughson 4 | * Date: 2/15/19 5 | * 6 | * Given an array, count the number of even values in the array 7 | * 8 | * eg. 9 | * countEven({1, 2, 3, 4, 5}) = 2 10 | * 11 | * Execution: javac CountEven.java && java CountEven 12 | */ 13 | 14 | public class CountEven { 15 | 16 | // Global variable for saving the result 17 | static int globalResult; 18 | 19 | // Count even values using a global variable 20 | public static void countEvenGlobal(int[] arr) { 21 | globalResult = 0; 22 | countEvenGlobal(arr, 0); 23 | } 24 | 25 | // Recursive inner function 26 | private static void countEvenGlobal(int[] arr, int i) { 27 | // If we reach the end of the array, we're done 28 | if (i >= arr.length) return; 29 | 30 | // If the current value is even, increment the result 31 | if (arr[i] % 2 == 0) globalResult++; 32 | countEvenGlobal(arr, i+1); 33 | } 34 | 35 | // Wrapper class so that we can pass-by-reference 36 | public static class ResultWrapper { 37 | int result; 38 | } 39 | 40 | // Count even values using a passed variable 41 | public static int countEvenPassed(int[] arr) { 42 | ResultWrapper result = new ResultWrapper(); 43 | result.result = 0; 44 | countEvenPassed(arr, 0, result); 45 | return result.result; 46 | } 47 | 48 | // Recursive inner class 49 | private static void countEvenPassed(int[] arr, int i, ResultWrapper result) { 50 | // If we reach the end of the array, return 51 | if (i >= arr.length) return; 52 | 53 | // If the value is even, update the result 54 | if (arr[i] % 2 == 0) result.result++; 55 | countEvenPassed(arr, i+1, result); 56 | } 57 | 58 | // Count even values by building up as we return 59 | public static int countEvenBuiltUp(int[] arr) { 60 | return countEvenBuiltUp(arr, 0); 61 | } 62 | 63 | // Recursive inner class 64 | private static int countEvenBuiltUp(int[] arr, int i) { 65 | // If we reach the end, return 0 66 | if (i >= arr.length) return 0; 67 | 68 | // Otherwise make our recursive call and then add 1 to the value if the 69 | // current value is even 70 | int result = countEvenBuiltUp(arr, i+1); 71 | if (arr[i] % 2 == 0) result++; 72 | 73 | return result; 74 | } 75 | 76 | public static void main(String[] args) { 77 | countEvenGlobal(new int[]{1,2,3,4,5,6,7}); 78 | System.out.println(globalResult); 79 | System.out.println(countEvenPassed(new int[]{1,2,3,4,5,6,7})); 80 | System.out.println(countEvenBuiltUp(new int[]{1,2,3,4,5,6,7})); 81 | } 82 | } -------------------------------------------------------------------------------- /java/DFSCombinations.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.HashSet; 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public class DFSCombinations { 8 | public static class State { 9 | private boolean[] state; 10 | 11 | public State(int n) { 12 | this.state = new boolean[n]; 13 | } 14 | 15 | private State(boolean[] state) { 16 | this.state = state.clone(); 17 | } 18 | 19 | public List adjacent() { 20 | List result = new LinkedList(); 21 | for (int i = 0; i < this.state.length; i++) { 22 | state[i] = !state[i]; 23 | result.add(new State(state)); 24 | state[i] = !state[i]; 25 | } 26 | 27 | return result; 28 | } 29 | 30 | public String toString() { 31 | StringBuilder sb = new StringBuilder(); 32 | sb.append("["); 33 | for (int i = 0; i < this.state.length; i++) { 34 | if (state[i]) sb.append(i + ","); 35 | } 36 | if (sb.length() > 1) sb.setLength(sb.length() - 1); 37 | sb.append("]"); 38 | return sb.toString(); 39 | } 40 | 41 | public boolean equals(Object o) { 42 | if (o instanceof State) { 43 | State s = (State) o; 44 | if (this.state.length != s.state.length) return false; 45 | for (int i = 0; i < this.state.length; i++) { 46 | if (this.state[i] != s.state[i]) return false; 47 | } 48 | return true; 49 | } 50 | return false; 51 | } 52 | 53 | public int hashCode() { 54 | return Arrays.hashCode(this.state); 55 | } 56 | } 57 | 58 | public static List combinations(int n) { 59 | Set results = new HashSet(); 60 | combinations(new State(n), results); 61 | return new LinkedList(results); 62 | } 63 | 64 | private static void combinations(State curr, Set results) { 65 | if (results.contains(curr)) return; 66 | results.add(curr); 67 | for (State s : curr.adjacent()) { 68 | combinations(s, results); 69 | } 70 | } 71 | 72 | public static void main(String[] args) { 73 | System.out.println(combinations(4)); 74 | } 75 | } -------------------------------------------------------------------------------- /java/DFSEditDistance.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.HashSet; 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public class DFSEditDistance { 8 | public static class State { 9 | private StringBuilder state; 10 | private Set chars; 11 | 12 | public State(String s) { 13 | this(s, new HashSet(Arrays.asList(new Character[]{ 14 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 15 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}))); 16 | } 17 | 18 | public State(StringBuilder sb) { 19 | this(sb.toString()); 20 | } 21 | 22 | public State(String s, Set chars) { 23 | this.state = new StringBuilder(s); 24 | this.chars = new HashSet(chars); 25 | } 26 | 27 | public List adjacent() { 28 | List results = new LinkedList(); 29 | for (int i = 0; i < state.length(); i++) { 30 | char curr = state.charAt(i); 31 | state.deleteCharAt(i); 32 | results.add(new State(state)); 33 | state.insert(i, curr); 34 | for (Character c : chars) { 35 | state.setCharAt(i, c); 36 | results.add(new State(state)); 37 | state.setCharAt(i, curr); 38 | state.insert(i, c); 39 | results.add(new State(state)); 40 | state.deleteCharAt(i); 41 | } 42 | } 43 | 44 | return results; 45 | } 46 | 47 | public String toString() { 48 | return state.toString(); 49 | } 50 | 51 | public boolean equals(Object o) { 52 | if (o instanceof State) { 53 | State s = (State) o; 54 | if (this.state.toString().equals(s.state.toString())) return true; 55 | } 56 | return false; 57 | } 58 | 59 | public int hashCode() { 60 | return this.state.toString().hashCode(); 61 | } 62 | } 63 | 64 | public static List editDistance(String s1, String s2) { 65 | List> result = new LinkedList>(); 66 | editDistance(new State(s1), new State(s2), Math.max(s1.length(), s2.length()), 67 | new HashSet(), new LinkedList(), result); 68 | return result.get(0); 69 | } 70 | 71 | private static void editDistance(State s1, State s2, int maxDepth, Set visited, 72 | List path, List> result) { 73 | if (visited.contains(s1)) return; 74 | 75 | if (s1.equals(s2)) { 76 | if (result.size() == 0) result.add(new LinkedList(path)); 77 | else if (path.size() < result.get(0).size()) result.set(0, new LinkedList(path)); 78 | return; 79 | } 80 | 81 | if (maxDepth == path.size()) return; 82 | visited.add(s1); 83 | 84 | for (State s : s1.adjacent()) { 85 | path.add(s); 86 | editDistance(s, s2, maxDepth, visited, path, result); 87 | path.remove(path.size() - 1); 88 | } 89 | } 90 | 91 | public static void main(String[] args) { 92 | System.out.println(editDistance("abc", "cab")); 93 | } 94 | } -------------------------------------------------------------------------------- /java/DFSGraph.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.LinkedList; 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | public class DFSGraph { 7 | public static class Node { 8 | int value; 9 | Node[] neighbors; 10 | 11 | public Node(int value) { 12 | this.value = value; 13 | } 14 | 15 | public String toString() { 16 | return "" + value; 17 | } 18 | } 19 | 20 | public static boolean pathExists(Node src, Node dest) { 21 | return pathExists(src, dest, new HashSet()); 22 | } 23 | 24 | private static boolean pathExists(Node curr, Node dest, Set visited) { 25 | if (visited.contains(curr)) return false; 26 | if (curr == dest) return true; 27 | 28 | visited.add(curr); 29 | for (Node n : curr.neighbors) { 30 | if (pathExists(n, dest, visited)) return true; 31 | } 32 | return false; 33 | } 34 | 35 | public static List> paths(Node src, Node dest) { 36 | List> results = new LinkedList>(); 37 | paths(src, dest, new HashSet(), new LinkedList(), results); 38 | return results; 39 | } 40 | 41 | private static void paths(Node curr, Node dest, Set visited, List path, List> results) { 42 | if (visited.contains(curr)) return; 43 | if (curr == dest) { 44 | path.add(curr); 45 | results.add(new LinkedList(path)); 46 | path.remove(path.size() - 1); 47 | return; 48 | } 49 | 50 | visited.add(curr); 51 | path.add(curr); 52 | for (Node n : curr.neighbors) { 53 | paths(n, dest, visited, path, results); 54 | } 55 | path.remove(path.size() - 1); 56 | visited.remove(curr); 57 | } 58 | 59 | public static void main(String[] args) { 60 | Node[] graph = new Node[6]; 61 | for (int i = 0; i < graph.length; i++) { 62 | graph[i] = new Node(i); 63 | } 64 | 65 | graph[0].neighbors = new Node[]{graph[1], graph[2], graph[3]}; 66 | graph[1].neighbors = new Node[]{graph[4], graph[1]}; 67 | graph[2].neighbors = new Node[]{graph[2]}; 68 | graph[3].neighbors = new Node[]{graph[1]}; 69 | graph[4].neighbors = new Node[]{graph[1], graph[2], graph[3]}; 70 | graph[5].neighbors = new Node[]{}; 71 | 72 | System.out.println(paths(graph[0], graph[4])); 73 | } 74 | } -------------------------------------------------------------------------------- /java/DFSKnapsack.java: -------------------------------------------------------------------------------- 1 | public class DFSKnapsack { 2 | //// private Item[] items; 3 | // private int maxWeight; 4 | // 5 | // public static class State { 6 | // private boolean[] state; 7 | // private int currentWeight; 8 | // private int currentValue; 9 | // 10 | // public State(int n) { 11 | // this.state = new boolean[n]; 12 | // this.currentWeight = 0; 13 | // this.currentValue = 0; 14 | // } 15 | // 16 | // public List adjacent() { 17 | // List result = new LinkedList(); 18 | // for (int i = 0; i < this.state.length; i++) { 19 | // if (state[i]) { 20 | // state[i] = !state[i]; 21 | // currentWeight -= items[i].weight; 22 | // currentValue -= items[i].value; 23 | // result.add(new State(state)); 24 | // state[i] = !state[i]; 25 | // currentWeight += items[i].weight; 26 | // currentValue += items[i].value; 27 | // } else if (items[i].weight + currentWeight < maxWeight) { 28 | // state[i] = !state[i]; 29 | // currentWeight += items[i].weight; 30 | // currentValue += items[i].value; 31 | // result.add(new State(state)); 32 | // state[i] = !state[i]; 33 | // currentWeight -= items[i].weight; 34 | // currentValue -= items[i].value; 35 | // } 36 | // } 37 | // 38 | // return result; 39 | // } 40 | // } 41 | } -------------------------------------------------------------------------------- /java/DFSTree.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class DFSTree { 5 | public static class Node { 6 | int value; 7 | Node left; 8 | Node right; 9 | 10 | public Node(int value) { 11 | this.value = value; 12 | } 13 | 14 | public String toString() { 15 | return "" + value; 16 | } 17 | } 18 | 19 | public static boolean contains(Node root, int val) { 20 | if (root == null) return false; 21 | if (root.value == val) return true; 22 | return contains(root.left, val) || contains(root.right, val); 23 | } 24 | 25 | public static List pathToNode(Node root, int val) { 26 | if (root == null) return null; 27 | if (root.value == val) { 28 | List toReturn = new LinkedList(); 29 | toReturn.add(root); 30 | return toReturn; 31 | } 32 | 33 | List left = pathToNode(root.left, val); 34 | if (left != null) { 35 | left.add(0, root); 36 | return left; 37 | } 38 | 39 | List right = pathToNode(root.right, val); 40 | if (right != null) { 41 | right.add(0, root); 42 | return right; 43 | } 44 | return null; 45 | } 46 | 47 | public static void main(String[] args) { 48 | Node root = new Node(1); 49 | root.left = new Node(2); 50 | root.right = new Node(3); 51 | root.left.left = new Node(4); 52 | root.left.right = new Node(5); 53 | root.right.left = new Node(6); 54 | root.right.right = new Node(7); 55 | 56 | System.out.println(pathToNode(root, 0)); 57 | } 58 | } -------------------------------------------------------------------------------- /java/Decode.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | import java.util.LinkedList; 3 | 4 | public class Decode { 5 | public static List decode(String s) { 6 | List result = new LinkedList(); 7 | decode(s, 0, new StringBuilder(), result); 8 | return result; 9 | } 10 | 11 | private static void decode(String s, int i, StringBuilder curr, List result) { 12 | if (i >= s.length()) { 13 | result.add(curr.toString()); 14 | return; 15 | } 16 | 17 | for (char c : getNext(s, i)) { 18 | curr.append(c); 19 | 20 | if (c < 'A'+10) { 21 | decode(s, i+1, curr, result); 22 | } else { 23 | decode(s, i+2, curr, result); 24 | } 25 | curr.setLength(curr.length() - 1); 26 | } 27 | } 28 | 29 | private static List getNext(String s, int i) { 30 | List toReturn = new LinkedList(); 31 | int val = Integer.valueOf(s.substring(i, i+1)); 32 | toReturn.add((char) ('A' + val - 1)); 33 | if (i < s.length() - 1) { 34 | val = Integer.valueOf(s.substring(i, i+2)); 35 | if (val <= 26) toReturn.add((char) ('A' + val - 1)); 36 | } 37 | return toReturn; 38 | } 39 | 40 | public static void main(String[] args) { 41 | System.out.println(decode("223")); 42 | System.out.println(decode("227")); 43 | System.out.println(decode("4231123")); 44 | } 45 | } -------------------------------------------------------------------------------- /java/EditDistance.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class EditDistance { 5 | public static class Step { 6 | String before; 7 | String after; 8 | 9 | public Step(String before, String after) { 10 | this.before = before; 11 | this.after = after; 12 | } 13 | 14 | public String toString() { 15 | return "\"" + before + "\" -> \"" + after + "\""; 16 | } 17 | } 18 | 19 | public static List editDistance(String s1, String s2) { 20 | return editDistance(s1, s2, 0); 21 | } 22 | 23 | private static List editDistance(String s1, String s2, int i) { 24 | if (s1.equals(s2)) { 25 | return new LinkedList(); 26 | } 27 | 28 | if (i >= s1.length()) { 29 | return insert(s1, s2, i); 30 | } 31 | 32 | if (i >= s2.length()){ 33 | return remove(s1, s2, i); 34 | } 35 | 36 | List inserted = insert(s1, s2, i); 37 | List removed = remove(s1, s2, i); 38 | List swapped = swap(s1, s2, i); 39 | 40 | List toReturn = inserted; 41 | if (removed.size() < toReturn.size()) toReturn = removed; 42 | if (swapped.size() < toReturn.size()) toReturn = swapped; 43 | 44 | if (s1.charAt(i) == s2.charAt(i)) { 45 | List skipped = editDistance(s1, s2, i+1); 46 | if (skipped.size() < toReturn.size()) toReturn = skipped; 47 | } 48 | 49 | return toReturn; 50 | } 51 | 52 | private static List insert(String s1, String s2, int i) { 53 | String insert = s1.substring(0, i) + s2.charAt(i) + s1.substring(i, s1.length()); 54 | List toReturn = editDistance(insert, s2, i+1); 55 | toReturn.add(0, new Step(s1, insert)); 56 | return toReturn; 57 | } 58 | 59 | private static List remove(String s1, String s2, int i) { 60 | String remove = s1.substring(0, i) + s1.substring(i+1, s1.length()); 61 | List toReturn = editDistance(remove, s2, i); 62 | toReturn.add(0, new Step(s1, remove)); 63 | return toReturn; 64 | } 65 | 66 | private static List swap(String s1, String s2, int i) { 67 | String swap = s1.substring(0, i) + s2.charAt(i) + s1.substring(i+1, s1.length()); 68 | List toReturn = editDistance(swap, s2, i+1); 69 | toReturn.add(0, new Step(s1, swap)); 70 | return toReturn; 71 | } 72 | 73 | public static void main(String[] args) { 74 | System.out.println(editDistance("adi", "abcadefghai")); 75 | } 76 | } -------------------------------------------------------------------------------- /java/EggDrop.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Egg Drop 3 | * Author: Sam Gavis-Hughson 4 | * Date: 11/28/2017 5 | * 6 | * Consider dropping eggs off of a building. If you drop an egg from the Xth 7 | * floor and it breaks, then you know for all eggs dropped from floor X or above, 8 | * they will break. Similarly, if you drop an egg from floor X and it doesn't 9 | * break, no egg will break when dropped from floors 1 through X. Given a building 10 | * with N floors and E eggs, find the minimum number of drops needed to determine 11 | * the maximum floor that you can drop an egg from without it breaking. 12 | * 13 | * eg. 14 | * 15 | * eggs = 1 16 | * floors = 10 17 | * eggDrop(eggs, floors) = 10 18 | * If you only have one egg, you need to try every floor from 1 to floors. 19 | * 20 | * eggs = 2 21 | * floors = 10 22 | * eggDrop(eggs, floors) = 4 23 | * Drop the egg from the 4th floor, then the 7th, then the 10th. Each time, if 24 | * the egg breaks, go to one above the previous test and progress up linearly. 25 | * 26 | * Execution: javac EggDrop.java && java EggDrop 27 | */ 28 | 29 | public class EggDrop { 30 | 31 | // Brute force recursive solution. Try dropping an egg from every floor, 32 | // then recursively try the case where it breaks and the case where it 33 | // doesn't to see how many drops they take. floors indicates the range of 34 | // floors that need to be tested, not the total floors. Eg. if the egg broke 35 | // at floor 20 and not at floor 5, then floors = 15 36 | public static int bruteForceEggDrop(int eggs, int floors) { 37 | if (floors == 0) return 0; 38 | if (floors == 1) return 1; 39 | // If we only have one egg, we have to go up one at a time through each 40 | // floor to guarantee that we find the exact floor 41 | if (eggs == 1) return floors; 42 | 43 | int maxDrops = Integer.MAX_VALUE; 44 | // Try dropping the egg from each height. Compute the worst case for if 45 | // it breaks and if it doesn't break 46 | for (int i = 1; i <= floors; i++) { 47 | // If the egg breaks, then the floor we're looking for could be any 48 | // floor less than i 49 | int breaks = bruteForceEggDrop(eggs - 1, i - 1); 50 | // If the egg doesn't break, we can exclude all the floors below and 51 | // including the current floor (i) 52 | int doesntBreak = bruteForceEggDrop(eggs, floors - i); 53 | maxDrops = Math.min(maxDrops, Math.max(breaks, doesntBreak)); 54 | } 55 | return maxDrops + 1; 56 | } 57 | 58 | // Top-down dynamic solution 59 | public static int topDownEggDrop(int eggs, int floors) { 60 | int[][] dp = new int[eggs + 1][floors + 1]; 61 | return topDownEggDrop(eggs, floors, dp); 62 | } 63 | 64 | // Overloaded recursive method 65 | private static int topDownEggDrop(int eggs, int floors, int[][] dp) { 66 | if (floors == 0) return 0; 67 | if (floors == 1) return 1; 68 | if (eggs == 1) return floors; 69 | 70 | if (dp[eggs][floors] == 0) { 71 | int maxDrops = Integer.MAX_VALUE; 72 | for (int i = 1; i <= floors; i++) { 73 | int breaks = bruteForceEggDrop(eggs - 1, i - 1); 74 | int doesntBreak = bruteForceEggDrop(eggs, floors - i); 75 | maxDrops = Math.min(maxDrops, Math.max(breaks, doesntBreak)); 76 | } 77 | dp[eggs][floors] = maxDrops + 1; 78 | } 79 | return dp[eggs][floors]; 80 | } 81 | 82 | // Bottom-up dynamic solution 83 | public static int bottomUpEggDrop(int eggs, int floors) { 84 | int[][] dp = new int[eggs + 1][floors + 1]; 85 | 86 | for (int i = 1; i < dp.length; i++) { 87 | for (int j = 1; j < dp[0].length; j++) { 88 | if (j == 1) { 89 | dp[i][j] = 1; 90 | } else if (i == 1) { 91 | dp[i][j] = j; 92 | } else { 93 | int maxDrops = Integer.MAX_VALUE; 94 | for (int k = 1; k <= j; k++) { 95 | int breaks = dp[i-1][k-1]; 96 | int doesntBreak = dp[i][j-k]; 97 | maxDrops = Math.min(maxDrops, Math.max(breaks, doesntBreak)); 98 | } 99 | dp[i][j] = maxDrops + 1; 100 | } 101 | } 102 | } 103 | 104 | return dp[eggs][floors]; 105 | } 106 | 107 | // Sample testcases 108 | public static void main(String[] args) { 109 | 110 | System.out.println(bruteForceEggDrop(2,6)); 111 | (new TestCase(1, 1, 1)).run(); 112 | (new TestCase(1, 10, 10)).run(); 113 | (new TestCase(2, 10, 4)).run(); 114 | (new TestCase(2, 20, 6)).run(); 115 | (new TestCase(3, 10, 4)).run(); 116 | System.out.println("Passed all test cases"); 117 | } 118 | 119 | // Class for defining and running test cases 120 | private static class TestCase { 121 | private int eggs; 122 | private int floors; 123 | private int output; 124 | 125 | private TestCase(int eggs, int floors, int output) { 126 | this.eggs = eggs; 127 | this.floors = floors; 128 | this.output = output; 129 | } 130 | 131 | private void run() { 132 | assert bruteForceEggDrop(eggs, floors) == output: 133 | "bruteForceEggDrop failed for eggs = " + eggs + ", floors = " + floors; 134 | assert topDownEggDrop(eggs, floors) == output: 135 | "topDownEggDrop failed for eggs = " + eggs + ", floors = " + floors; 136 | assert bottomUpEggDrop(eggs, floors) == output: 137 | "bottomUpEggDrop failed for eggs = " + eggs + ", floors = " + floors; 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /java/Fibonacci.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Fibonacci 3 | * Author: Sam Gavis-Hughson 4 | * Date: 2/15/19 5 | * 6 | * Given an integer n, find the nth Fibonacci number 7 | * 8 | * eg. 9 | * fib(8) = 21 10 | * 11 | * Execution: javac CountEven.java && java CountEven 12 | */ 13 | 14 | 15 | public class Fibonacci { 16 | public static int fibonacci(int n) { 17 | if (n <= 0) return 0; 18 | if (n == 1) return 1; 19 | return fibonacci(n-1) + fibonacci(n-2); 20 | } 21 | 22 | public static void main(String[] args) { 23 | System.out.println(fibonacci(8)); 24 | } 25 | } -------------------------------------------------------------------------------- /java/FilterBuiltinList.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.ArrayList; 3 | import java.util.List; 4 | 5 | public class FilterBuiltinList { 6 | public static void filterListIterative(List l, int cutoff) { 7 | for (int i = l.size() - 1; i >= 0; i--) { 8 | if (l.get(i) > cutoff) l.remove(i); 9 | } 10 | } 11 | 12 | public static void filterListRecursive(List l, int cutoff) { 13 | filterListRecursive(l, cutoff, 0); 14 | } 15 | 16 | private static void filterListRecursive(List l, int cutoff, int i) { 17 | if (i >= l.size()) return; 18 | filterListRecursive(l, cutoff, i+1); 19 | if (l.get(i) > cutoff) l.remove(i); 20 | } 21 | 22 | public static void main(String[] args) { 23 | List l1 = new ArrayList(Arrays.asList(new Integer[]{1,2,3,4,5,4,3,2,1})); 24 | List l2 = new ArrayList(l1); 25 | filterListIterative(l1, 3); 26 | filterListRecursive(l2, 3); 27 | System.out.println("Iterative: " + l1); 28 | System.out.println("Recursive: " + l2); 29 | } 30 | } -------------------------------------------------------------------------------- /java/FilterList.java: -------------------------------------------------------------------------------- 1 | public class FilterList { 2 | 3 | public static class Node { 4 | Node next; 5 | int val; 6 | 7 | public Node(int val) { 8 | this.val = val; 9 | } 10 | } 11 | 12 | public static Node lessThanIterative(Node head, int cutoff) { 13 | Node newHead = head; 14 | while (newHead != null && newHead.val >= cutoff) { 15 | newHead = newHead.next; 16 | } 17 | 18 | Node curr = newHead; 19 | while (curr != null && curr.next != null) { 20 | if (curr.next.val >= cutoff) { 21 | curr.next = curr.next.next; 22 | } else { 23 | curr = curr.next; 24 | } 25 | } 26 | 27 | return newHead; 28 | } 29 | 30 | public static Node lessThan(Node head, int cutoff) { 31 | if (head == null) { 32 | return null; 33 | } 34 | 35 | Node remainder = lessThan(head.next, cutoff); 36 | 37 | if (head.val < cutoff) { 38 | head.next = remainder; 39 | return head; 40 | } 41 | return remainder; 42 | } 43 | 44 | public static void main(String[] args) { 45 | Node head = new Node(5); 46 | head.next = new Node(1); 47 | head.next.next = new Node(10); 48 | head.next.next.next = new Node(7); 49 | 50 | printList(lessThanIterative(head, 11)); 51 | } 52 | 53 | private static void printList(Node head) { 54 | if (head == null) { 55 | System.out.println("null"); 56 | return; 57 | } 58 | while (head.next != null) { 59 | System.out.print(head.val + " -> "); 60 | head = head.next; 61 | } 62 | System.out.println(head.val); 63 | } 64 | } -------------------------------------------------------------------------------- /java/FlattenArrays.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class FlattenArrays { 5 | public static List flattenArraysIterative(int[][] arr) { 6 | List result = new LinkedList(); 7 | for (int[] a : arr) { 8 | for (int i : a) { 9 | result.add(i); 10 | } 11 | } 12 | 13 | return result; 14 | } 15 | 16 | public static List flattenArrays(int[][] arr) { 17 | List result = new LinkedList(); 18 | flattenArrays(arr, 0, 0, result); 19 | return result; 20 | } 21 | 22 | private static void flattenArrays(int[][] arr, int i, int j, List result) { 23 | if (i == arr.length) return; 24 | if (j == arr[i].length) { 25 | flattenArrays(arr, i+1, 0, result); 26 | return; 27 | } 28 | result.add(arr[i][j]); 29 | flattenArrays(arr, i, j+1, result); 30 | } 31 | 32 | public static void main(String[] args) { 33 | System.out.println(flattenArraysIterative(new int[][]{new int[]{1,2,3}, new int[]{4}, new int[]{5,6}})); 34 | System.out.println(flattenArrays(new int[][]{new int[]{1,2,3}, new int[]{4}, new int[]{5,6}})); 35 | } 36 | } -------------------------------------------------------------------------------- /java/GCD.java: -------------------------------------------------------------------------------- 1 | public class GCD { 2 | public static int gcd(int a, int b) { 3 | if (b > a) return gcd(b, a); 4 | if (b == 0) return a; 5 | return gcd(b, a % b); 6 | } 7 | 8 | public static void main(String[] args) { 9 | System.out.println(gcd(10, 5)); 10 | System.out.println(gcd(5, 10)); 11 | System.out.println(gcd(10, 1)); 12 | System.out.println(gcd(1, 5)); 13 | } 14 | } -------------------------------------------------------------------------------- /java/GreatestProductPath.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.LinkedList; 3 | import java.util.List; 4 | 5 | public class GreatestProductPath { 6 | public static class Coordinate { 7 | int x; 8 | int y; 9 | 10 | public Coordinate(int x, int y) { 11 | this.x = x; 12 | this.y = y; 13 | } 14 | 15 | public String toString() { 16 | return "(" + x + ", " + y + ")"; 17 | } 18 | } 19 | 20 | public static int greatestProductPath(int[][] matrix) { 21 | return greatestProductPath(matrix, 0, 0); 22 | } 23 | 24 | private static int greatestProductPath(int[][] matrix, int i, int j) { 25 | if (i == matrix.length - 1 && j == matrix[0].length - 1) return matrix[i][j]; 26 | if (i >= matrix.length || j >= matrix[0].length) return 0; 27 | 28 | return matrix[i][j] * Math.max(greatestProductPath(matrix, i+1, j), 29 | greatestProductPath(matrix, i, j+1)); 30 | } 31 | 32 | public static int greatestProductPath2(int[][] matrix) { 33 | List result = new LinkedList(); 34 | result.add(Integer.MIN_VALUE); 35 | greatestProductPath2(matrix, 0, 0, 1, result); 36 | return result.get(0); 37 | } 38 | 39 | private static void greatestProductPath2(int[][] matrix, int i, int j, int product, List result) { 40 | if (i >= matrix.length || j >= matrix[0].length) return; 41 | 42 | product *= matrix[i][j]; 43 | 44 | if (i == matrix.length - 1 && j == matrix[0].length - 1) { 45 | if (result.get(0) < product) { 46 | result.set(0, product); 47 | } 48 | return; 49 | } 50 | 51 | greatestProductPath2(matrix, i+1, j, product, result); 52 | greatestProductPath2(matrix, i, j+1, product, result); 53 | } 54 | 55 | public static int greatestProductPathBuildUp(int[][] matrix) { 56 | return greatestProductPathBuildUp(matrix, 0, 0)[0]; 57 | } 58 | 59 | private static int[] greatestProductPathBuildUp(int[][] matrix, int i, int j) { 60 | if (i >= matrix.length || j >= matrix[0].length) return null; 61 | 62 | int[] right = greatestProductPathBuildUp(matrix, i+1, j); 63 | int[] down = greatestProductPathBuildUp(matrix, i, j+1); 64 | 65 | if (right == null && down == null) return new int[]{matrix[i][j], matrix[i][j]}; 66 | 67 | int max = Integer.MIN_VALUE; 68 | int min = Integer.MAX_VALUE; 69 | 70 | if (right != null) { 71 | max = Math.max(max, Math.max(right[0] * matrix[i][j], 72 | right[1] * matrix[i][j])); 73 | min = Math.min(min, Math.min(right[0] * matrix[i][j], 74 | right[1] * matrix[i][j])); 75 | } 76 | 77 | if (down != null) { 78 | max = Math.max(max, Math.max(down[0] * matrix[i][j], 79 | down[1] * matrix[i][j])); 80 | min = Math.min(min, Math.min(down[0] * matrix[i][j], 81 | down[1] * matrix[i][j])); 82 | } 83 | 84 | return new int[]{max, min}; 85 | } 86 | 87 | public static void main(String[] args) { 88 | int[][] matrix = new int[][]{ 89 | new int[]{1,2,3}, 90 | new int[]{4,5,6}, 91 | new int[]{7,8,-9}}; 92 | 93 | System.out.println(greatestProductPathBuildUp(matrix)); 94 | } 95 | } -------------------------------------------------------------------------------- /java/InsertAtBottom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: InsertAtBottom 3 | * Author: Sam Gavis-Hughson 4 | * Date: 11/1/2018 5 | * 6 | * Given a stack, write a function to insert an item at the bottom of the stack. 7 | * 8 | * insertAtBottom({1,2,3}, 4) = {1,2,3,4} 9 | * 10 | * Execution: javac InsertAtBottom.java && java InsertAtBottom 11 | */ 12 | 13 | import java.util.Stack; 14 | 15 | public class InsertAtBottom { 16 | 17 | // Iteratively insert item at bottom of stack using an auxilary stack 18 | public static void insertAtBottomIterative(Stack s, int i) { 19 | Stack temp = new Stack(); 20 | while (!s.isEmpty()) temp.push(s.pop()); 21 | s.push(i); 22 | while (!temp.isEmpty()) s.push(temp.pop()); 23 | } 24 | 25 | // Recursively insert item at bottom of stack. Recursively iterate to the 26 | // bottom of the stack, then insert i and return, replacing items above 27 | public static void insertAtBottomRecursive(Stack s, int i) { 28 | 29 | // When we've removed everything from the stack, insert i 30 | if (s.isEmpty()) { 31 | s.push(i); 32 | return; 33 | } 34 | 35 | // Save the current value in the stack frame. Then recurse to the bottom 36 | // of the stack and insert i 37 | int top = s.pop(); 38 | insertAtBottomRecursive(s, i); 39 | s.push(top); 40 | } 41 | 42 | // Sample test case 43 | public static void main(String[] args) { 44 | Stack s = new Stack(); 45 | s.push(1); 46 | s.push(2); 47 | s.push(3); 48 | s.push(4); 49 | insertAtBottomRecursive(s, 5); 50 | System.out.println(s); 51 | } 52 | } -------------------------------------------------------------------------------- /java/InterleaveStrings.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | //import java.util.StringBuilder; 4 | 5 | public class InterleaveStrings { 6 | public static List interleaveBruteForce(String s1, String s2) { 7 | int[] toCombine = new int[s1.length() + s2.length()]; 8 | for (int i = 0; i < toCombine.length; i++) toCombine[i] = i; 9 | List> positions = 10 | CombinationsOfLength.combinationsOfLengthBacktracking(toCombine, s1.length()); 11 | 12 | List results = new LinkedList(); 13 | 14 | for (List l : positions) { 15 | int i = 0; 16 | int j = 0; 17 | StringBuilder result = new StringBuilder(); 18 | for (int k = 0; k < s1.length() + s2.length(); k++) { 19 | if (l.contains(k)) result.append(s1.charAt(i++)); 20 | else result.append(s2.charAt(j++)); 21 | } 22 | 23 | results.add(result.toString()); 24 | } 25 | return results; 26 | } 27 | 28 | public static List interleave(String s1, String s2) { 29 | List results = new LinkedList(); 30 | interleave(s1, s2, 0, 0, new StringBuilder(), results); 31 | return results; 32 | } 33 | 34 | private static void interleave(String s1, String s2, int i, int j, 35 | StringBuilder path, List results) { 36 | if (i == s1.length() && j == s2.length()) { 37 | results.add(path.toString()); 38 | return; 39 | } 40 | 41 | if (i < s1.length()) { 42 | path.append(s1.charAt(i)); 43 | interleave(s1, s2, i+1, j, path, results); 44 | path.setLength(path.length() - 1); 45 | } 46 | if (j < s2.length()) { 47 | path.append(s2.charAt(j)); 48 | interleave(s1, s2, i, j+1, path, results); 49 | path.setLength(path.length() - 1); 50 | } 51 | } 52 | 53 | public static void main(String[] args) { 54 | System.out.println(interleaveBruteForce("ab", "cd")); 55 | } 56 | } -------------------------------------------------------------------------------- /java/IsPalindrome.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Is Palindrome 3 | * Author: Sam Gavis-Hughson 4 | * Date: 11/1/2018 5 | * 6 | * Given a string, determine whether or not the string is a palindrome. 7 | * 8 | * Execution: javac IsPalindrome.java && java IsPalindrome 9 | */ 10 | 11 | public class IsPalindrome { 12 | 13 | // Recursively determine if a string is a palindrome. If the outer two chars 14 | // are the same, then remove them and recursively move towards the center 15 | public static boolean isPalindrome(String s) { 16 | // We could end up with 1 or 0 chars, either of which is a palindrome 17 | if (s.length() <= 1) return true; 18 | 19 | // If the outer two characters are the same, remove them and move 20 | // inward. Otherwise its not a palindrome 21 | return s.charAt(0) == s.charAt(s.length() - 1) 22 | && isPalindrome(s.substring(1, s.length()-1)); 23 | } 24 | 25 | // Recursively determine if string is a palindrome. Optimized by tracking 26 | // indices rather than creating new substrings 27 | public static boolean isPalindromeOptimized(String s) { 28 | return isPalindromeOptimized(s, 0, s.length() - 1); 29 | } 30 | 31 | // Recursive inner function 32 | private static boolean isPalindromeOptimized(String s, int start, int end) { 33 | // If the start and end are the same or end is less, then palindrome 34 | if (end - start <= 0) return true; 35 | 36 | // Same as nonoptimal version, except update indices instead 37 | return s.charAt(start) == s.charAt(end) 38 | && isPalindromeOptimized(s, start+1, end-1); 39 | } 40 | 41 | // Sample test cases 42 | public static void main(String[] args) { 43 | System.out.println(isPalindromeOptimized("abcba")); 44 | System.out.println(isPalindromeOptimized("abccba")); 45 | System.out.println(isPalindromeOptimized("abcdba")); 46 | System.out.println(isPalindromeOptimized("abccbb")); 47 | System.out.println(isPalindromeOptimized("a")); 48 | System.out.println(isPalindromeOptimized("")); 49 | } 50 | } -------------------------------------------------------------------------------- /java/Iteration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Iteration 3 | * Author: Sam Gavis-Hughson 4 | * Date: 11/1/2018 5 | * 6 | * A variety of functions for iterating over an array iteratively and 7 | * recursively. 8 | * 9 | * eg. 10 | * printForward({1, 2, 3, 4, 5}) 11 | * 1 12 | * 2 13 | * 3 14 | * 4 15 | * 5 16 | * 17 | * Execution: javac Iteration.java && java Iteration 18 | */ 19 | 20 | public class Iteration { 21 | 22 | // Iteratively print an array from start to end 23 | public static void printForwardIterative(int[] arr) { 24 | for (int i = 0; i < arr.length; i++) { 25 | System.out.println(arr[i]); 26 | } 27 | } 28 | 29 | // Recursively print an array from start to end 30 | public static void printForwardRecursive(int[] arr) { 31 | printForwardRecursive(arr, 0); 32 | } 33 | 34 | // Recursive inner function 35 | private static void printForwardRecursive(int[] arr, int i) { 36 | // Once we reach the end of the array, we've printed everything 37 | if (i == arr.length) return; 38 | 39 | // If we haven't reached the end, print the current item and then 40 | // increment the counter 41 | System.out.println(arr[i]); 42 | printForwardRecursive(arr, i+1); 43 | } 44 | 45 | // Iteratively print an array from end to start 46 | public static void printBackwardIterative(int[] arr) { 47 | for (int i = arr.length - 1; i >= 0; i--) { 48 | System.out.println(arr[i]); 49 | } 50 | } 51 | 52 | // Recursively print an array from end to start 53 | public static void printBackwardRecursive(int[] arr) { 54 | printBackwardRecursive(arr, 0); 55 | } 56 | 57 | // Recursive inner function 58 | private static void printBackwardRecursive(int[] arr, int i) { 59 | // Once we reach the end of the array, return and start printing 60 | if (i == arr.length) return; 61 | 62 | // If we haven't reached the end, recursively print the remaining items, 63 | // then print the current item 64 | printBackwardRecursive(arr, i+1); 65 | System.out.println(arr[i]); 66 | } 67 | 68 | // Recursively print all odd indices in an array 69 | public static void printOddRecursive(int[] arr) { 70 | printOddRecursive(arr, 0); 71 | } 72 | 73 | // Recursive inner function 74 | private static void printOddRecursive(int[] arr, int i) { 75 | if (i == arr.length) return; 76 | 77 | // Only print the item if it's odd 78 | if (i % 2 == 1) System.out.println(arr[i]); 79 | printOddRecursive(arr, i+1); 80 | } 81 | 82 | // Recursively print all odd elements in an array, optimal method 83 | public static void printOddRecursive2(int[] arr) { 84 | printOddRecursive2(arr, 1); 85 | } 86 | 87 | // Recursive inner function 88 | private static void printOddRecursive2(int[] arr, int i) { 89 | if (i >= arr.length) return; 90 | System.out.println(arr[i]); 91 | printOddRecursive2(arr, i+2); 92 | } 93 | 94 | 95 | // Recursively sum items in array 96 | public static int sumArray1(int[] arr) { 97 | return sumArray1(arr, 0); 98 | } 99 | 100 | // Recursive inner function 101 | private static int sumArray1(int[] arr, int i) { 102 | if (i == arr.length) return 0; 103 | return arr[i] + sumArray1(arr, i+1); 104 | } 105 | 106 | // Class for storing result 107 | public static class Result { 108 | int result; 109 | } 110 | 111 | // Recursively sum items in array using passed variable 112 | public static int sumArray2(int[] arr) { 113 | Result r = new Result(); 114 | sumArray2(arr, 0, r); 115 | return r.result; 116 | } 117 | 118 | // Recursive inner function 119 | public static void sumArray2(int[] arr, int i, Result r) { 120 | if (i == arr.length) return; 121 | r.result += arr[i]; 122 | sumArray2(arr, i+1, r); 123 | } 124 | 125 | // Test main method 126 | public static void main(String[] args) { 127 | int[] arr = new int[]{1,2,3,4,5}; 128 | printForwardIterative(arr); 129 | printForwardRecursive(arr); 130 | 131 | printBackwardIterative(arr); 132 | printBackwardRecursive(arr); 133 | 134 | printOddRecursive(arr); 135 | printOddRecursive2(arr); 136 | 137 | System.out.println(sumArray1(arr)); 138 | System.out.println(sumArray2(arr)); 139 | } 140 | } -------------------------------------------------------------------------------- /java/IterativeDFS.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | import java.util.Stack; 4 | 5 | public class IterativeDFS { 6 | public static class Node { 7 | int value; 8 | Node left; 9 | Node right; 10 | 11 | public Node(int value) { 12 | this.value = value; 13 | } 14 | 15 | public String toString() { 16 | return "" + value; 17 | } 18 | } 19 | 20 | public static void iterativeDFS(Node root) { 21 | Stack items = new Stack(); 22 | Set visited = new HashSet(); 23 | items.push(root); 24 | 25 | while (!items.isEmpty()) { 26 | Node top = items.peek(); 27 | boolean unvisitedChildren = false; 28 | if (top.right != null && !visited.contains(top.right)) { 29 | items.push(top.right); 30 | unvisitedChildren = true; 31 | } 32 | if (top.left != null && !visited.contains(top.left)) { 33 | items.push(top.left); 34 | unvisitedChildren = true; 35 | } 36 | 37 | if (!unvisitedChildren) { 38 | visited.add(top); 39 | items.pop(); 40 | System.out.println(top); 41 | } 42 | } 43 | } 44 | 45 | public static void main(String[] args) { 46 | Node root = new Node(1); 47 | root.left = new Node(2); 48 | root.right = new Node(3); 49 | root.left.left = new Node(4); 50 | root.left.right = new Node(5); 51 | root.right.left = new Node(6); 52 | root.right.right = new Node(7); 53 | 54 | iterativeDFS(root); 55 | } 56 | } -------------------------------------------------------------------------------- /java/Knapsack.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class Knapsack { 5 | public static class Item { 6 | int weight; 7 | int value; 8 | 9 | public Item(int weight, int value) { 10 | this.weight = weight; 11 | this.value = value; 12 | } 13 | 14 | public String toString() { 15 | return "{w: " + weight + ", v: " + value + "}"; 16 | } 17 | } 18 | 19 | public static List knapsackBruteForce(Item[] items, int totalWeight) { 20 | List> results = new LinkedList>(); 21 | knapsackBruteForce(items, 0, new LinkedList(), results); 22 | 23 | List maxList = null; 24 | int max = Integer.MIN_VALUE; 25 | 26 | for (List l : results) { 27 | int weight = 0; 28 | int value = 0; 29 | for (Item i : l) { 30 | weight += i.weight; 31 | value += i.value; 32 | } 33 | 34 | if (weight <= totalWeight && value > max) { 35 | maxList = l; 36 | max = value; 37 | } 38 | } 39 | 40 | return maxList; 41 | } 42 | 43 | private static void knapsackBruteForce(Item[] items, int i, List path, 44 | List> results) { 45 | if (i == items.length) { 46 | results.add(new LinkedList(path)); 47 | return; 48 | } 49 | 50 | knapsackBruteForce(items, i+1, path, results); 51 | path.add(items[i]); 52 | knapsackBruteForce(items, i+1, path, results); 53 | path.remove(path.size() - 1); 54 | } 55 | 56 | public static List knapsackBacktracking(Item[] items, int totalWeight) { 57 | List> results = new LinkedList>(); 58 | knapsackBacktracking(items, 0, new LinkedList(), 0, totalWeight, results); 59 | 60 | List maxList = null; 61 | int max = Integer.MIN_VALUE; 62 | 63 | for (List l : results) { 64 | int sum = 0; 65 | for (Item i : l) { 66 | sum += i.value; 67 | } 68 | 69 | if (sum > max) { 70 | maxList = l; 71 | max = sum; 72 | } 73 | } 74 | 75 | return maxList; 76 | } 77 | 78 | private static void knapsackBacktracking(Item[] items, int i, List path, 79 | int currentWeight, int totalWeight, 80 | List> results) { 81 | if (currentWeight > totalWeight) return; 82 | if (i == items.length) { 83 | results.add(new LinkedList(path)); 84 | return; 85 | } 86 | 87 | knapsackBacktracking(items, i+1, path, currentWeight, totalWeight, results); 88 | path.add(items[i]); 89 | knapsackBacktracking(items, i+1, path, currentWeight+items[i].weight, totalWeight, results); 90 | path.remove(path.size() - 1); 91 | } 92 | 93 | public static List knapsackBacktrackingOptimized(Item[] items, int totalWeight) { 94 | List> result = new LinkedList>(); 95 | result.add(new LinkedList()); 96 | knapsackBacktrackingOptimized(items, 0, new LinkedList(), 0, totalWeight, result); 97 | return result.get(0); 98 | } 99 | 100 | private static void knapsackBacktrackingOptimized(Item[] items, int i, List path, 101 | int currentWeight, int totalWeight, 102 | List> result) { 103 | if (currentWeight > totalWeight) return; 104 | if (i == items.length) { 105 | if (itemsValue(result.get(0)) < itemsValue(path)) { 106 | result.set(0, new LinkedList(path)); 107 | } 108 | return; 109 | } 110 | 111 | knapsackBacktrackingOptimized(items, i+1, path, currentWeight, totalWeight, result); 112 | path.add(items[i]); 113 | knapsackBacktrackingOptimized(items, i+1, path, currentWeight+items[i].weight, totalWeight, result); 114 | path.remove(path.size() - 1); 115 | } 116 | 117 | private static int itemsValue(List l) { 118 | int sum = 0; 119 | for (Item i : l) sum +=i.value; 120 | return sum; 121 | } 122 | 123 | public static class Result { 124 | List result; 125 | int value; 126 | 127 | public Result() { 128 | this.result = new LinkedList(); 129 | this.value = 0; 130 | } 131 | } 132 | 133 | 134 | public static List knapsackOptimized(Item[] items, int totalWeight) { 135 | Result result = new Result(); 136 | knapsackOptimized(items, 0, new LinkedList(), 0, totalWeight, result, 0); 137 | return result.result; 138 | } 139 | 140 | private static void knapsackOptimized(Item[] items, int i, List path, int currentWeight, 141 | int totalWeight, Result result, int currentValue) { 142 | if (currentWeight > totalWeight) return; 143 | if (i == items.length) { 144 | if (currentValue > result.value) { 145 | result.result = new LinkedList(path); 146 | result.value = currentValue; 147 | } 148 | return; 149 | } 150 | 151 | knapsackOptimized(items, i+1, path, currentWeight, totalWeight, result, currentValue); 152 | path.add(items[i]); 153 | knapsackOptimized(items, i+1, path, currentWeight+items[i].weight, totalWeight, result, currentValue+items[i].value); 154 | path.remove(path.size() - 1); 155 | } 156 | 157 | public static List knapsackBuiltUp(Item[] items, int totalWeight) { 158 | Result result = knapsackBuiltUp(items, totalWeight, 0); 159 | return result.result; 160 | } 161 | 162 | private static Result knapsackBuiltUp(Item[] items, int totalWeight, int i) { 163 | if (i == items.length) return new Result(); 164 | 165 | Result exclude = knapsackBuiltUp(items, totalWeight, i+1); 166 | 167 | if (totalWeight-items[i].weight >= 0) { 168 | Result include = knapsackBuiltUp(items, totalWeight - items[i].weight, i+1); 169 | 170 | if (include.value + items[i].value > exclude.value) { 171 | include.result.add(0, items[i]); 172 | include.value += items[i].value; 173 | return include; 174 | } 175 | } 176 | 177 | return exclude; 178 | } 179 | 180 | public static void main(String[] args) { 181 | System.out.println(knapsackBruteForce(new Item[]{new Item(1,6), new Item(2,10), new Item(3,12)}, 5)); 182 | System.out.println(knapsackOptimized(new Item[]{new Item(1,6), new Item(2,10), new Item(3,12)}, 5)); 183 | System.out.println(knapsackBuiltUp(new Item[]{new Item(1,6), new Item(2,10), new Item(3,12)}, 5)); 184 | } 185 | // * items = {(w:1, v:6), (w:2, v:10), (w:3, v:12)} 186 | 187 | } -------------------------------------------------------------------------------- /java/LongestConsecutivePath.java: -------------------------------------------------------------------------------- 1 | public class LongestConsecutivePath { 2 | public static class Node { 3 | int value; 4 | Node left; 5 | Node right; 6 | 7 | public Node(int value) { 8 | this.value = value; 9 | } 10 | } 11 | 12 | public static int longestConsecutivePath(Node root) { 13 | return longestConsecutivePath(root, 1, root); 14 | } 15 | 16 | private static int longestConsecutivePath(Node root, int pathLength, Node parent) { 17 | if (root == null) return pathLength; 18 | 19 | if (root.value == parent.value+1) { 20 | return Math.max(longestConsecutivePath(root.left, pathLength+1, root), 21 | longestConsecutivePath(root.right, pathLength+1, root)); 22 | } 23 | 24 | return Math.max(pathLength, Math.max(longestConsecutivePath(root.left, 1, root), 25 | longestConsecutivePath(root.right, 1, root))); 26 | } 27 | 28 | public static void main(String[] args) { 29 | Node root = new Node(1); 30 | root.left = new Node(3); 31 | root.left.right = new Node(4); 32 | root.left.right.left = new Node(5); 33 | 34 | System.out.println(longestConsecutivePath(root)); 35 | } 36 | } -------------------------------------------------------------------------------- /java/LongestIncreasingSubsequence.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class LongestIncreasingSubsequence { 5 | public static List longestIncreasingSubsequence(int[] arr) { 6 | return longestIncreasingSubsequence(arr, 0, 0); 7 | } 8 | 9 | private static List longestIncreasingSubsequence(int[] arr, int i, int min) { 10 | if (i == arr.length) { 11 | return new LinkedList(); 12 | } 13 | 14 | List maxList = longestIncreasingSubsequence(arr, i+1, min); 15 | 16 | if (arr[i] > min) { 17 | List includeI = longestIncreasingSubsequence(arr, i+1, arr[i]); 18 | includeI.add(0, arr[i]); 19 | if (includeI.size() > maxList.size()) maxList = includeI; 20 | } 21 | 22 | return maxList; 23 | } 24 | 25 | public static void main(String[] args) { 26 | System.out.println(longestIncreasingSubsequence(new int[]{9,6,1,5,10,13,55,12})); 27 | System.out.println(longestIncreasingSubsequence(new int[]{9,8,7,6,5,4,3,2,1})); 28 | } 29 | } -------------------------------------------------------------------------------- /java/MakingChange.java: -------------------------------------------------------------------------------- 1 | public class MakingChange { 2 | public static int makingChange(int[] coins, int amt) { 3 | return makingChange(coins, amt, 0); 4 | } 5 | 6 | private static int makingChange(int[] coins, int amt, int i) { 7 | if (amt == 0) return 0; 8 | if (amt < 0 || i == coins.length) return -1; 9 | 10 | int include = makingChange(coins, amt - coins[i], i); 11 | int exclude = makingChange(coins, amt, i+1); 12 | 13 | if (include < 0) return exclude; 14 | if (exclude < 0) return include + 1; 15 | 16 | return Math.min(include+1, exclude); 17 | } 18 | 19 | public static void main(String[] args) { 20 | System.out.println(makingChange(new int[]{1,6,10}, 12)); 21 | } 22 | } -------------------------------------------------------------------------------- /java/MinMax.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class MinMax { 4 | public static int[] minMax(int[] arr) { 5 | int[] result = new int[]{Integer.MAX_VALUE, Integer.MIN_VALUE}; 6 | minMax(arr, 0, result); 7 | return result; 8 | } 9 | 10 | private static void minMax(int[] arr, int i, int[] result) { 11 | if (i >= arr.length) return; 12 | result[0] = Math.min(result[0], arr[i]); 13 | result[1] = Math.max(result[1], arr[i]); 14 | minMax(arr, i+1, result); 15 | } 16 | 17 | public static void main(String[] args) { 18 | System.out.println(Arrays.toString(minMax(new int[]{1,2,3,4,5}))); 19 | System.out.println(Arrays.toString(minMax(new int[]{5,4,3,2,1}))); 20 | } 21 | } -------------------------------------------------------------------------------- /java/MinimumCompression.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | 4 | public class MinimumCompression { 5 | public static class CompressedString { 6 | String value; 7 | int repetitions; 8 | 9 | public CompressedString(String value, int repetitions) { 10 | this.value = value; 11 | this.repetitions = repetitions; 12 | } 13 | 14 | public int length() { 15 | if (repetitions == 1) return value.length(); 16 | return value.length() + 3; 17 | } 18 | 19 | public String toString() { 20 | if (repetitions == 1) return value; 21 | return "" + repetitions + "[" + value + "]"; 22 | } 23 | } 24 | 25 | public static String minimumCompression(String input) { 26 | CompressedString result = minimumCompressionInner(input); 27 | return result.toString(); 28 | } 29 | 30 | private static CompressedString minimumCompressionInner(String input) { 31 | CompressedString result = new CompressedString(input, 1); 32 | for (int i = 1; i < input.length(); i++) { 33 | CompressedString prefix = minimumCompressionInner(input.substring(0, i)); 34 | CompressedString suffix = minimumCompressionInner(input.substring(i, input.length())); 35 | 36 | if (prefix.value.equals(suffix.value)) { 37 | if (prefix.length() < result.length()) { 38 | result = new CompressedString(prefix.value, prefix.repetitions + suffix.repetitions); 39 | } 40 | } else { 41 | String curr = prefix.toString() + suffix.toString(); 42 | if (curr.length() < result.length()) { 43 | result = new CompressedString(curr, 1); 44 | } 45 | } 46 | } 47 | return result; 48 | } 49 | 50 | public static String minimumCompressionDP(String input) { 51 | CompressedString result = minimumCompressionDP(input, new HashMap()); 52 | return result.toString(); 53 | } 54 | 55 | private static CompressedString minimumCompressionDP(String input, Map dp) { 56 | if (dp.containsKey(input)) return dp.get(input); 57 | 58 | CompressedString result = new CompressedString(input, 1); 59 | for (int i = 1; i < input.length(); i++) { 60 | CompressedString prefix = minimumCompressionDP(input.substring(0, i), dp); 61 | CompressedString suffix = minimumCompressionDP(input.substring(i, input.length()), dp); 62 | 63 | if (prefix.value.equals(suffix.value)) { 64 | if (prefix.length() < result.length()) { 65 | result = new CompressedString(prefix.value, prefix.repetitions + suffix.repetitions); 66 | } 67 | } else { 68 | String curr = prefix.toString() + suffix.toString(); 69 | if (curr.length() < result.length()) { 70 | result = new CompressedString(curr, 1); 71 | } 72 | } 73 | } 74 | 75 | dp.put(input, result); 76 | return result; 77 | } 78 | 79 | public static void main(String[] args) { 80 | System.out.println(minimumCompressionDP("abdddddabdddddabdddddabddddd")); 81 | } 82 | } -------------------------------------------------------------------------------- /java/NDigitNumbers.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class NDigitNumbers { 5 | public static List nDigitNumbers(int N, int target) { 6 | List> results = new LinkedList>(); 7 | nDigitNumbers(N, target, 0, new LinkedList(), results); 8 | 9 | List toReturn = new LinkedList(); 10 | for (List l : results) { 11 | toReturn.add(listToInteger(l)); 12 | } 13 | 14 | return toReturn; 15 | } 16 | 17 | private static void nDigitNumbers(int N, int target, int sum, 18 | List path, List> results) { 19 | if (sum > target) return; 20 | if (N == 0) { 21 | if (sum == target) { 22 | results.add(new LinkedList(path)); 23 | } 24 | return; 25 | } 26 | 27 | for (int i = 0; i < 10; i++) { 28 | if (sum == 0 && i == 0) continue; 29 | path.add(i); 30 | nDigitNumbers(N-1, target, sum+i, path, results); 31 | path.remove(path.size() - 1); 32 | } 33 | } 34 | 35 | private static int listToInteger(List l) { 36 | int sum = 0; 37 | for (int i = 0; i < l.size(); i++) { 38 | sum += l.get(i) * Math.pow(10, l.size()-i-1); 39 | } 40 | return sum; 41 | } 42 | 43 | public static void main(String[] args) { 44 | System.out.println(nDigitNumbers(5, 12)); 45 | } 46 | } -------------------------------------------------------------------------------- /java/NQueens.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.LinkedList; 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | public class NQueens { 7 | public static class Cell { 8 | int row; 9 | int col; 10 | 11 | public Cell(int row, int col) { 12 | this.row = row; 13 | this.col = col; 14 | } 15 | 16 | public String toString() { 17 | return "{r: " + row + ", c: " + col + "}"; 18 | } 19 | } 20 | 21 | public static List> nQueensBruteForce(int dim, int N) { 22 | List> results = new LinkedList>(); 23 | nQueensBruteForce(dim, N, 0, 0, new LinkedList(), results); 24 | return results; 25 | } 26 | 27 | private static void nQueensBruteForce(int dim, int N, int row, int col, 28 | List path, List> results) { 29 | if (path.size() == N) { 30 | results.add(new LinkedList(path)); 31 | return; 32 | } 33 | if (row == dim || col == dim) return; 34 | 35 | path.add(new Cell(row, col)); 36 | nQueensBruteForce(dim, N, row, col+1, path, results); 37 | nQueensBruteForce(dim, N, row+1, 0, path, results); 38 | 39 | path.remove(path.size() - 1); 40 | nQueensBruteForce(dim, N, row, col+1, path, results); 41 | nQueensBruteForce(dim, N, row+1, 0, path, results); 42 | } 43 | 44 | public static List> nQueensOptimized(int dim, int N) { 45 | List> results = new LinkedList>(); 46 | Set availableCols = new HashSet(); 47 | for (int i = 0; i < dim; i++) availableCols.add(i); 48 | nQueensOptimized(dim, N, 0, availableCols, new HashSet(), 49 | new HashSet(), new LinkedList(), results); 50 | return results; 51 | } 52 | 53 | private static void nQueensOptimized(int dim, int N, int row, Set availableCols, 54 | Set leftDiagonals, Set rightDiagonals, 55 | List path, List> results) { 56 | if (path.size() == N) { 57 | results.add(new LinkedList(path)); 58 | return; 59 | } 60 | 61 | if (row >= dim) return; 62 | 63 | for (Integer col : availableCols.toArray(new Integer[]{})) { 64 | if (leftDiagonals.contains(row - col) || rightDiagonals.contains(row + col)) continue; 65 | path.add(new Cell(row, col)); 66 | availableCols.remove(col); 67 | leftDiagonals.add(row - col); 68 | rightDiagonals.add(row + col); 69 | 70 | nQueensOptimized(dim, N, row+1, availableCols, leftDiagonals, rightDiagonals, path, results); 71 | 72 | path.remove(path.size() - 1); 73 | availableCols.add(col); 74 | leftDiagonals.remove(row - col); 75 | rightDiagonals.remove(row + col); 76 | } 77 | 78 | nQueensOptimized(dim, N, row+1, availableCols, leftDiagonals, rightDiagonals, path, results); 79 | } 80 | 81 | public static void main(String[] args) { 82 | System.out.println(nQueensOptimized(8 ,8)); 83 | } 84 | } -------------------------------------------------------------------------------- /java/Parentheses.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class Parentheses { 5 | public static List parentheses(String s) { 6 | if (s.length() == 1) { 7 | List result = new LinkedList(); 8 | result.add(s); 9 | return result; 10 | } 11 | 12 | List results = new LinkedList(); 13 | 14 | for (int i = 1; i < s.length(); i++) { 15 | List left = parentheses(s.substring(0, i)); 16 | List right = parentheses(s.substring(i, s.length())); 17 | 18 | for (String s1 : left) { 19 | for (String s2 : right) { 20 | results.add("(" + s1 + s2 + ")"); 21 | } 22 | } 23 | } 24 | 25 | return results; 26 | } 27 | 28 | public static void main(String[] args) { 29 | // System.out.println(parentheses("abc")); 30 | System.out.println(parentheses("abcdefghijkl").size()); 31 | } 32 | } -------------------------------------------------------------------------------- /java/Permutations.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.HashSet; 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public class Permutations { 8 | public static List> permutations(Set items) { 9 | List> results = new LinkedList>(); 10 | permutations(items, new LinkedList(), results); 11 | return results; 12 | } 13 | 14 | private static void permutations(Set items, List path, 15 | List> results) { 16 | if (items.isEmpty()) { 17 | results.add(new LinkedList(path)); 18 | return; 19 | } 20 | 21 | for (Integer i : items.toArray(new Integer[]{})) { 22 | items.remove(i); 23 | path.add(i); 24 | permutations(items, path, results); 25 | items.add(i); 26 | path.remove(path.size() - 1); 27 | } 28 | } 29 | 30 | public static List> permutationsSwap(int[] items) { 31 | List> results = new LinkedList>(); 32 | permutationsSwap(items, 0, new LinkedList(), results); 33 | return results; 34 | } 35 | 36 | private static void permutationsSwap(int[] items, int i, List path, 37 | List> results) { 38 | if (i == items.length) { 39 | results.add(new LinkedList(path)); 40 | return; 41 | } 42 | 43 | for (int j = i; j < items.length; j++) { 44 | swap(items, i, j); 45 | path.add(items[i]); 46 | permutationsSwap(items, i+1, path, results); 47 | swap(items, i, j); 48 | path.remove(path.size() - 1); 49 | } 50 | } 51 | 52 | private static void swap(int[] items, int i, int j) { 53 | int temp = items[i]; 54 | items[i] = items[j]; 55 | items[j] = temp; 56 | } 57 | 58 | public static void main(String[] args) { 59 | System.out.println(permutations(new HashSet(Arrays.asList(new Integer[]{1,2,3})))); 60 | System.out.println(permutationsSwap(new int[]{1,2,3})); 61 | } 62 | } -------------------------------------------------------------------------------- /java/PermutationsOfLength.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.HashSet; 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public class PermutationsOfLength { 8 | public static List> permutationsOfSetLength(Set items, int length) { 9 | if (length > items.size()) return null; 10 | List> results = new LinkedList>(); 11 | permutationsOfSetLength(items, length, new LinkedList(), results); 12 | return results; 13 | } 14 | 15 | private static void permutationsOfSetLength(Set items, int length, List path, 16 | List> results) { 17 | if (length == 0) { 18 | results.add(new LinkedList(path)); 19 | return; 20 | } 21 | 22 | for (Integer i : items.toArray(new Integer[]{})) { 23 | items.remove(i); 24 | path.add(i); 25 | permutationsOfSetLength(items, length - 1, path, results); 26 | items.add(i); 27 | path.remove(path.size() - 1); 28 | } 29 | } 30 | 31 | public static void main(String[] args) { 32 | System.out.println(permutationsOfSetLength(new HashSet(Arrays.asList(new Integer[]{1,2,3})), 2)); 33 | } 34 | } -------------------------------------------------------------------------------- /java/PermutationsWithDuplicates.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.HashMap; 3 | import java.util.HashSet; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | public class PermutationsWithDuplicates { 10 | public static List> permutationsWithDuplicates(List items) { 11 | List> results = new LinkedList>(); 12 | HashMap itemCounts = new HashMap(); 13 | for (int i : items) { 14 | if (itemCounts.containsKey(i)) { 15 | itemCounts.put(i, itemCounts.get(i) + 1); 16 | } else { 17 | itemCounts.put(i, 1); 18 | } 19 | } 20 | permutationsWithDuplicates(itemCounts, new LinkedList(), results); 21 | return results; 22 | } 23 | 24 | private static void permutationsWithDuplicates(Map itemCounts, List path, 25 | List> results) { 26 | if (itemCounts.isEmpty()) { 27 | results.add(new LinkedList(path)); 28 | return; 29 | } 30 | 31 | for (Integer i : new HashSet(itemCounts.keySet())) { 32 | int curr = itemCounts.get(i); 33 | if (curr == 1) { 34 | itemCounts.remove(i); 35 | } else { 36 | itemCounts.put(i, curr - 1); 37 | } 38 | 39 | path.add(i); 40 | permutationsWithDuplicates(itemCounts, path, results); 41 | itemCounts.put(i, curr); 42 | path.remove(path.size() - 1); 43 | } 44 | } 45 | 46 | public static void main(String[] args) { 47 | System.out.println(permutationsWithDuplicates(Arrays.asList(new Integer[]{1,1,1,1,1}))); 48 | } 49 | } -------------------------------------------------------------------------------- /java/PrintReversedLinkedList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Print Reversed Linked List 3 | * Author: Sam Gavis-Hughson 4 | * Date: 2/15/19 5 | * 6 | * Given a linked list, write a function to print the values of the linked list 7 | * in reverse order 8 | * 9 | * eg. 10 | * printReverseLinkedList(1 -> 2 -> 3 -> 4 -> null) 11 | * 4 12 | * 3 13 | * 2 14 | * 1 15 | * 16 | * Execution: javac PrintReversedLinkedList.java && java PrintReversedLinkedList 17 | */ 18 | 19 | import java.util.Stack; 20 | 21 | public class PrintReversedLinkedList { 22 | public static class Node { 23 | int val; 24 | Node next; 25 | 26 | public Node(int n) { 27 | this.val = n; 28 | } 29 | } 30 | 31 | // Recursively print linked list in reverse order 32 | public static void printReversedLinkedList(Node head) { 33 | // If we reach the end of the list, return 34 | if (head == null) return; 35 | 36 | // Otherwise first recurse to the end and then print as we return 37 | printReversedLinkedList(head.next); 38 | System.out.println(head.val); 39 | } 40 | 41 | // Iteratively print linked list in reverse using a stack 42 | public static void printReversedLinkedListIterative(Node head) { 43 | // Add all the items to a LIFO stack 44 | Stack s = new Stack(); 45 | while (head != null) { 46 | s.push(head); 47 | head = head.next; 48 | } 49 | 50 | // Pop everything from the stack and print 51 | while (!s.isEmpty()) { 52 | System.out.println(s.pop()); 53 | } 54 | } 55 | 56 | public static void main(String[] args) { 57 | Node list = new Node(1); 58 | list.next = new Node(2); 59 | list.next.next = new Node(3); 60 | list.next.next.next = new Node(4); 61 | 62 | printReversedLinkedList(list); 63 | } 64 | } -------------------------------------------------------------------------------- /java/RotatedArray.java: -------------------------------------------------------------------------------- 1 | public class RotatedArray { 2 | public static int findMin(int[] arr) { 3 | return findMin(arr, 0, arr.length-1); 4 | } 5 | 6 | private static int findMin(int[] arr, int min, int max) { 7 | if (arr[min] < arr[max]) return min; 8 | if (min+1 == max) return max; 9 | 10 | int mid = (min + max) / 2; 11 | if (arr[min] < arr[mid]) return findMin(arr, mid, max); 12 | return findMin(arr, min, mid); 13 | } 14 | 15 | public static void main(String[] args) { 16 | System.out.println(findMin(new int[]{1,2,3,4})); 17 | System.out.println(findMin(new int[]{1,2,3,4,5,6})); 18 | System.out.println(findMin(new int[]{2,3,4,5,6,1})); 19 | System.out.println(findMin(new int[]{3,4,5,6,1,2})); 20 | System.out.println(findMin(new int[]{4,5,6,1,2,3})); 21 | System.out.println(findMin(new int[]{5,6,1,2,3,4})); 22 | System.out.println(findMin(new int[]{6,1,2,3,4,5})); 23 | } 24 | } -------------------------------------------------------------------------------- /java/SeatingArrangement.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.HashSet; 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | 9 | public class SeatingArrangement { 10 | public static List> arrangements(int N, Map pairs) { 11 | Set remaining = new HashSet(); 12 | for (int i = 1; i <= N; i++) remaining.add(i); 13 | List> results = new LinkedList>(); 14 | arrangements(remaining, pairs, new LinkedList(), results); 15 | return results; 16 | } 17 | 18 | private static void arrangements(Set remaining, Map pairs, 19 | List path, List> results) { 20 | if (remaining.isEmpty()) { 21 | results.add(new LinkedList(path)); 22 | return; 23 | } 24 | 25 | for (Integer i : remaining.toArray(new Integer[]{})) { 26 | remaining.remove(i); 27 | path.add(i); 28 | 29 | Integer j = pairs.get(i); 30 | if (j != null) { 31 | remaining.remove(j); 32 | path.add(j); 33 | } 34 | 35 | arrangements(remaining, pairs, path, results); 36 | 37 | remaining.add(i); 38 | path.remove(path.size() - 1); 39 | 40 | if (j != null) { 41 | remaining.add(j); 42 | path.remove(path.size() - 1); 43 | } 44 | } 45 | } 46 | 47 | public static void main(String[] args) { 48 | Map pairs = new HashMap(); 49 | pairs.put(1, 3); 50 | pairs.put(3, 1); 51 | 52 | System.out.println(arrangements(3, pairs)); 53 | } 54 | } -------------------------------------------------------------------------------- /java/SortedPermutations.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.List; 3 | import java.util.LinkedList; 4 | 5 | public class SortedPermutations { 6 | public static List> sortedPermutations(int[] arr) { 7 | Arrays.sort(arr); 8 | return Permutations.permutationsSwap(arr); 9 | } 10 | 11 | public static void main(String[] args) { 12 | System.out.println(sortedPermutations(new int[]{3,2,1})); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /java/SquareSubmatrix.java: -------------------------------------------------------------------------------- 1 | public class SquareSubmatrix { 2 | // Brute force solution 3 | public static int squareSubmatrix(boolean[][] arr) { 4 | int max = 0; 5 | // Compute recursively for each cell what it is the upper left corner of 6 | for (int i = 0; i < arr.length; i++) { 7 | for (int j = 0; j < arr[0].length; j++) { 8 | max = Math.max(max, squareSubmatrix(arr, i, j)); 9 | } 10 | } 11 | 12 | return max; 13 | } 14 | 15 | // Overloaded recursive function 16 | private static int squareSubmatrix(boolean[][] arr, int i, int j) { 17 | // If we get to the bottom or right of the matrix, we can't go any 18 | // further 19 | if (i == arr.length || j == arr[0].length) return 0; 20 | 21 | // If the cell is False then it is not part of a valid submatrix 22 | if (!arr[i][j]) return 0; 23 | 24 | // Find the size of the right, bottom, and bottom right submatrices and 25 | // add 1 to the minimum of those 3 to get the result 26 | return 1 + Math.min(Math.min(squareSubmatrix(arr, i+1, j), 27 | squareSubmatrix(arr, i, j+1)), 28 | squareSubmatrix(arr, i+1, j+1)); 29 | } 30 | 31 | public static void main(String[] args) { 32 | System.out.println(squareSubmatrix(new boolean[][]{ 33 | new boolean[]{true, true, true, false}, 34 | new boolean[]{false, true, true, true}, 35 | new boolean[]{true, true, true, true}})); 36 | } 37 | } -------------------------------------------------------------------------------- /java/StairStep.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Stair Step 3 | * Author: Sam Gavis-Hughson 4 | * Date: 11/1/2018 5 | * 6 | * Given a height of a staircase, n, determine the number of ways you can reach 7 | * the top by taking steps of size 1, 2, or 3. 8 | * 9 | * Execution: javac StairStep.java && java StairStep 10 | */ 11 | 12 | import java.util.LinkedList; 13 | import java.util.List; 14 | 15 | public class StairStep { 16 | 17 | // Count the number of ways up the staircase 18 | public static int stairStepCount(int n) { 19 | // If n==0, we're at the top, so there's one way. If n<0, we've passed 20 | // the top, so there are no valid paths 21 | if (n == 0) return 1; 22 | if (n < 0) return 0; 23 | 24 | // Find all the ways if you took 1, 2, or 3 steps from the current position 25 | return stairStepCount(n-1) + stairStepCount(n-2) + stairStepCount(n-3); 26 | } 27 | 28 | // Find a list of all of the paths up the staircase 29 | public static List> stairStep(int n) { 30 | // We have one valid path, which is to take no steps from where we are 31 | if (n == 0) { 32 | List> result = new LinkedList>(); 33 | result.add(new LinkedList()); 34 | return result; 35 | } 36 | 37 | // We have no valid paths 38 | if (n < 0) { 39 | return new LinkedList>(); 40 | } 41 | 42 | // Try taking 1, 2, or 3 steps from where we are and find all those paths 43 | List> result = 44 | new LinkedList>(stairStep(n-1)); 45 | result.addAll(stairStep(n-2)); 46 | result.addAll(stairStep(n-3)); 47 | 48 | // Since we stepped from our current step, include the current step in 49 | // the path. 50 | for (List l : result) { 51 | l.add(n); 52 | } 53 | 54 | return result; 55 | } 56 | 57 | // Similar implementation that counts up rather than counting down 58 | public static List> stairStep2(int n) { 59 | return stairStep2(n, 0); 60 | } 61 | 62 | // Inner recursive function 63 | private static List> stairStep2(int n, int currentStep) { 64 | if (currentStep == n) { 65 | List> result = new LinkedList>(); 66 | result.add(new LinkedList()); 67 | return result; 68 | } 69 | if (currentStep > n) { 70 | return new LinkedList>(); 71 | } 72 | 73 | List> result = new LinkedList>(); 74 | result.addAll(stairStep2(n, currentStep+1)); 75 | result.addAll(stairStep2(n, currentStep+2)); 76 | result.addAll(stairStep2(n, currentStep+3)); 77 | 78 | // We are generating the list from step X to the top of the staircase, 79 | // so we insert the current step at the beginning of the list 80 | for (List l : result) { 81 | l.add(0, currentStep); 82 | } 83 | 84 | return result; 85 | } 86 | 87 | // Sample test cases 88 | public static void main(String[] args) { 89 | System.out.println(stairStep2(3)); 90 | System.out.println(stairStep2(4)); 91 | System.out.println(stairStep2(5)); 92 | } 93 | } -------------------------------------------------------------------------------- /java/Sublists.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.LinkedList; 3 | import java.util.List; 4 | 5 | public class Sublists { 6 | public static List> sublistsIterative(List l) { 7 | List> result = new LinkedList>(); 8 | for (int i = 0; i < l.size(); i++) { 9 | for (int j = 0; j < i; j++) { 10 | result.add(new LinkedList(l.subList(j, i))); 11 | } 12 | } 13 | return result; 14 | } 15 | 16 | public static List> sublistsRecursive(List l) { 17 | List> result = new LinkedList>(); 18 | sublistsRecursive(l, 0, result); 19 | return result; 20 | } 21 | 22 | private static void sublistsRecursive(List l, int i, List> result) { 23 | if (i >= l.size()) return; 24 | sublistsRecursiveInner(l, i, 0, result); 25 | sublistsRecursive(l, i+1, result); 26 | } 27 | 28 | private static void sublistsRecursiveInner(List l, int i, int j, List> result) { 29 | if (j >= i) return; 30 | result.add(new LinkedList(l.subList(j, i))); 31 | sublistsRecursiveInner(l, i, j+1, result); 32 | } 33 | 34 | public static void main(String[] args) { 35 | System.out.println(sublistsIterative(Arrays.asList(1,2,3,4,5))); 36 | System.out.println(sublistsRecursive(Arrays.asList(1,2,3,4,5))); 37 | } 38 | } -------------------------------------------------------------------------------- /java/Substrings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Substrings 3 | * Author: Sam Gavis-Hughson 4 | * Date: 11/1/2018 5 | * 6 | * Given a String, write a function that returns a list of all of the substrings. 7 | * 8 | * substrings("abcd") = {"a", "ab", "abc", "abcd", "b", "bc", "bcd", "c", "cd", "d"} 9 | * 10 | * Execution: javac Substrings.java && java Substrings 11 | */ 12 | 13 | import java.util.LinkedList; 14 | import java.util.List; 15 | 16 | public class Substrings { 17 | 18 | // Iteratively generate all substrings using a nested for loop 19 | public static List substringsIterative(String s) { 20 | List result = new LinkedList(); 21 | // Iterate over possible starting indices 22 | for (int i = 0; i < s.length(); i++) { 23 | // Iterate over possible ending indices 24 | for (int j = i+1; j <= s.length(); j++) { 25 | result.add(s.substring(i, j)); 26 | } 27 | } 28 | 29 | return result; 30 | } 31 | 32 | // Recursively generate all substrings using one recursive function for each 33 | // for loop 34 | public static List substringsRecursive(String s) { 35 | List result = new LinkedList(); 36 | substringsRecursive(s, 0, result); 37 | return result; 38 | } 39 | 40 | // Recursively iterate over all possible starting characters 41 | private static void substringsRecursive(String s, int i, List result) { 42 | if (i >= s.length()) return; 43 | substringsRecursiveInner(s, i, i+1, result); 44 | substringsRecursive(s, i+1, result); 45 | } 46 | 47 | // Recursively iterate over all possible ending characters 48 | private static void substringsRecursiveInner(String s, int i, int j, List result) { 49 | if (j > s.length()) return; 50 | result.add(s.substring(i, j)); 51 | substringsRecursiveInner(s, i, j+1, result); 52 | } 53 | 54 | // Recursively generate all substrings with a single recursive function. We 55 | // increment either i or j but have to make sure that we don't include the 56 | // same substring multiple times 57 | public static List substringsRecursive2(String s) { 58 | List result = new LinkedList(); 59 | substringsRecursive2(s, 0, 1, result); 60 | return result; 61 | } 62 | 63 | // Inner recursive function 64 | private static void substringsRecursive2(String s, int i, int j, List result) { 65 | if (i >= s.length() || j > s.length()) return; 66 | 67 | // This condition ensures that we only include each substring once. 68 | // There are many options here. i+1 == j also works 69 | if (j == s.length()) substringsRecursive2(s, i+1, i+2, result); 70 | substringsRecursive2(s, i, j+1, result); 71 | 72 | result.add(s.substring(i, j)); 73 | } 74 | 75 | // Sample test cases 76 | public static void main(String[] args) { 77 | System.out.println(substringsIterative("abcd")); 78 | System.out.println(substringsRecursive2("abcd")); 79 | } 80 | } -------------------------------------------------------------------------------- /java/TargetSum.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | public class TargetSum { 5 | public static List> targetSum(int[] arr, int target) { 6 | List> results = new LinkedList>(); 7 | targetSum(arr, target, 0, new LinkedList(), results); 8 | return results; 9 | } 10 | 11 | private static void targetSum(int[] arr, int target, int i, List path, List> results) { 12 | if (target < 0) return; 13 | if (target == 0) { 14 | results.add(new LinkedList(path)); 15 | return; 16 | } 17 | 18 | if (i == arr.length) return; 19 | 20 | path.add(arr[i]); 21 | targetSum(arr, target-arr[i], i, path, results); 22 | path.remove(path.size() - 1); 23 | targetSum(arr, target, i+1, path, results); 24 | } 25 | 26 | public static void main(String[] args) { 27 | System.out.println(targetSum(new int[]{1,2,3}, 4)); 28 | } 29 | } -------------------------------------------------------------------------------- /java/TowersOfHanoi.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Towers of Hanoi 3 | * Author: Sam Gavis-Hughson 4 | * Date: 11/1/2018 5 | * 6 | * Given a number of disks, write a function to find the set of moves needed to 7 | * solve the Towers of Hanoi puzzle 8 | * https://en.wikipedia.org/wiki/Tower_of_Hanoi 9 | * 10 | * Execution: javac TowersOfHanoi.java && java TowersOfHanoi 11 | */ 12 | 13 | import java.util.Arrays; 14 | import java.util.LinkedList; 15 | import java.util.List; 16 | 17 | public class TowersOfHanoi { 18 | 19 | // Enum for each of the 3 positions that a disk can be in. This enum also 20 | // contains toString() methods to make printing easier 21 | public enum Position { 22 | SRC { 23 | public String toString() { return "SRC"; } 24 | }, 25 | DEST { 26 | public String toString() { return "DEST"; } 27 | }, 28 | AUX { 29 | public String toString() { return "AUX"; } 30 | }; 31 | } 32 | 33 | // Recursively count the number of moves to move n disks. If there is 1 34 | // disk, it takes 1 move. Otherwise, move n-1 disks to AUX, then bottom disk 35 | // to DEST, then n-1 disks from AUX to DEST 36 | public static int moveCount(int n) { 37 | // 0 or negative disks take 0 moves, one disk only takes one move 38 | if (n <= 0) return 0; 39 | if (n == 1) return 1; 40 | 41 | // Count the number of moves to move n-1 disks to AUX and then to DEST 42 | return 2 * moveCount(n-1) + 1; 43 | } 44 | 45 | // Simple move class to simplify code 46 | public static class Move { 47 | int disk; 48 | Position src; 49 | Position dest; 50 | 51 | public Move(int disk, Position src, Position dest) { 52 | this.disk = disk; 53 | this.src = src; 54 | this.dest = dest; 55 | } 56 | 57 | public String toString() { 58 | return "" + disk + " from " + src + " to " + dest; 59 | } 60 | } 61 | 62 | // Recursively compute the list of moves required to move n disks 63 | public static List moves(int n) { 64 | return moves(n, Position.SRC, Position.DEST, Position.AUX); 65 | } 66 | 67 | // Recursive inner function 68 | private static List moves(int n, Position src, Position dest, Position aux) { 69 | // If we have 0 or negative disks, no moves. If we have one disk, just 70 | // move it directly to DEST 71 | if (n <= 0) return new LinkedList(); 72 | if (n == 1) return Arrays.asList(new Move(n, src, dest)); 73 | 74 | // Move the n-1 disks to AUX, then the n disk to DEST, then n-1 from 75 | // AUX to DEST. We simply append the moves required to do each. 76 | List result = new LinkedList(); 77 | result.addAll(moves(n-1, src, aux, dest)); 78 | result.add(new Move(n, src, dest)); 79 | result.addAll(moves(n-1, aux, dest, src)); 80 | return result; 81 | } 82 | 83 | // Sample test cases 84 | public static void main(String[] args) { 85 | System.out.println(moveCount(5)); 86 | System.out.println(moves(5)); 87 | } 88 | } -------------------------------------------------------------------------------- /java/TreeDiameter.java: -------------------------------------------------------------------------------- 1 | import java.util.Collections; 2 | import java.util.HashMap; 3 | import java.util.List; 4 | import java.util.LinkedList; 5 | import java.util.Map; 6 | 7 | public class TreeDiameter { 8 | public static class Node { 9 | int value; 10 | Node left; 11 | Node right; 12 | 13 | public Node(int value) { 14 | this.value = value; 15 | } 16 | 17 | public String toString() { 18 | return "" + value; 19 | } 20 | } 21 | 22 | public static int diameterBruteForce(Node root) { 23 | if (root == null) return 0; 24 | 25 | int currentDiameter = 1 + height(root.left) + height(root.right); 26 | 27 | return Math.max(currentDiameter, Math.max(diameterBruteForce(root.left), 28 | diameterBruteForce(root.right))); 29 | } 30 | 31 | private static int height(Node root) { 32 | if (root == null) return 0; 33 | 34 | return 1 + Math.max(height(root.left), height(root.right)); 35 | } 36 | 37 | public static int diameterOptimized(Node root) { 38 | Map allHeights = new HashMap(); 39 | allHeights(root, allHeights); 40 | return diameterOptimized(root, allHeights); 41 | } 42 | 43 | private static int diameterOptimized(Node root, Map heights) { 44 | if (root == null) return 0; 45 | 46 | int leftHeight = root.left == null ? 0 : heights.get(root.left); 47 | int rightHeight = root.right == null ? 0 : heights.get(root.right); 48 | 49 | return Math.max(1 + leftHeight + rightHeight, 50 | Math.max(diameterOptimized(root.left, heights), 51 | diameterOptimized(root.right, heights))); 52 | } 53 | 54 | private static int allHeights(Node root, Map heights) { 55 | if (root == null) return 0; 56 | int height = 1+ Math.max(allHeights(root.left, heights), allHeights(root.right, heights)); 57 | heights.put(root, height); 58 | return height; 59 | } 60 | 61 | public static class Height { 62 | int height; 63 | 64 | public Height() { 65 | this.height = 0; 66 | } 67 | } 68 | 69 | public static int diameterSpaceOptimized(Node root) { 70 | return diameterSpaceOptimized(root, new Height()); 71 | } 72 | 73 | private static int diameterSpaceOptimized(Node root, Height h) { 74 | if (root == null) return 0; 75 | 76 | Height heightLeft = new Height(); 77 | Height heightRight = new Height(); 78 | 79 | int diamLeft = diameterSpaceOptimized(root.left, heightLeft); 80 | int diamRight = diameterSpaceOptimized(root.right, heightRight); 81 | 82 | h.height = 1 + Math.max(heightLeft.height, heightRight.height); 83 | return Math.max(1 + heightLeft.height + heightRight.height, 84 | Math.max(diamLeft, diamRight)); 85 | } 86 | 87 | public static class Path { 88 | List path; 89 | 90 | public Path() { 91 | this.path = new LinkedList(); 92 | } 93 | } 94 | 95 | public static List diameterList(Node root) { 96 | return diameterList(root, new Path()); 97 | } 98 | 99 | private static List diameterList(Node root, Path path) { 100 | if (root == null) return new LinkedList(); 101 | 102 | Path leftPath = new Path(); 103 | Path rightPath = new Path(); 104 | 105 | List diamLeft = diameterList(root.left, leftPath); 106 | List diamRight = diameterList(root.right, rightPath); 107 | 108 | List result = diamLeft; 109 | if (diamRight.size() > result.size()) result = diamRight; 110 | if (leftPath.path.size() + rightPath.path.size() + 1 > result.size()) { 111 | result = new LinkedList(); 112 | result.addAll(leftPath.path); 113 | Collections.reverse(result); 114 | result.add(root); 115 | result.addAll(rightPath.path); 116 | } 117 | 118 | if (leftPath.path.size() > rightPath.path.size()) path.path = leftPath.path; 119 | else path.path = rightPath.path; 120 | 121 | path.path.add(0, root); 122 | 123 | return result; 124 | } 125 | 126 | public static void main(String[] args) { 127 | Node root = new Node(1); 128 | root.left = new Node(2); 129 | root.right = new Node(3); 130 | root.left.left = new Node(4); 131 | root.left.right = new Node(5); 132 | root.left.left = new Node(6); 133 | root.left.right = new Node(7); 134 | root.left.right.left = new Node(8); 135 | System.out.println(diameterList(root)); 136 | } 137 | } -------------------------------------------------------------------------------- /java/TreeNextNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNextNode { 2 | public static class Node { 3 | int value; 4 | Node left; 5 | Node right; 6 | Node next; 7 | 8 | public Node(int value) { 9 | this.value = value; 10 | } 11 | } 12 | 13 | public static void linkNextNode(Node root) { 14 | if (root == null) return; 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /java/TreeToLinkedList.java: -------------------------------------------------------------------------------- 1 | public class TreeToLinkedList { 2 | public static class Node { 3 | int value; 4 | Node next; 5 | Node prev; 6 | 7 | public Node(int value) { 8 | this.value = value; 9 | } 10 | 11 | public String toString() { 12 | return "{" + value + ", prev=" + prev.value + ", next=" + next.value + "}"; 13 | } 14 | } 15 | 16 | public static Node treeToLinkedList(Node root) { 17 | if (root == null) return null; 18 | 19 | Node left = treeToLinkedList(root.prev); 20 | Node right = treeToLinkedList(root.next); 21 | 22 | root.prev = root; 23 | root.next = root; 24 | 25 | if (left != null) root = connectLists(left, root); 26 | if (right != null) root = connectLists(root, right); 27 | 28 | return root; 29 | } 30 | 31 | private static Node connectLists(Node l1, Node l2) { 32 | Node l1End = l1.prev; 33 | Node l2End = l2.prev; 34 | 35 | l1End.next = l2; 36 | l2.prev = l1End; 37 | l2End.next = l1; 38 | l1.prev = l2End; 39 | 40 | return l1; 41 | } 42 | 43 | public static void main(String[] args) { 44 | Node[] tree = new Node[]{new Node(1), new Node(2), new Node(3), new Node(4), new Node(5)}; 45 | Node root = tree[0]; 46 | root.prev = tree[1]; 47 | root.next = tree[2]; 48 | root.prev.next = tree[3]; 49 | root.next.prev = tree[4]; 50 | 51 | /* 52 | * 1 53 | * / \ 54 | * 2 3 55 | * \ / 56 | * 4 5 57 | * 58 | * - 2 - 4 - 1 - 5 - 3 - 59 | * 60 | */ 61 | 62 | treeToLinkedList(root); 63 | for (Node n : tree) System.out.println(n); 64 | } 65 | } -------------------------------------------------------------------------------- /java/UniqueBSTs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Title: Unique BSTs 3 | * Author: Sam Gavis-Hughson 4 | * Date: 2/15/19 5 | * 6 | * Given a number of items, determine the number of different unique BSTs you 7 | * can generate using that set of inputs 8 | * 9 | * eg. 10 | * countBSTs(4) = 14 11 | * 12 | * Execution: javac UniqueBSTs.java && java UniqueBSTs 13 | */ 14 | 15 | import java.util.Arrays; 16 | import java.util.LinkedList; 17 | import java.util.List; 18 | 19 | public class UniqueBSTs { 20 | 21 | // Count the number of unique BSTs 22 | public static int countBSTs(int n) { 23 | // If a tree has 0 or 1 node, there's exactly 1 unique tree we can make 24 | if (n <= 1) return 1; 25 | int count = 0; 26 | 27 | // Try selecting each possible root and then finding the number of 28 | // combinatinos on the left side and on the right side 29 | for (int i = 0; i < n; i++) { 30 | count += countBSTs(i) * countBSTs(n-i-1); 31 | } 32 | 33 | return count; 34 | } 35 | 36 | // Find all unique BSTs 37 | public static List> uniqueBSTs(int n) { 38 | return uniqueBSTs(0, n); 39 | } 40 | 41 | // Recursive inner function 42 | private static List> uniqueBSTs(int min, int max) { 43 | // If min and max are equal, subtree has a single node 44 | if (min == max) { 45 | List> temp = new LinkedList>(); 46 | temp.add(Arrays.asList(min)); 47 | return temp; 48 | } 49 | 50 | // Try each possible root node 51 | List> result = new LinkedList>(); 52 | for (int i = min; i < max; i++) { 53 | // Get the order for the left subtree and the order for the right 54 | List> left = uniqueBSTs(min, i); 55 | List> right = uniqueBSTs(i+1, max); 56 | 57 | // Merge every combination of left subtree and right subtree 58 | for (List l1 : left) { 59 | for (List l2 : right) { 60 | List temp = new LinkedList(); 61 | temp.add(i); 62 | temp.addAll(l1); 63 | temp.addAll(l2); 64 | result.add(temp); 65 | } 66 | } 67 | } 68 | 69 | return result; 70 | } 71 | 72 | public static void main(String[] args) { 73 | System.out.println(countBSTs(3)); 74 | System.out.println(countBSTs(4)); 75 | } 76 | } -------------------------------------------------------------------------------- /java/WordBreak.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.HashSet; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | 9 | public class WordBreak { 10 | public static List wordBreak(String s, Set dict) { 11 | List results = new LinkedList(); 12 | wordBreak(new ArrayList(), s, dict, results); 13 | return results; 14 | } 15 | 16 | private static void wordBreak(List curr, String remainder, 17 | Set dict, List results) { 18 | if (remainder.length() == 0) { 19 | StringBuilder sb = new StringBuilder(); 20 | for (int i = 0; i < curr.size() - 1; i++) { 21 | sb.append(curr.get(i) + " "); 22 | } 23 | sb.append(curr.get(curr.size() - 1)); 24 | results.add(sb.toString()); 25 | return; 26 | } 27 | 28 | for (int i = 1; i <= remainder.length(); i++) { 29 | String substr = remainder.substring(0, i); 30 | if (dict.contains(substr)) { 31 | curr.add(substr); 32 | wordBreak(curr, remainder.substring(i, remainder.length()), dict, results); 33 | curr.remove(curr.size() - 1); 34 | } 35 | } 36 | } 37 | 38 | public static void main(String[] args) { 39 | System.out.println(wordBreak("catsanddog", 40 | new HashSet(Arrays.asList("cat", "cats", "and", "sand", "dog")))); 41 | } 42 | } -------------------------------------------------------------------------------- /python3/AllBSTOrders.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self): 3 | self.val = None 4 | self.left = None 5 | self.right = None 6 | 7 | class ALLBSTOrders: 8 | 9 | def all_BST_orders_DC(self, root): 10 | if not root: 11 | to_return = [] 12 | to_return.append([]) 13 | return to_return 14 | 15 | left = self.all_BST_orders_DC(root.left) 16 | right = self.all_BST_orders_DC(root.right) 17 | 18 | merged = self.merge_all(left, right) 19 | 20 | for l in merged: 21 | l.insert(0, root.val) 22 | 23 | return merged 24 | 25 | def merge_all(self, first, second): 26 | result = [] 27 | for f in first: 28 | for s in second: 29 | self.merge(f,s, 0,0, [], result) 30 | return result 31 | 32 | def merge(self, first, second, i, j, path, result): 33 | if i == len(first) and j == len(second): 34 | result.append(path) 35 | return 36 | 37 | if i != len(first): 38 | path.append(first[i]) 39 | self.merge(first, second, i + 1, j, path[:], result) 40 | path.pop() 41 | 42 | if j != len(second): 43 | path.append(second[j]) 44 | self.merge(first, second, i, j + 1, path[:], result) 45 | path.pop() 46 | 47 | def all_bst_orders_ordering(self, root): 48 | results = [] 49 | self.all_bst_orders_ordering_helper(set([root]), [], results) 50 | return results 51 | 52 | def all_bst_orders_ordering_helper(self, available, path, results): 53 | if not available: 54 | results.append(path) 55 | return 56 | 57 | for n in available: 58 | available.remove(n) 59 | if n.left: 60 | available.add(n.left) 61 | if n.right: 62 | available.add(n.right) 63 | path.append(n.val) 64 | 65 | self.all_bst_orders_ordering_helper(available, path[:], results) 66 | 67 | path.pop() 68 | if n.left: 69 | available.remove(n.left) 70 | if n.right: 71 | available.remove(n.right) 72 | available.add(n) 73 | 74 | test = ALLBSTOrders() 75 | root = Node() 76 | root.val = 5 77 | root.left = Node() 78 | root.left.val = 3 79 | root.right = Node() 80 | root.right.val = 8 81 | root.left.left = Node() 82 | root.left.left.val = 2 83 | root.left.right = Node() 84 | root.left.right.val = 4 85 | print(test.all_BST_orders_DC(root)) 86 | print(test.all_bst_orders_ordering(root)) 87 | -------------------------------------------------------------------------------- /python3/ArrayOfArrays.py: -------------------------------------------------------------------------------- 1 | class ArrayOfArrays: 2 | 3 | def array_of_arrays(self, arr): 4 | results = [] 5 | self.array_of_arrays_helper(arr, 0, [], results) 6 | return results 7 | 8 | def array_of_arrays_helper(self, arr, i, path, results): 9 | if i == len(arr): 10 | results.append(path) 11 | return 12 | 13 | for j in arr[i]: 14 | path.append(j) 15 | self.array_of_arrays_helper(arr, i + 1, path[:], results) 16 | path.pop() 17 | 18 | test = ArrayOfArrays() 19 | a_of_a = [[1,2],[3],[4,5]] 20 | print(test.array_of_arrays(a_of_a)) 21 | -------------------------------------------------------------------------------- /python3/Combinations.py: -------------------------------------------------------------------------------- 1 | class Combinations: 2 | 3 | def combinations_global(self,n): 4 | """ 5 | :type n:List[int] 6 | :rtype: void 7 | """ 8 | self.results = [] 9 | self.combinations_global_helper(n, 0, []) 10 | print(self.results) 11 | 12 | def combinations_global_helper(self, n, i, path): 13 | """ 14 | :type n:List[int] 15 | :type i: int 16 | :type path: List[int] 17 | :rtype: void 18 | """ 19 | if i == len(n): 20 | self.results.append(path) 21 | return 22 | 23 | path_with_current = path[:] 24 | path_with_current.append(n[i]) 25 | 26 | # Find all the combinations that exclude current item 27 | self.combinations_global_helper(n, i+1, path) 28 | 29 | # Find all the combinations that include current item 30 | self.combinations_global_helper(n, i+1, path_with_current) 31 | 32 | def combinations_passed(self, n): 33 | """ 34 | :type n: List[int] 35 | :rtype: List[List[int]] 36 | """ 37 | results = [] 38 | self.combinations_passed_helper(n, 0, results, []) 39 | return results 40 | 41 | def combinations_passed_helper(self, n, i, results, path): 42 | """ 43 | :type n:List[int] 44 | :type i: int 45 | :type results: List[List[int]] 46 | :type path: List[int] 47 | :rtype: void 48 | """ 49 | if i == len(n): 50 | results.append(path) 51 | return 52 | 53 | path_with_current = path[:] 54 | path_with_current.append(n[i]) 55 | 56 | # Find all the combinations that exclude current item 57 | self.combinations_passed_helper(n, i+1, results, path) 58 | 59 | # Find all the combinations that include current item 60 | self.combinations_passed_helper(n, i+1, results, path_with_current) 61 | 62 | def combinations_built_up(self, n): 63 | """ 64 | :type n: List[int] 65 | :rtype: List[List[int]] 66 | """ 67 | return self.combinations_built_up_helper(n, 0) 68 | 69 | def combinations_built_up_helper(self, n, i): 70 | """ 71 | :type n:List[int] 72 | :type i: int 73 | :rtype: List[List[int]] 74 | """ 75 | if i == len(n): 76 | to_return = [] 77 | to_return.append([]) 78 | return to_return 79 | 80 | to_return = [] 81 | for result in self.combinations_built_up_helper(n, i+1): 82 | # Exclude current item 83 | to_return.append(result) 84 | 85 | # Include current item 86 | result = [n[i]] + result 87 | to_return.append(result) 88 | 89 | return to_return 90 | 91 | test = Combinations() 92 | combinations = [1,2,3] 93 | test.combinations_global(combinations) 94 | print(test.combinations_passed(combinations)) 95 | print(test.combinations_built_up(combinations)) -------------------------------------------------------------------------------- /python3/CombinationsOfLength.py: -------------------------------------------------------------------------------- 1 | class CombinationsOfLength(): 2 | def combinations_of_length_brute_force(self, n, length): 3 | # the below method is from Combinations.py file 4 | all_combinations = Cominations.combinations_built_up(n) 5 | filtered = [] 6 | for l in all_combinations: 7 | if len(l) == length: 8 | filtered.append(l) 9 | return filtered 10 | 11 | def combinations_of_length_backtracking(self, n, length): 12 | return self.combinations_of_length_backtracking_helper(n, 0, length, 0) 13 | 14 | def combinations_of_length_backtracking_helper(self, n, i, target_length, current_length): 15 | if current_length > target_length: 16 | return [] 17 | 18 | if i == len(n) and current_length != target_length: 19 | return [] 20 | 21 | if i == len(n): 22 | to_return = [] 23 | to_return.append([]) 24 | return to_return 25 | 26 | include = self.combinations_of_length_backtracking_helper(n, i + 1, target_length, current_length + 1) 27 | exclude = self.combinations_of_length_backtracking_helper(n, i + 1, target_length, current_length) 28 | 29 | to_return = [] 30 | 31 | for result in include: 32 | result.insert(0, n[i]) 33 | to_return.append(result) 34 | 35 | to_return.extend(exclude) 36 | 37 | return to_return 38 | 39 | test = CombinationsOfLength() 40 | print(test.combinations_of_length_backtracking([1,2,3,4,5], 3)) 41 | -------------------------------------------------------------------------------- /python3/ConsultantSchedule.py: -------------------------------------------------------------------------------- 1 | Schedule = collections.namedtuple('Schedule', ('schedule','value')) 2 | class ConsultantSchedule(): 3 | def consultant_schedule(self, ny, bos): 4 | new_york = self.consultant_schedule_new_york(ny, bos, 0) 5 | boston = self.consultant_schedule_boston(ny, bos, 0) 6 | if new_york.value > boston.value: 7 | return new_york.schedule 8 | return boston.schedule 9 | 10 | def consultant_schedule_boston(self, ny, bos, i): 11 | if i >= len(ny): 12 | return Schedule("", 0) 13 | 14 | stay = self.consultant_schedule_boston(ny, bos, i + 1) 15 | move = self.consultant_schedule_new_york(ny, bos, i + 1) 16 | 17 | if stay.value + bos[i] > move.value: 18 | return Schedule("B" + stay.schedule, stay.value + bos[i]) 19 | return Schedule("T" + move.schedule, move.value) 20 | 21 | def consultant_schedule_new_york(self, ny, bos, i): 22 | if i >= len(ny): 23 | return Schedule("", 0) 24 | 25 | stay = self.consultant_schedule_boston(ny, bos, i + 1) 26 | move = self.consultant_schedule_new_york(ny, bos, i + 1) 27 | 28 | if stay.value + ny[i] > move.value: 29 | return Schedule("N" + stay.schedule, stay.value + ny[i]) 30 | return Schedule("T" + move.schedule, move.value) 31 | 32 | test = ConsultantSchedule() 33 | print(test.consultant_schedule([1,2,3,4,4,3,2,1], [4,3,2,1,1,2,3,4])) 34 | -------------------------------------------------------------------------------- /python3/DFSGraph.py: -------------------------------------------------------------------------------- 1 | class Node(): 2 | def __init__(self, val=None, neighbors=[]): 3 | self.val = val 4 | self.neighbors = [] 5 | 6 | class DFSGraph(): 7 | 8 | def path_exists(self, src, dest): 9 | return self.path_exists_helper(src, dest, set()) 10 | 11 | def path_exists_helper(self, curr, dest, visited): 12 | if curr in visited: 13 | return False 14 | if curr == dest: 15 | return True 16 | 17 | visited.add(curr) 18 | for n in curr.neighbors: 19 | if self.path_exists_helper(n, dest, visited): 20 | return True 21 | 22 | return False 23 | 24 | def paths(self, src, dest): 25 | results = [] 26 | self.paths_helper(src, dest, set(), [], results) 27 | return results 28 | 29 | def paths_helper(self, curr, dest, visited, path, results): 30 | if curr in visited: 31 | return 32 | if curr == dest: 33 | path.append(curr) 34 | results.append([n.val for n in path]) 35 | path.pop() 36 | return 37 | 38 | visited.add(curr) 39 | path.append(curr) 40 | for n in curr.neighbors: 41 | self.paths_helper(n, dest, visited, path[:], results) 42 | path.pop() 43 | visited.remove(curr) 44 | 45 | test = DFSGraph() 46 | graph = [] 47 | for i in range(6): 48 | node = Node(i) 49 | graph.append(node) 50 | 51 | graph[0].neighbors = [graph[1], graph[2], graph[3]] 52 | graph[1].neighbors = [graph[4], graph[1]] 53 | graph[2].neighbors = [graph[2]] 54 | graph[3].neighbors = [graph[1]] 55 | graph[4].neighbors = [graph[1], graph[2], graph[3]] 56 | graph[5].neighbors = [] 57 | 58 | print(test.paths(graph[0],graph[4])) 59 | -------------------------------------------------------------------------------- /python3/DFSTree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, val, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | def __repr__(self): 8 | return str(self.val) 9 | 10 | class DFSTree(): 11 | def contains(self, root, val): 12 | if not root: 13 | return False 14 | if root.val == val: 15 | return True 16 | return self.contains(root.left, val) or self.contain(root.right, val) 17 | 18 | def path_to_node(self, root, val): 19 | if not root: 20 | return None 21 | if root.val == val: 22 | to_return = [] 23 | to_return.append(root) 24 | return to_return 25 | 26 | left = self.path_to_node(root.left, val) 27 | if left: 28 | left.insert(0, root) 29 | return left 30 | 31 | right = self.path_to_node(root.right, val) 32 | if right: 33 | right.insert(0, root) 34 | return right 35 | 36 | return None 37 | 38 | test = DFSTree() 39 | root = Node(1) 40 | root.left = Node(2); 41 | root.right = Node(3); 42 | root.left.left = Node(4); 43 | root.left.right = Node(5); 44 | root.right.left = Node(6); 45 | root.right.right = Node(7); 46 | print(test.path_to_node(root, 7)) 47 | -------------------------------------------------------------------------------- /python3/Decode.py: -------------------------------------------------------------------------------- 1 | class Decode: 2 | def decode(self,s): 3 | """ 4 | :type s: string 5 | :rtype: List[string] 6 | """ 7 | result = [] 8 | # we are going to use an empty array and join it together, acting in place of StringBuilder 9 | self.decode_helper(s, 0, [], result) 10 | return result 11 | 12 | def decode_helper(self, s, i, curr, result): 13 | """ 14 | :type s: string 15 | :type i: int 16 | :type curr: List[string] 17 | :type result: List[string] 18 | :rtype: void 19 | """ 20 | if i >= len(s): 21 | result.append(''.join(curr)) 22 | return 23 | 24 | for c in self.get_next(s,i): 25 | curr.append(c) 26 | if ord(c) < ord('A') + 10: 27 | self.decode_helper(s, i + 1, curr, result) 28 | else: 29 | self.decode_helper(s, i + 2, curr, result) 30 | del curr[-1] 31 | 32 | def get_next(self, s, i): 33 | """ 34 | :type s: string 35 | :type i: int 36 | :rtype: List[string] 37 | """ 38 | to_return = [] 39 | val = int(s[i:i+1]) 40 | to_return.append(chr(ord('A') + val - 1)) 41 | 42 | if i < len(s)-1: 43 | val = int(s[i:i+2]) 44 | if val <= 26: 45 | to_return.append(chr(ord('A') + val - 1)) 46 | return to_return 47 | 48 | test = Decode() 49 | print(test.decode("223")) 50 | print(test.decode("227")) 51 | print(test.decode("4231123")) -------------------------------------------------------------------------------- /python3/GreatestProductPath.py: -------------------------------------------------------------------------------- 1 | class GreatestProductPath(): 2 | """ 3 | Given an NxN matrix, find the path from (0,0) to (N-1, N-1) by moving either right or down that has the greatest product 4 | """ 5 | def greatest_product_path(matrix): 6 | return self.greatest_product_path_helper(matrix, 0, 0) 7 | 8 | def greatest_product_path_helper(matrix, i, j): 9 | if i == len(matrix)-1 and j == len(matrix[0] -1): 10 | return matrix[i][j] 11 | 12 | if i >= len(matrix) or j >= len(matrix[0]): 13 | return 0 14 | 15 | return matrix[i][j] * max(self.greatest_product_path_helper(matrix, i + 1, j), \ 16 | self.greatest_product_path_helper(matrix, i, j+ 1)) 17 | 18 | def greatest_product_path2(matrix): 19 | result = [] 20 | result.append(-float('inf')) 21 | self.greatest_product_path2_helper(matrix, 0, 0, 1, result) 22 | return result[0] 23 | 24 | def greatest_product_path2_helper(matrix, i, j, product, result): 25 | if i >= len(matrix) or j >= len(matrix[0]): 26 | return 27 | 28 | product *= matrix[i][j] 29 | 30 | if i == len(matrix) - 1 and j == len(matrix[0]) - 1: 31 | if result[0] < product: 32 | result[0] = product 33 | return 34 | 35 | self.greatest_product_path2_helper(matrix, i + 1, j, product, result) 36 | self.greatest_product_path2_helper(matrix, i, j + 1, product, result) 37 | 38 | 39 | def greatest_product_path_built_up(matrix): 40 | return self.greatest_product_path_built_up_helper(matrix, 0, 0)[0] 41 | 42 | def greatest_product_path_built_up_helper(matrix, i, j): 43 | if i >= len(matrix) or j >= len(matrix[0]): 44 | return None 45 | 46 | right = self.greatest_product_path_built_up_helper(matrix, i + 1, j) 47 | down = self.greatest_product_path_built_up_helper(matrix, i, j + 1) 48 | 49 | if not right and not down: 50 | return (matrix[i][j], matrix[i][j]) 51 | 52 | max_val = float('inf') 53 | min_val = -float('inf') 54 | 55 | if right: 56 | max_val = max(max_val, max(right[0] * matrix[i][j], \ 57 | right[1] * matrix[i][j])) 58 | min_val = min(min_val, min(right[0] * matrix[i][j], \ 59 | right[1] * matrix[i][j])) 60 | 61 | if down: 62 | max_val = max(max_val, max(down[0] * matrix[i][j], \ 63 | down[1] * matrix[i][j])) 64 | min_val = min(min_val, min(down[0] * matrix[i][j], \ 65 | down[1] * matrix[i][j])) 66 | 67 | return (max_val, min_val) 68 | 69 | -------------------------------------------------------------------------------- /python3/InsertAtBottom.py: -------------------------------------------------------------------------------- 1 | class InsertAtBottom: 2 | def insert_at_bottom_iterative(self, s, i): 3 | """ 4 | :type s: List[int] 5 | :type i: int 6 | :rtype: void 7 | """ 8 | temp = [] 9 | while s: 10 | temp.append(s.pop()) 11 | s.append(i) 12 | while temp: 13 | s.append(temp.pop()) 14 | 15 | def insert_at_bottom_recursive(self, s, i): 16 | """ 17 | :type s: List[int] 18 | :type i: int 19 | :rtype: void 20 | """ 21 | if not s: 22 | s.append(i) 23 | return 24 | 25 | top = s.pop() 26 | self.insert_at_bottom_recursive(s, i) 27 | s.append(top) 28 | 29 | test = InsertAtBottom() 30 | stack = [1,2,3,4] 31 | test.insert_at_bottom_iterative(stack, 5) 32 | print(stack) 33 | test.insert_at_bottom_recursive(stack, 6) 34 | print(stack) -------------------------------------------------------------------------------- /python3/IsPalindrome.py: -------------------------------------------------------------------------------- 1 | class IsPalindrome: 2 | def is_palindrome(self, s): 3 | """ 4 | :type s: string 5 | :rtype: boolean 6 | """ 7 | if len(s) <= 1: 8 | return True 9 | return s[0] == s[-1] and self.is_palindrome(s[1:-1]) 10 | 11 | test = IsPalindrome() 12 | print(test.is_palindrome("abcba")) 13 | print(test.is_palindrome("abccba")) 14 | print(test.is_palindrome("abcdba")) 15 | print(test.is_palindrome("abccbb")) 16 | print(test.is_palindrome("a")) 17 | print(test.is_palindrome("")) -------------------------------------------------------------------------------- /python3/Iteration.py: -------------------------------------------------------------------------------- 1 | class Iteration: 2 | def print_forward_iterative(self, arr): 3 | """ 4 | :type arr: List[int] 5 | :rtype: void 6 | """ 7 | for i in range(len(arr)): 8 | print(arr[i]) 9 | 10 | def print_forward(self, arr): 11 | """ 12 | :type arr: List[int] 13 | :rtype: void 14 | """ 15 | self.print_forward_helper(arr, 0) 16 | 17 | def print_forward_helper(self, arr, i): 18 | """ 19 | :type arr: List[int] 20 | :type i: int 21 | :rtype: void 22 | """ 23 | if i == len(arr): 24 | return 25 | print(arr[i]) 26 | self.print_forward_helper(arr, i + 1) 27 | 28 | def print_backward_iterative(self, arr): 29 | """ 30 | :type arr: List[int] 31 | :rtype: void 32 | """ 33 | for i in range(len(arr)-1, -1, -1): 34 | print(arr[i]) 35 | 36 | def print_backward(self, arr): 37 | """ 38 | :type arr: List[int] 39 | :rtype: void 40 | """ 41 | self.print_backward_helper(arr, 0) 42 | 43 | def print_backward_helper(self, arr, i): 44 | """ 45 | :type arr: List[int] 46 | :type i: int 47 | :rtype: void 48 | """ 49 | if i == len(arr): 50 | return 51 | self.print_backward_helper(arr, i + 1) 52 | print(arr[i]) 53 | 54 | test = Iteration() 55 | arr = [1,2,3,4,5] 56 | test.print_forward_iterative(arr) 57 | test.print_forward(arr) 58 | 59 | test.print_backward_iterative(arr) 60 | test.print_backward(arr) -------------------------------------------------------------------------------- /python3/LongestIncreasingSubsequence.py: -------------------------------------------------------------------------------- 1 | class LongestIncreasingSubsequence: 2 | def longest_increasing_subsequence(self, l): 3 | return self.longest_increasing_subsequence_helper(l, 0, 0) 4 | 5 | def longest_increasing_subsequence_helper(self, arr, i, curr_min): 6 | if i == len(arr): 7 | return [] 8 | 9 | max_list = self.longest_increasing_subsequence_helper(arr, i + 1, curr_min) 10 | 11 | if arr[i] > curr_min: 12 | includeI = self.longest_increasing_subsequence_helper(arr, i + 1, arr[i]) 13 | includeI.insert(0, arr[i]) 14 | if len(includeI) > len(max_list): 15 | max_list =includeI 16 | 17 | return max_list 18 | 19 | test = LongestIncreasingSubsequence() 20 | l = [9,6,1,5,3,7,55,12] 21 | print("Result: ",test.longest_increasing_subsequence(l)) 22 | -------------------------------------------------------------------------------- /python3/LowestCommonAncestor.py: -------------------------------------------------------------------------------- 1 | class TreeNode: 2 | def __init__(self, val): 3 | self.val = val 4 | self.left = None 5 | self.right = None 6 | 7 | class LowestCommonAncestor: 8 | 9 | def lowestCommonAncestor(self, root, n1, n2): 10 | if not root: 11 | return 12 | 13 | if root.val == n1.val or root.val == n2.val: 14 | return root 15 | 16 | left = self.lowestCommonAncestor(root.left, n1, n2) 17 | 18 | right = self.lowestCommonAncestor(root.right, n1, n2) 19 | 20 | if left and right: 21 | return root 22 | else: 23 | return left or right 24 | 25 | root = TreeNode(1) 26 | root.left = TreeNode(2) 27 | root.left.left = TreeNode(4) 28 | root.left.right = TreeNode(5) 29 | root.right = TreeNode(3) 30 | root.right.left = TreeNode(6) 31 | root.right.right = TreeNode(7) 32 | 33 | lca = LowestCommonAncestor() 34 | print(lca.lowestCommonAncestor(root, root.left.left, root.left.right).val) # expected to be 2 35 | print(lca.lowestCommonAncestor(root, root.left.left, root).val) # expected to be 1 36 | print(lca.lowestCommonAncestor(root, root.left, root.right.right).val) # expected to be 1 37 | -------------------------------------------------------------------------------- /python3/StairStep.py: -------------------------------------------------------------------------------- 1 | class StairStep: 2 | def stair_step_count(self, n): 3 | """ 4 | :type n: int 5 | :rtype: int 6 | """ 7 | if n == 0: 8 | return 1 9 | if n < 0: 10 | return 0 11 | 12 | return self.stair_step_count(n-1)+self.stair_step_count(n-2)+self.stair_step_count(n-3) 13 | 14 | # figure out a way to cut down on the duplication! 15 | def stair_step(self, n): 16 | """ 17 | :type n: int 18 | :rtype: List[List[int] 19 | """ 20 | if n == 0: 21 | result = [] 22 | result.append([]) 23 | return result 24 | if n < 0: 25 | return [] 26 | 27 | result = self.stair_step(n-1) 28 | result.extend(self.stair_step(n-2)) 29 | result.extend(self.stair_step(n-3)) 30 | 31 | for l in result: 32 | l.append(n) 33 | 34 | return result 35 | 36 | test = StairStep() 37 | print(test.stair_step(3)) 38 | print(test.stair_step(5)) -------------------------------------------------------------------------------- /python3/TowerOfHanoi.py: -------------------------------------------------------------------------------- 1 | class POSITION: 2 | SRC, DEST, AUX = "SRC", "DEST", "AUX" 3 | 4 | class Move: 5 | def __init__(self, disk, src, dest): 6 | """ 7 | :type disk: int 8 | :type src: POSITION 9 | :type dest: POSITION 10 | :rtype: void 11 | """ 12 | self.disk = disk 13 | self.src = src 14 | self.dest = dest 15 | 16 | def __str__(self): 17 | return "{0} from {1} to {2}".format(self.disk, self.src, self.dest) 18 | 19 | class TowerOfHanoi(object): 20 | """Print out the moves it takes to move all disks from start to end position 21 | """ 22 | def towers_of_hanoi(self, n): 23 | """ 24 | :type n: int 25 | :rtype: void 26 | """ 27 | return self.towers_of_hanoi_helper(n, POSITION.SRC, POSITION.DEST, POSITION.AUX) 28 | 29 | def towers_of_hanoi_helper(self, n, src, dest, aux): 30 | """ 31 | :type num_discs: int 32 | :type n: Move 33 | :type src: Move 34 | :type dest: Move 35 | :type aux: Move 36 | :rtype: List[Move] 37 | """ 38 | # base case 39 | if n == 1: 40 | return str(Move(n, src, dest)) 41 | 42 | result = [] 43 | result.append(self.towers_of_hanoi_helper(n-1, src, aux, dest)) 44 | result.append(str(Move(n, src, dest))) 45 | result.append(self.towers_of_hanoi_helper(n-1, aux, dest, src)) 46 | return result 47 | --------------------------------------------------------------------------------