├── .gitignore ├── README.md ├── pom.xml └── src ├── main └── java │ ├── arraystring │ ├── _01_01_IsUnique.java │ ├── _01_02_CheckPermutation.java │ ├── _01_03_URLify.java │ ├── _01_04_PalindromePermutation.java │ ├── _01_05_OneAway.java │ ├── _01_06_StringCompression.java │ ├── _01_07_RotateMatrix.java │ ├── _01_08_ZeroMatrix.java │ └── _01_09_StringRotation.java │ ├── bitmanipulation │ ├── _05_01_Insertion.java │ ├── _05_02_BinaryToString.java │ ├── _05_03_FlipBitToWin.java │ ├── _05_04_NextBiggerNumber.java │ ├── _05_04_NextSmallerNumber.java │ ├── _05_05_Debugger.java │ ├── _05_06_Conversion.java │ ├── _05_07_PairwiseSwap.java │ └── _05_08_DrawLine.java │ ├── linkedlist │ ├── LinkedListNode.java │ ├── _02_01_RemoveDups.java │ ├── _02_02_ReturnKthToLast.java │ ├── _02_03_DeleteMiddleNode.java │ ├── _02_04_Partition.java │ ├── _02_05_SumList.java │ ├── _02_05_SumListReverse.java │ ├── _02_06_Palindrome.java │ ├── _02_07_Intersection.java │ └── _02_08_LoopDetection.java │ ├── mathlogic │ └── _06_01_TheHeavyPill.java │ ├── moderate │ ├── _16_01_NumberSwapper.java │ └── _16_06_SmallestDifference.java │ ├── recursivedp │ ├── _08_01_TripleStep.java │ ├── _08_02_RobotInAGrid.java │ ├── _08_03_MagicIndex.java │ ├── _08_04_PowerSet.java │ ├── _08_05_RecursiveMultiply.java │ ├── _08_06_HanoiTowers.java │ ├── _08_07_PermutationWithoutDup.java │ ├── _08_08_PermutationWithDup.java │ ├── _08_09_Parens.java │ ├── _08_10_PaintFill.java │ ├── _08_11_Coins.java │ ├── _08_12_EightQueens.java │ ├── _08_13_StackOfBoxes.java │ └── _08_14_BooleanEvaluation.java │ ├── sortingsearching │ ├── _10_01_SortedMerge.java │ ├── _10_02_GroupAnagrams.java │ ├── _10_03_SearchInRotatedArray.java │ ├── _10_04_SortedSearch.java │ └── _10_05_SparseSearch.java │ ├── stackqueue │ ├── _03_01_ThreeInOne.java │ ├── _03_02_MinStack.java │ ├── _03_03_StackOfPlates.java │ ├── _03_04_QueueViaStacks.java │ ├── _03_05_SortStack.java │ └── _03_06_AnimalShelter.java │ └── treegraph │ ├── BinaryTreeNode.java │ ├── Digraph.java │ ├── ParentAwareBinaryTreeNode.java │ ├── _04_01_RouteBetweenNodes.java │ ├── _04_02_MinimalTree.java │ ├── _04_03_ListOfDepths.java │ ├── _04_04_CheckBalanced.java │ ├── _04_05_ValidateBST.java │ ├── _04_06_Successor.java │ ├── _04_07_BuildOrder.java │ ├── _04_08_FindCommonAncestor.java │ ├── _04_09_BSTSequences.java │ ├── _04_10_CheckSubTree.java │ ├── _04_11_RandomNode.java │ └── _04_12_PathsWithSum.java └── test └── java ├── arraystring ├── _01_01_IsUniqueTest.java ├── _01_02_CheckPermutationTest.java ├── _01_03_URLifyTest.java ├── _01_04_PalindromePermutationTest.java ├── _01_05_OneAwayTest.java ├── _01_06_StringCompressionTest.java ├── _01_07_RotateMatrixTest.java ├── _01_08_ZeroMatrixTest.java └── _01_09_StringRotationTest.java ├── bitmanipulation ├── _05_01_InsertionTest.java ├── _05_02_BinaryToStringTest.java ├── _05_03_FilpBitToWinTest.java ├── _05_04_NextBiggerNumberTest.java ├── _05_04_NextSmallerNumberTest.java ├── _05_05_DebuggerTest.java ├── _05_06_ConversionTest.java ├── _05_07_PairwiseSwapTest.java └── _05_08_DrawLineTest.java ├── linkedlist ├── _02_01_RemoveDupsTest.java ├── _02_02_ReturnKthToLastTest.java ├── _02_03_DeleteMiddleNodeTest.java ├── _02_04_PartitionTest.java ├── _02_05_SumListReverseTest.java ├── _02_05_SumListTest.java ├── _02_06_PalindromeTest.java ├── _02_07_IntersectionTest.java └── _02_08_LoopDetectionTest.java ├── moderate ├── _16_01_NumberSwapperTest.java └── _16_06_SmallestDifferenceTest.java ├── recursivedp ├── _08_01_TripleStepTest.java ├── _08_02_RobotInAGridTest.java ├── _08_03_MagicIndexTest.java ├── _08_04_PowerSetTest.java ├── _08_05_RecursiveMultiplyTest.java ├── _08_06_HanoiTowersTest.java ├── _08_07_PermutationWithoutDupTest.java ├── _08_08_PermutationWithDupTest.java ├── _08_09_ParensTest.java ├── _08_10_PaintFillTest.java ├── _08_11_CoinsTest.java ├── _08_12_EightQueensTest.java ├── _08_13_StackOfBoxesTest.java └── _08_14_BooleanEvaluationTest.java ├── sortingsearching ├── _10_01_SortedMergeTest.java ├── _10_02_GroupAnagramsTest.java ├── _10_03_SearchInRotatedArrayTest.java ├── _10_04_SortedSearchTest.java └── _10_05_SparseSearchTest.java ├── stackqueue ├── _03_01_ThreeInOneTest.java ├── _03_02_MinStackTest.java ├── _03_03_StackOfPlatesTest.java ├── _03_04_QueueViaStacksTest.java ├── _03_05_SortStackTest.java └── _03_06_AnimalShelterTest.java └── treegraph ├── _04_01_RouteBetweenNodesTest.java ├── _04_02_MinimalTreeTest.java ├── _04_03_ListOfDepthsTest.java ├── _04_04_CheckBalancedTest.java ├── _04_05_ValidateBSTTest.java ├── _04_06_SuccessorTest.java ├── _04_07_BuildOrderTest.java ├── _04_08_FindCommonAncestorTest.java ├── _04_09_BSTSequencesTest.java ├── _04_10_CheckSubTreeTest.java ├── _04_11_RandomNodeTest.java └── _04_12_PathsWithSumTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | target 4 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Acknowledgement 2 | Credits should go to Gayle Laakmann McDowell for her great work on [Cracking the Coding Interview](http://amzn.to/2zTpjdP). 3 | 4 | # Why this repo 5 | Ctci stands out among many interview books by providing not only questions but also incremental hints and solutions. 6 | However, Ctci doesn't come with tests. This repo attempts to fill this gap by adding tests for each question. 7 | 8 | - First, writing tests helps to understand the question. 9 | - Second, we can improve our testing skills 10 | - Last but not least, tests allow to try out many different solutions. 11 | 12 | # Get started 13 | 14 | This repo includes two git branches: 15 | - **practice**: Only tests are provided. It's up to you to find a solution. 16 | - **master**: Both tests and solutions are provided. Compare yours with mine. 17 | 18 | To get started, please follow the steps below: 19 | 1. Fork this repository 20 | 2. Checkout `practice` branch to solve problems 21 | 3. Compare with the reference. For instance,you want to check the optimal solution for `IsUnique` 22 | 23 | ```git diff master -- src/main/java/arraystring/_01_01_IsUnique.java``` 24 | 25 | 4. Give your feedback! If you find better solutions or tests, we'd love to see your Pull Request. 26 | 27 | # Keep practicing 28 | 29 | Don't worry if you stuck on questions. When it happens, go out for a walk, eat an ice cream 30 | or send me a [tweet](https://twitter.com/mhuiwang). Come back later when you feel better. The most important thing is that you keep practicing. 31 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | truelaurel 8 | ctci 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 1.8 17 | 1.8 18 | 19 | 20 | 21 | 22 | 23 | 24 | junit 25 | junit 26 | 4.13.1 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_01_IsUnique.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import java.util.Set; 4 | import java.util.stream.Collectors; 5 | 6 | /** 7 | * Implement an algorithm to determine if a string has all unique characters. 8 | */ 9 | 10 | class _01_01_IsUnique { 11 | 12 | // time o(n) 13 | // space o(1) 14 | boolean isUnique(String str) { 15 | Set set = str.chars().boxed().collect(Collectors.toSet()); 16 | return set.size() == str.length(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_02_CheckPermutation.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Given two strings,write a method to decide if one is a permutation of the other. 8 | */ 9 | class _01_02_CheckPermutation { 10 | boolean check(String a, String b) { 11 | return computeFrequency(a).equals(computeFrequency(b)); 12 | } 13 | 14 | private Map computeFrequency(String s) { 15 | Map freq = new HashMap<>(); 16 | for (int i = 0; i < s.length(); i++) { 17 | freq.merge(s.charAt(i), 1, (ov, v) -> ov + v); 18 | } 19 | return freq; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_03_URLify.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | /** 4 | * Write a method to replace all spaces in a string with '%20' 5 | * You may assume that the string has sufficient space at the end to hold the additional characters, 6 | * and that you are given the "true" length of the string. 7 | * (Note: If implementing in Java,please use a character array so that you can perform this operation in place.) 8 | *

9 | * EXAMPLE 10 | * Input: "Mr John Smith ", 13 11 | * Output: "Mr%20John%20Smith" 12 | */ 13 | class _01_03_URLify { 14 | char[] urlify(char[] chars, int trueLength) { 15 | int spaces = 0; 16 | for (int i = 0; i < trueLength; i++) { 17 | if (chars[i] == ' ') { 18 | spaces++; 19 | } 20 | } 21 | 22 | if (spaces * 2 + trueLength != chars.length) { 23 | throw new IllegalArgumentException("Given chars is not big enough to hold all chars"); 24 | } 25 | 26 | for (int i = trueLength - 1, j = chars.length - 1; i >= 0; i--) { 27 | if (chars[i] == ' ') { 28 | chars[j--] = '0'; 29 | chars[j--] = '2'; 30 | chars[j--] = '%'; 31 | } else { 32 | chars[j--] = chars[i]; 33 | } 34 | } 35 | return chars; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_04_PalindromePermutation.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * Given a string, write a function to check if it is a permutation of a palindrome. 8 | * A palindrome is a word or phrase that is the same forwards and backwards. 9 | * A permutation is a rearrangement of letters. 10 | * The palindrome does not need to be limited to just dictionary words. 11 | *

12 | * EXAMPLE 13 | * Input: Tact Coa 14 | * Output: True (permutations: "taco cat", "atco cta", etc.) 15 | */ 16 | class _01_04_PalindromePermutation { 17 | boolean check(String s) { 18 | Set set = new HashSet<>(); 19 | for (char c : s.toCharArray()) { 20 | if (c == ' ') continue; 21 | if (set.contains(c)) set.remove(c); 22 | else set.add(c); 23 | } 24 | return set.size() < 2; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_05_OneAway.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | /** 4 | * There are three types of edits that can be performed on strings: 5 | * insert a character, remove a character, or replace a character. 6 | * Given two strings, write a function to check if they are one edit (or zero edits) away. 7 | *

8 | * EXAMPLE 9 | * pale, ple -> true 10 | * pales, pale -> true 11 | * pale, bale -> true 12 | * pale, bake -> false 13 | */ 14 | class _01_05_OneAway { 15 | boolean isOneAway(String a, String b) { 16 | if (a.length() == b.length()) { 17 | return oneReplace(a, b); 18 | } else if (a.length() - b.length() == 1) { 19 | return oneInsertion(a, b); 20 | } else if (b.length() - a.length() == 1) { 21 | return oneInsertion(b, a); 22 | } else { 23 | return false; 24 | } 25 | } 26 | 27 | private boolean oneInsertion(String longStr, String shortStr) { 28 | boolean insert = false; 29 | for (int i = 0, j = 0; i < shortStr.length(); i++, j++) { 30 | if (shortStr.charAt(i) != longStr.charAt(j)) { 31 | if (insert) return false; 32 | insert = true; 33 | i--; 34 | } 35 | } 36 | 37 | return true; 38 | } 39 | 40 | private boolean oneReplace(String a, String b) { 41 | boolean replace = false; 42 | for (int i = 0; i < a.length(); i++) { 43 | if (a.charAt(i) != b.charAt(i)) { 44 | if (replace) return false; 45 | replace = true; 46 | } 47 | } 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_06_StringCompression.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | /** 4 | * Implement a method to perform basic string compression using the counts of repeated characters. 5 | * For example, the string aabcccccaaa would become a2blc5a3. 6 | * If the "compressed" string would not become smaller than the original string, your method should return 7 | * the original string. You can assume the string has only uppercase and lowercase letters (a - z). 8 | */ 9 | class _01_06_StringCompression { 10 | String compress(String s) { 11 | StringBuilder sb = new StringBuilder(); 12 | int count = 0; 13 | for (int i = 0; i < s.length(); i++) { 14 | count++; 15 | if (i == s.length() - 1 || s.charAt(i) != s.charAt(i + 1)) { 16 | sb.append(count).append(s.charAt(i)); 17 | count = 0; 18 | } 19 | } 20 | return sb.length() < s.length() ? sb.toString() : s; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_07_RotateMatrix.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | /** 4 | * Given an image represented by an NxN matrix, where each pixel in the image is 4 bytes, 5 | * write a method to rotate the image by 90 degrees. Can you do this in place? 6 | */ 7 | class _01_07_RotateMatrix { 8 | int[][] rotate(int[][] m) { 9 | int n = m.length; 10 | swapRow(m, n); 11 | transpose(m, n); 12 | return m; 13 | } 14 | 15 | private void transpose(int[][] m, int n) { 16 | for (int i = 0; i < n; i++) { 17 | for (int j = i + 1; j < n; j++) { 18 | int tmp = m[i][j]; 19 | m[i][j] = m[j][i]; 20 | m[j][i] = tmp; 21 | } 22 | } 23 | } 24 | 25 | private void swapRow(int[][] m, int n) { 26 | for (int start = 0, end = n - 1; start < end; start++, end--) { 27 | int[] tmp = m[start]; 28 | m[start] = m[end]; 29 | m[end] = tmp; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_08_ZeroMatrix.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | /** 4 | * Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column are set to 0. 5 | */ 6 | class _01_08_ZeroMatrix { 7 | int[][] zero(int[][] matrix) { 8 | int m = matrix.length; 9 | if (m == 0) return matrix; 10 | int n = matrix[0].length; 11 | if (n == 0) return matrix; 12 | 13 | boolean hasZeroInFirstRow = findZeroInFirstRow(matrix[0], n); 14 | 15 | boolean hasZeroInFirstCol = findZeroInFirstCol(matrix, m); 16 | 17 | detectZeroRowCol(matrix, m, n); 18 | 19 | zeroRows(matrix, m, n); 20 | 21 | zeroCols(matrix, m, n); 22 | 23 | if (hasZeroInFirstRow) { 24 | zeroFirstRow(matrix, n); 25 | } 26 | 27 | if (hasZeroInFirstCol) { 28 | zeroFirstCol(matrix, m); 29 | } 30 | 31 | return matrix; 32 | 33 | } 34 | 35 | private void zeroFirstCol(int[][] matrix, int m) { 36 | for (int i = 0; i < m; i++) { 37 | matrix[i][0] = 0; 38 | } 39 | } 40 | 41 | private void zeroFirstRow(int[][] matrix, int n) { 42 | for (int j = 0; j < n; j++) { 43 | matrix[0][j] = 0; 44 | } 45 | } 46 | 47 | private void zeroCols(int[][] matrix, int m, int n) { 48 | for (int j = 1; j < n; j++) { 49 | if (matrix[0][j] == 0) { 50 | for (int i = 0; i < m; i++) { 51 | matrix[i][j] = 0; 52 | } 53 | } 54 | } 55 | } 56 | 57 | private void zeroRows(int[][] matrix, int m, int n) { 58 | for (int i = 1; i < m; i++) { 59 | if (matrix[i][0] == 0) { 60 | for (int j = 0; j < n; j++) { 61 | matrix[i][j] = 0; 62 | } 63 | } 64 | } 65 | } 66 | 67 | private void detectZeroRowCol(int[][] matrix, int m, int n) { 68 | for (int i = 0; i < m; i++) { 69 | for (int j = 0; j < n; j++) { 70 | if (matrix[i][j] == 0) { 71 | matrix[i][0] = 0; 72 | matrix[0][j] = 0; 73 | } 74 | } 75 | } 76 | } 77 | 78 | private boolean findZeroInFirstCol(int[][] matrix, int m) { 79 | boolean hasZeroInFirstCol = false; 80 | for (int i = 0; i < m; i++) { 81 | if (matrix[i][0] == 0) hasZeroInFirstCol = true; 82 | } 83 | return hasZeroInFirstCol; 84 | } 85 | 86 | private boolean findZeroInFirstRow(int[] matrix, int n) { 87 | boolean hasZeroInFirstRow = false; 88 | for (int j = 0; j < n; j++) { 89 | if (matrix[j] == 0) hasZeroInFirstRow = true; 90 | } 91 | return hasZeroInFirstRow; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/arraystring/_01_09_StringRotation.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | /** 4 | * Assume you have a method isSubstring which checks if one word is a substring of another. 5 | * Given two strings, sl and s2, write code to check if s2 is a rotation of s1 6 | * using only one call to isSubstring (e.g.,"waterbottle" is a rotation of"erbottlewat"). 7 | */ 8 | class _01_09_StringRotation { 9 | boolean rotated(String original, String result) { 10 | return original.length() == result.length() && isSubstring((original + original), result); 11 | } 12 | 13 | private boolean isSubstring(String complete, String sub) { 14 | return complete.contains(sub); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_01_Insertion.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * You are given two 32-bit numbers, N and M, and two bit positions, i and j. 5 | * Write a method to insert M into N such that M starts at bit j and ends at bit i. 6 | * You can assume that the bits j through i have enough space to fit all of M. 7 | * That is, if M = 10011, you can assume that there are at least 5 bits between j and i. 8 | * You would not, for example, have j = 3 and i = 2, because M could not fully fit between bit 3 and bit 2. 9 | *

10 | * EXAMPLE 11 | * Input: N 10000000000, M 10011, i 2, j 6 12 | * Output:N = 10001001100 13 | */ 14 | class _05_01_Insertion { 15 | 16 | int insert(int n, int m, int i, int j) { 17 | int allOnes = -1; 18 | int left = allOnes << (j + 1); 19 | int right = (1 << i) - 1; 20 | int mask = left | right; 21 | int shiftedM = m << i; 22 | int clearedN = n & mask; 23 | return shiftedM | clearedN; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_02_BinaryToString.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * Given a real number between O and 1 (e.g., 0.72) that is passed in as a double, print the binary representation. 5 | * If the number cannot be represented accurately in binary with at most 32 characters, print "ERROR:' 6 | */ 7 | class _05_02_BinaryToString { 8 | String print(double num) { 9 | if (num <= 0 || num >= 1) return "ERROR"; 10 | StringBuilder sb = new StringBuilder(); 11 | sb.append("."); 12 | for (int i = 0; i < 32; i++) { 13 | if (num == 0) return sb.toString(); 14 | num *= 2; 15 | if (num >= 1.0) { 16 | sb.append('1'); 17 | num -= 1; 18 | } else { 19 | sb.append('0'); 20 | } 21 | } 22 | return "ERROR"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_03_FlipBitToWin.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * You have an integer and you can flip exactly one bit from a 0 to a 1. 5 | * Write code to find the length of the longest sequence of 1s you could create. 6 | *

7 | * EXAMPLE 8 | * Input: 1775 (or: 11011101111) 9 | * Output: 8 10 | */ 11 | class _05_03_FlipBitToWin { 12 | int flip(int n) { 13 | if (n == -1) return 32; 14 | int pre = 0; 15 | int cur = 0; 16 | int max = 1; 17 | while (n != 0) { 18 | if ((n & 1) == 1) { 19 | cur++; 20 | } else { 21 | pre = (n & 2) == 0 ? 0 : cur; 22 | cur = 0; 23 | } 24 | max = Math.max(max, pre + cur + 1); 25 | n >>>= 1; 26 | } 27 | return max; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_04_NextBiggerNumber.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * Given a positive integer, 5 | * print the next largest number that 6 | * have the same number of 1 bits in their binary representation. 7 | */ 8 | class _05_04_NextBiggerNumber { 9 | 10 | int nextBigger(int n) { 11 | if (n <= 0) return -1; 12 | 13 | int tmp = n; 14 | int zeros = 0; 15 | int ones = 0; 16 | while (tmp != 0 && (tmp & 1) == 0) { 17 | zeros++; 18 | tmp >>= 1; 19 | } 20 | while ((tmp & 1) == 1) { 21 | ones++; 22 | tmp >>= 1; 23 | } 24 | 25 | if (zeros + ones == 31) return -1; 26 | 27 | //flip zero to one 28 | n = n | 1 << (zeros + ones); 29 | 30 | //clear right part 31 | n = n & ~((1 << (zeros + ones)) - 1); 32 | 33 | //add ones 34 | n = n | ((1 << (ones - 1)) - 1); 35 | 36 | return n; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_04_NextSmallerNumber.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * Given a positive integer, 5 | * print the next smallest number that 6 | * have the same number of 1 bits in their binary representation. 7 | */ 8 | class _05_04_NextSmallerNumber { 9 | 10 | int nextSmaller(int n) { 11 | if (n <= 0) return -1; 12 | 13 | int tmp = n; 14 | int zeros = 0; 15 | int ones = 0; 16 | while ((tmp & 1) == 1) { 17 | ones++; 18 | tmp >>= 1; 19 | } 20 | 21 | while (tmp > 0 && (tmp & 1) == 0) { 22 | zeros++; 23 | tmp >>= 1; 24 | } 25 | 26 | if (zeros == 0) return -1; 27 | 28 | //clear right part 29 | n = n & ~((1 << (zeros + ones + 1)) - 1); 30 | 31 | //add ones 32 | n = n | (((1 << (ones + 1)) - 1) << (zeros - 1)); 33 | 34 | return n; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_05_Debugger.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * Explain what the following code does 5 | */ 6 | public class _05_05_Debugger { 7 | 8 | // n & (n - 1) clears the least significant bit, if nothing remains. it means there is only is one 1. 9 | // therefore it's a power of 2 10 | boolean debug(int n) { 11 | return (n & (n - 1)) == 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_06_Conversion.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * Write a function to determine the number of bits you would need to flip to convert 5 | * integer A to integer B. 6 | *

7 | * EXAMPLE 8 | * Input: 29 (or: 11101), 15 (or: 01111) 9 | * Output: 2 10 | */ 11 | public class _05_06_Conversion { 12 | int convert(int a, int b) { 13 | int c = a ^ b; 14 | int ones = 0; 15 | while (c > 0) { 16 | ones++; 17 | c &= c - 1; 18 | } 19 | return ones; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_07_PairwiseSwap.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * Write a program to swap odd and even bits in an integer with as few instructions as 5 | * possible (e.g., bit 0 and bit 1 are swapped, bit 2 and bit 3 are swapped, and so on). 6 | */ 7 | class _05_07_PairwiseSwap { 8 | int swap(int n) { 9 | return ((0xaaaa_aaaa & n) >>> 1) | ((0x5555_5555 & n) << 1); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/bitmanipulation/_05_08_DrawLine.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | /** 4 | * A monochrome screen is stored as a single array of bytes, allowing eight consecutive pixels to be stored in one byte. 5 | *

6 | * The screen has width w, where w is divisible by 8 (that is, no byte will be split across rows). 7 | * The height of the screen, of course, can be derived from the length of the array and the width. 8 | *

9 | * Implement a function that draws a horizontal line from (x1, y) to ( x2, y). 10 | *

11 | * for example, if screen has a width 16 and a height 2. | encoded as 0 and - as 1 12 | * | | | | | | | | | | | | | | | | 13 | * | | | | | | | | | | | | | | | | 14 | *

15 | * drawing a line from (2, 1) to (13, 1) gives the following result 16 | * | | | | | | | | | | | | | | | | 17 | * | | - - - - - - - - - - - - | | 18 | */ 19 | class _05_08_DrawLine { 20 | byte[] drawLine(byte[] screen, int width, int x1, int x2, int y) { 21 | if (x2 < x1) throw new IllegalArgumentException("end must not be less than start"); 22 | int startByte = x1 / 8; 23 | int endByte = x2 / 8; 24 | 25 | int row = width / 8 * y; 26 | 27 | for (int i = startByte + 1; i <= endByte - 1; i++) { 28 | screen[row + i] = (byte) 0xff; 29 | } 30 | 31 | int startIndex = x1 % 8; 32 | int endIndex = x2 % 8; 33 | 34 | if (startByte == endByte) { 35 | set(screen, row + startByte, startIndex, endIndex); 36 | } else { 37 | set(screen, row + startByte, startIndex, 7); 38 | set(screen, row + endByte, 0, endIndex); 39 | } 40 | return screen; 41 | } 42 | 43 | private void set(byte[] screen, int i, int start, int end) { 44 | screen[i] |= (byte) ((0xff >> start) & ~(0xff >> (end + 1))); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/LinkedListNode.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import java.util.Objects; 4 | 5 | public class LinkedListNode { 6 | 7 | int val; 8 | LinkedListNode next; 9 | 10 | LinkedListNode(int val) { 11 | this.val = val; 12 | } 13 | 14 | static LinkedListNode empty() { 15 | return null; 16 | } 17 | 18 | static LinkedListNode of(int... list) { 19 | LinkedListNode pre = null; 20 | LinkedListNode head = null; 21 | for (int val : list) { 22 | if (pre == null) { 23 | head = new LinkedListNode(val); 24 | pre = head; 25 | } else { 26 | pre.next = new LinkedListNode(val); 27 | pre = pre.next; 28 | } 29 | } 30 | return head; 31 | } 32 | 33 | @Override 34 | public boolean equals(Object o) { 35 | if (this == o) return true; 36 | if (o == null || getClass() != o.getClass()) return false; 37 | LinkedListNode that = (LinkedListNode) o; 38 | return val == that.val && 39 | Objects.equals(next, that.next); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "LinkedListNode{" + 45 | "val=" + val + 46 | ", next=" + next + 47 | '}'; 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return Objects.hash(val, next); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_01_RemoveDups.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * Remove Dups! 8 | * Write code to remove duplicates from an unsorted linked list. 9 | */ 10 | class _02_01_RemoveDups { 11 | 12 | // time o(n) 13 | // space o(n) 14 | LinkedListNode removeDups(LinkedListNode head) { 15 | Set set = new HashSet<>(); 16 | LinkedListNode pre = null; 17 | LinkedListNode next = head; 18 | while (next != null) { 19 | if (set.contains(next.val)) { 20 | pre.next = next.next; 21 | } else { 22 | set.add(next.val); 23 | pre = next; 24 | } 25 | next = next.next; 26 | } 27 | return head; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_02_ReturnKthToLast.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | /** 4 | * Implement an algorithm to find the kth to last element of a singly linked list 5 | */ 6 | class _02_02_ReturnKthToLast { 7 | 8 | // time o(n) 9 | // space o(1) 10 | LinkedListNode kthToLast(LinkedListNode head, int k) { 11 | LinkedListNode kth = head; 12 | LinkedListNode runner = head; 13 | int dist = 0; 14 | while (runner.next != null) { 15 | if (dist == k) { 16 | runner = runner.next; 17 | kth = kth.next; 18 | } else { 19 | runner = runner.next; 20 | dist++; 21 | } 22 | } 23 | return dist == k ? kth : null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_03_DeleteMiddleNode.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | /** 4 | * Implement an algorithm to delete a node in the 5 | * middle(i.e., any node but the first and last node, not necessarily the exact middle) 6 | * of a singly linked list, given only access to that node. 7 | */ 8 | class _02_03_DeleteMiddleNode { 9 | 10 | // time o(1) 11 | // space o(1) 12 | boolean deleteMiddleNode(LinkedListNode node) { 13 | if (node == null || node.next == null) return false; 14 | LinkedListNode next = node.next; 15 | node.val = next.val; 16 | node.next = next.next; 17 | return true; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_04_Partition.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | /** 4 | * Partition: Write code to partition a linked list around a value x, 5 | * such that all nodes less than x come before all nodes greater than or equal to x. 6 | * If x is contained within the list, the values of x only need to be after the elements less than x (see below). 7 | * The partition element x can appear anywhere in the "right partition"; 8 | * it does not need to appear between the left and right partitions. 9 | * EXAMPLE 10 | * Input: 3 -> 5 -> 8 -> 5 -> 10 -> 2 -> 1[partition=5] 11 | * Output: 3 -> 1 -> 2 -> 10 -> 5 -> 5 -> 8 12 | */ 13 | class _02_04_Partition { 14 | 15 | LinkedListNode partition(LinkedListNode head, int x) { 16 | if (head == null) return null; 17 | LinkedListNode pre = null; 18 | LinkedListNode cur = head; 19 | while (cur != null) { 20 | if (cur.val < x && pre != null) { 21 | pre.next = cur.next; 22 | cur.next = head; 23 | head = cur; 24 | cur = pre.next; 25 | } else { 26 | pre = cur; 27 | cur = cur.next; 28 | } 29 | } 30 | return head; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_05_SumList.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | /** 4 | * Sum Lists: You have two numbers represented by a linked list, 5 | * where each node contains a single digit. 6 | * The digits are stored in normal order, such that the 1 's digit is at the tail of the list. 7 | * Write a function that adds the two numbers and returns the sum as a linked list. 8 | *

9 | * EXAMPLE 10 | * Input:(7-> 1 -> 6) + (5 -> 9 -> 2).That is, 716 + 592. 11 | * Output:1 -> 4 -> 0 -> 8.That is, 1408. 12 | */ 13 | class _02_05_SumList { 14 | 15 | LinkedListNode sum(LinkedListNode l1, LinkedListNode l2) { 16 | int length1 = len(l1); 17 | int length2 = len(l2); 18 | l1 = pad(l1, length2 - length1); 19 | l2 = pad(l2, length1 - length2); 20 | PartialSum partial = sumRec(l1, l2); 21 | if (partial.carry == 0) return partial.head; 22 | LinkedListNode head = new LinkedListNode(1); 23 | head.next = partial.head; 24 | return head; 25 | } 26 | 27 | private PartialSum sumRec(LinkedListNode l1, LinkedListNode l2) { 28 | if (l1 == null || l2 == null) { 29 | return new PartialSum(); 30 | } 31 | PartialSum partial = sumRec(l1.next, l2.next); 32 | 33 | int sum = l1.val + l2.val + partial.carry; 34 | LinkedListNode n = new LinkedListNode(sum % 10); 35 | n.next = partial.head; 36 | partial.head = n; 37 | partial.carry = sum / 10; 38 | return partial; 39 | } 40 | 41 | private int len(LinkedListNode node) { 42 | int l = 0; 43 | while (node != null) { 44 | node = node.next; 45 | l++; 46 | } 47 | return l; 48 | } 49 | 50 | private LinkedListNode pad(LinkedListNode head, int padding) { 51 | for (int i = 0; i < padding; i++) { 52 | LinkedListNode n = new LinkedListNode(0); 53 | n.next = head; 54 | head = n; 55 | } 56 | return head; 57 | } 58 | 59 | static class PartialSum { 60 | LinkedListNode head; 61 | int carry; 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_05_SumListReverse.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | /** 4 | * Sum Lists: You have two numbers represented by a linked list, 5 | * where each node contains a single digit. 6 | * The digits are stored in reverse order, such that the 1 's digit is at the head of the list. 7 | * Write a function that adds the two numbers and returns the sum as a linked list. 8 | *

9 | * EXAMPLE 10 | * Input:(7-> 1 -> 6) + (5 -> 9 -> 2).That is,617 + 295. 11 | * Output:2 -> 1 -> 9.That is,912. 12 | */ 13 | class _02_05_SumListReverse { 14 | LinkedListNode sum(LinkedListNode l1, LinkedListNode l2) { 15 | LinkedListNode head = null; 16 | LinkedListNode tail = null; 17 | int carry = 0; 18 | while (l1 != null || l2 != null) { 19 | LinkedListNode n = new LinkedListNode(0); 20 | int sum = carry; 21 | if (l1 != null) { 22 | sum += l1.val; 23 | l1 = l1.next; 24 | } 25 | 26 | if (l2 != null) { 27 | sum += l2.val; 28 | l2 = l2.next; 29 | } 30 | 31 | n.val = sum % 10; 32 | carry = sum / 10; 33 | 34 | if (head == null) { 35 | head = n; 36 | tail = n; 37 | } else { 38 | tail.next = n; 39 | tail = n; 40 | } 41 | } 42 | if (carry == 1) tail.next = new LinkedListNode(1); 43 | return head; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_06_Palindrome.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Palindrome: Implement a function to check if a linked list is a palindrome. 7 | */ 8 | class _02_06_Palindrome { 9 | 10 | boolean isPalindrome(LinkedListNode head) { 11 | if (head == null) return true; 12 | Stack stack = new Stack<>(); 13 | LinkedListNode cur = head; 14 | while (cur != null) { 15 | stack.push(cur.val); 16 | cur = cur.next; 17 | } 18 | 19 | int half = stack.size() / 2; 20 | while (half >= 0) { 21 | int val = stack.pop(); 22 | if (val != head.val) return false; 23 | head = head.next; 24 | half--; 25 | } 26 | return true; 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_07_Intersection.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | /** 4 | * Intersection: Given two (singly) linked lists, determine if the two lists intersect. 5 | * Return the intersecting node. Note that the intersection is de ned based on reference, not value. 6 | * That is, if the kth node of the first linked list is the exact same node (by reference) 7 | * as the jth node of the second linked list, then they are intersecting. 8 | */ 9 | class _02_07_Intersection { 10 | 11 | boolean intersects(LinkedListNode l1, LinkedListNode l2) { 12 | if (l1 == null || l2 == null) return false; 13 | LinkedListNode r1 = l1; 14 | LinkedListNode r2 = l2; 15 | boolean switched1 = false; 16 | boolean switched2 = false; 17 | while (r1 != null || r2 != null) { 18 | if (r1 == r2) return true; 19 | if (r1 == null) { 20 | if (switched1) return false; 21 | r1 = l2; 22 | switched1 = true; 23 | } else { 24 | r1 = r1.next; 25 | } 26 | 27 | if (r2 == null) { 28 | if (switched2) return false; 29 | r2 = l1; 30 | switched2 = true; 31 | } else { 32 | r2 = r2.next; 33 | } 34 | } 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/linkedlist/_02_08_LoopDetection.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | /** 4 | * Loop Detection: Given a circular linked list, implement an algorithm that returns the node at the 5 | * beginning of the loop. 6 | *

7 | * DEFINITION 8 | * Circular linked list: A (corrupt) linked list in which a node's next pointer points to an earlier node, so as to make a loop in the linked list. 9 | *

10 | * EXAMPLE 11 | * Input: A -> B -> C -> D -> E -> C[the same C as earlier] 12 | * Output: C 13 | */ 14 | class _02_08_LoopDetection { 15 | 16 | LinkedListNode detect(LinkedListNode head) { 17 | LinkedListNode runner = head; 18 | LinkedListNode walker = head; 19 | while (runner != null && runner.next != null) { 20 | runner = runner.next.next; 21 | walker = walker.next; 22 | if (runner == walker) break; 23 | } 24 | if (runner == null || runner.next == null) return null; 25 | 26 | walker = head; 27 | while (runner != walker) { 28 | runner = runner.next; 29 | walker = walker.next; 30 | } 31 | return runner; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mathlogic/_06_01_TheHeavyPill.java: -------------------------------------------------------------------------------- 1 | package mathlogic; 2 | 3 | /** 4 | * You have 20 bottles of pills. 19 bottles have 1.0 gram pills, but one has pills of weight 1.1 grams. 5 | * Given a scale that provides an exact measurement, how would you find the heavy bottle? 6 | * You can only use the scale once. 7 | */ 8 | public class _06_01_TheHeavyPill { 9 | 10 | /** 11 | * pick one pill form the #1 bottle and two pills from #2 bottle and n pills from #n bottle 12 | * according the extra contribution, we can't identify the bottle with heavy pills 13 | * weight = normalWeight + extraWeight where normalWeight = (1 + 2 + ... + 20) = 20 * ( 1 + 20)/2 = 210 14 | * #bottle = (weight - 210) / 0.1 15 | *

16 | * note that we need to assume there are enough pills in the bottles 17 | */ 18 | void solution() { 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/moderate/_16_01_NumberSwapper.java: -------------------------------------------------------------------------------- 1 | package moderate; 2 | 3 | /** 4 | * Write a function to swap a number in place (that is, without temporary variables). 5 | */ 6 | class _16_01_NumberSwapper { 7 | 8 | void swap(int[] ab) { 9 | ab[0] = ab[0] ^ ab[1]; 10 | ab[1] = ab[0] ^ ab[1]; 11 | ab[0] = ab[0] ^ ab[1]; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/moderate/_16_06_SmallestDifference.java: -------------------------------------------------------------------------------- 1 | package moderate; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Given two arrays of integers, compute the pair of values (one value in each array) 7 | * with the smallest (non-negative) difference. Return the difference. 8 | *

9 | * EXAMPLE 10 | * Input: {1, 3, 15, 11, 2}, {23, 127,235, 19, 8} 11 | * Output: 3. That is, the pair (11, 8). 12 | */ 13 | public class _16_06_SmallestDifference { 14 | 15 | int findSmallestDiff(int[] a1, int[] a2) { 16 | int[] small = a1.length < a2.length ? a1 : a2; 17 | int[] big = small == a1 ? a2 : a1; 18 | Arrays.sort(small); 19 | int diff = Integer.MAX_VALUE; 20 | for (int i : big) { 21 | int p = Arrays.binarySearch(small, i); 22 | if (p < 0) { 23 | int insertion = -p - 1; 24 | if (insertion > 0) { 25 | diff = Math.min(diff, i - small[insertion - 1]); 26 | } 27 | 28 | if (insertion < small.length) { 29 | diff = Math.min(diff, small[insertion] - i); 30 | } 31 | } 32 | } 33 | return diff; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_01_TripleStep.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | /** 4 | * A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time. 5 | * Implement a method to count how many possible ways the child can run up the stairs. 6 | */ 7 | class _08_01_TripleStep { 8 | 9 | //time o(n) space o(1) 10 | int countWays(int steps) { 11 | if (steps == 0) return 1; 12 | else if (steps == 1) return 1; 13 | else if (steps == 2) return 2; 14 | else if (steps == 3) return 4; 15 | int a = 1; 16 | int b = 2; 17 | int c = 4; 18 | int ways = 0; 19 | for (int i = 4; i <= steps; i++) { 20 | ways = a + b + c; 21 | a = b; 22 | b = c; 23 | c = ways; 24 | } 25 | return ways; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_02_RobotInAGrid.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.awt.*; 4 | import java.util.*; 5 | import java.util.List; 6 | 7 | /** 8 | * Imagine a robot sitting on the upper left corner of grid with r rows and c columns. 9 | * The robot can only move in two directions, right and down, but certain cells are "off limits" 10 | * such that the robot cannot step on them. Design an algorithm to find a path for the robot 11 | * from the top left to the bottom right. 12 | */ 13 | class _08_02_RobotInAGrid { 14 | List findPath(boolean[][] grid) { 15 | if (grid == null || grid.length == 0) return Collections.emptyList(); 16 | int rows = grid.length - 1; 17 | int cols = grid[0].length - 1; 18 | List path = new ArrayList<>(); 19 | Set failed = new HashSet<>(); 20 | getPath(grid, rows, cols, path, failed); 21 | return path; 22 | } 23 | 24 | private boolean getPath(boolean[][] grid, int r, int c, List path, Set failed) { 25 | if (r < 0 || c < 0 || !grid[r][c]) { 26 | return false; 27 | } 28 | Point p = new Point(r, c); 29 | 30 | if (failed.contains(p)) return false; 31 | 32 | boolean isOrigin = (r == 0) && (c == 0); 33 | if (isOrigin || getPath(grid, r - 1, c, path, failed) || getPath(grid, r, c - 1, path, failed)) { 34 | path.add(p); 35 | return true; 36 | } else { 37 | failed.add(p); 38 | return false; 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_03_MagicIndex.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | /** 4 | * Magic Index: A magic index in an array A[0...n-1] is defined to be an index such that A[i] = i. 5 | * Given a sorted array of distinct integers, write a method to find a magic index, if one exists, in array A. 6 | */ 7 | class _08_03_MagicIndex { 8 | 9 | int findMagicIndex(int[] arr) { 10 | if (arr == null || arr.length == 0) { 11 | return -1; 12 | } 13 | 14 | int start = 0; 15 | int end = arr.length - 1; 16 | while (start <= end) { 17 | int mid = start + (end - start) / 2; 18 | if (arr[mid] == mid) { 19 | return mid; 20 | } else if (arr[mid] > mid) { 21 | end = mid - 1; 22 | } else { 23 | start = mid + 1; 24 | } 25 | } 26 | return -1; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_04_PowerSet.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.util.Collections; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * Write a method to return all subsets of a set 10 | */ 11 | class _08_04_PowerSet { 12 | 13 | Set> subSets(Set set) { 14 | if (set.isEmpty()) return Collections.emptySet(); 15 | Set> subsets = new HashSet<>(); 16 | subsets.add(new HashSet<>()); 17 | for (Integer integer : set) { 18 | subsets = grow(subsets, integer); 19 | } 20 | return subsets; 21 | } 22 | 23 | private Set> grow(Set> subsets, Integer i) { 24 | Set> grown = subsets.stream().map(set -> grow(i, set)).collect(Collectors.toSet()); 25 | grown.addAll(subsets); 26 | return grown; 27 | } 28 | 29 | private HashSet grow(Integer i, Set set) { 30 | HashSet newSet = new HashSet<>(set); 31 | newSet.add(i); 32 | return newSet; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_05_RecursiveMultiply.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | /** 4 | * Write a recursive function to multiply two positive integers without using the * operator. 5 | * You can use addition, subtraction, and bit shifting, but you should minimize the number of those operations. 6 | */ 7 | class _08_05_RecursiveMultiply { 8 | 9 | int multiple(int a, int b) { 10 | int small = Math.min(a, b); 11 | int big = Math.max(a, b); 12 | return multipleRecursive(big, small); 13 | } 14 | 15 | private int multipleRecursive(int big, int small) { 16 | if (small == 0) return 0; 17 | if (small == 1) return big; 18 | int half = multipleRecursive(big, small >> 1); 19 | if (small % 2 == 0) return half + half; 20 | else return half + half + big; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_06_HanoiTowers.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * In the classic problem of the towers of Hanoi, 8 | * you have 3 towers and N disks of different sizes which can slide onto any tower. 9 | * The puzzle starts with disks sorted in ascending order of size from top to bottom 10 | * (i.e., each disk sits on top of an even larger one). 11 | * You have the following constraints: 12 | * (1) Only one disk can be moved at a time. 13 | * (2) A disk is slid off the top of one tower onto another tower. 14 | * (3) A disk cannot be placed on top of a smaller disk. 15 | * Write a program to move the disks from the first tower to the last using stacks. 16 | */ 17 | class _08_06_HanoiTowers { 18 | 19 | private static final int LEFT = 1; // id(left) = 1 20 | private static final int RIGHT = 3; // id(right) = 3 21 | private static final int SUM = 6; // id(center) = 2 22 | 23 | List leftToRight(int n) { 24 | return move(n, LEFT, RIGHT); 25 | } 26 | 27 | private List move(int n, int from, int to) { 28 | if (n == 1) { 29 | List moves = new ArrayList<>(); 30 | moves.add(from); 31 | moves.add(to); 32 | return moves; 33 | } 34 | int buffer = SUM - from - to; 35 | List moves = move(n - 1, from, buffer); 36 | moves.add(from); 37 | moves.add(to); 38 | moves.addAll(move(n - 1, buffer, to)); 39 | return moves; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_07_PermutationWithoutDup.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.util.Collections; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | /** 8 | * Write a method to compute all permutations of a string of unique characters. 9 | */ 10 | class _08_07_PermutationWithoutDup { 11 | 12 | Set computePermutation(String str) { 13 | if (str.length() == 0) return Collections.singleton(""); 14 | Set result = new HashSet<>(); 15 | for (int i = 0; i < str.length(); i++) { 16 | char c = str.charAt(i); 17 | String prefix = str.substring(0, i); 18 | String remainder = str.substring(i + 1, str.length()); 19 | Set partial = computePermutation(prefix + remainder); 20 | for (String s : partial) { 21 | result.add(c + s); 22 | } 23 | } 24 | return result; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_08_PermutationWithDup.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * Write a method to compute all permutations of a string whose characters 7 | * are not necessarily unique. The list of permutations should not have duplicates. 8 | */ 9 | class _08_08_PermutationWithDup { 10 | 11 | Set computePermutation(String str) { 12 | if (str.length() == 0) return Collections.singleton(""); 13 | Map frequencyTable = buildFrequencyTable(str); 14 | Set result = new HashSet<>(); 15 | dfs(frequencyTable, "", str.length(), result); 16 | return result; 17 | } 18 | 19 | private void dfs(Map map, String prefix, int remaining, Set result) { 20 | if (remaining == 0) { 21 | result.add(prefix); 22 | } else { 23 | for (Character c : map.keySet()) { 24 | int count = map.get(c); 25 | if (count > 0) { 26 | map.put(c, count - 1); 27 | dfs(map, prefix + c, remaining - 1, result); 28 | map.put(c, count); 29 | } 30 | } 31 | } 32 | } 33 | 34 | private Map buildFrequencyTable(String str) { 35 | Map m = new HashMap<>(); 36 | for (int i = 0; i < str.length(); i++) { 37 | m.compute(str.charAt(i), (k, v) -> v == null ? 1 : v + 1); 38 | } 39 | return m; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_09_Parens.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.util.Collections; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | /** 8 | * Implement an algorithm to print all valid (e.g., properly opened and closed) combinations of n pairs of parentheses. 9 | * EXAMPLE 10 | * Input: 3 11 | * Output: ((())), (()()), (())(), ()(()), ()()() 12 | */ 13 | public class _08_09_Parens { 14 | 15 | //time o(2^n) space o(n) where n = pairs * 2 16 | Set combine(int pairs) { 17 | if (pairs == 0) return Collections.emptySet(); 18 | Set result = new HashSet<>(); 19 | char[] buff = new char[pairs * 2]; 20 | doCombine(pairs, 0, 0, result, buff); 21 | return result; 22 | } 23 | 24 | private void doCombine(int pairs, int open, int close, Set result, char[] buff) { 25 | if (open == pairs && close == pairs) { 26 | result.add(String.valueOf(buff)); 27 | } else { 28 | if (open < pairs) { 29 | buff[open + close] = '('; 30 | doCombine(pairs, open + 1, close, result, buff); 31 | } 32 | if (close < open) { 33 | buff[open + close] = ')'; 34 | doCombine(pairs, open, close + 1, result, buff); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_10_PaintFill.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | /** 4 | * Paint Fill: Implement the "paint fill" function that one might see on many image editing programs. 5 | * That is, given a screen (represented by a two-dimensional array of colors), a point, and a new color, 6 | * fill in the surrounding area until the color changes from the original color. 7 | *

8 | * EXAMPLE 9 | *

10 | * [0, 1, 1] 11 | * [1, 1, 0] 12 | * [1, 0, 0] 13 | *

14 | * Given a new point at (2, 2) and new color 2, the expected screen after paint filling should be 15 | * [0, 1, 1] 16 | * [1, 1, 2] 17 | * [1, 2, 2] 18 | */ 19 | public class _08_10_PaintFill { 20 | 21 | private int[][] screen; 22 | private int rows; 23 | private int cols; 24 | private int oldColor; 25 | private int newColor; 26 | 27 | int[][] paintFill(int[][] screen, int row, int col, int newColor) { 28 | this.screen = screen; 29 | rows = screen.length; 30 | if (rows == 0) throw new IllegalArgumentException("scree must contain at least one row"); 31 | cols = screen[0].length; 32 | oldColor = screen[row][col]; 33 | this.newColor = newColor; 34 | doPaint(row, col); 35 | return screen; 36 | } 37 | 38 | private void doPaint(int row, int col) { 39 | if (screen[row][col] != oldColor) return; 40 | 41 | screen[row][col] = newColor; 42 | if (row > 0) { 43 | doPaint(row - 1, col); 44 | } 45 | 46 | if (row < rows - 1) { 47 | doPaint(row + 1, col); 48 | } 49 | 50 | if (col > 0) { 51 | doPaint(row, col - 1); 52 | } 53 | 54 | if (col < cols - 1) { 55 | doPaint(row, col + 1); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_11_Coins.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | /** 4 | * Coins: Given an infinite number of quarters (25 cents), dimes (10 cents), nickels (5 cents), and pennies (1 cent), 5 | * write code to calculate the number of ways of representing n cents. 6 | */ 7 | public class _08_11_Coins { 8 | 9 | int makeChangeWithQuarterDimeNickelPenny(int n) { 10 | int[] components = {25, 10, 5, 1}; 11 | int[][] cache = new int[n + 1][components.length]; 12 | return makeChange(n, 0, components, cache); 13 | } 14 | 15 | private int makeChange(int amount, int index, int[] components, int[][] cache) { 16 | if (amount == 0 || index == components.length - 1) { 17 | return 1; 18 | } 19 | if (cache[amount][index] > 0) { 20 | return cache[amount][index]; 21 | } 22 | int ways = 0; 23 | for (int remaining = amount; remaining >= 0; remaining -= components[index]) { 24 | ways += makeChange(remaining, index + 1, components, cache); 25 | } 26 | cache[amount][index] = ways; 27 | return ways; 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_12_EightQueens.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.awt.*; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | /** 9 | * Write an algorithm to print all ways of arranging eight queens on an 8x8 chess board 10 | * so that none of them share the same row, column, or diagonal. 11 | * In this case, "diagonal" means all diagonals, not just the two that bisect the board. 12 | */ 13 | public class _08_12_EightQueens { 14 | 15 | private static final int SIZE = 8; 16 | 17 | List> arrange() { 18 | List> result = new ArrayList<>(); 19 | Constraints constraints = new Constraints(); 20 | dfs(0, new Point[SIZE], constraints, result); 21 | return result; 22 | } 23 | 24 | private void dfs(int row, Point[] points, Constraints constraints, List> result) { 25 | if (row == SIZE) { 26 | result.add(Arrays.asList(points)); 27 | return; 28 | } 29 | 30 | for (int col = 0; col < SIZE; col++) { 31 | Point p = new Point(row, col); 32 | if (constraints.isFeasible(p)) { 33 | constraints.mark(p); 34 | points[row] = p; 35 | dfs(row + 1, points, constraints, result); 36 | constraints.unmark(p); 37 | } 38 | } 39 | 40 | } 41 | 42 | private static class Constraints { 43 | private boolean[] rows = new boolean[SIZE]; 44 | private boolean[] cols = new boolean[SIZE]; 45 | private boolean[] positive = new boolean[SIZE * 2 - 1]; 46 | private boolean[] negative = new boolean[SIZE * 2 - 1]; 47 | 48 | private void mark(Point p) { 49 | rows[p.x] = true; 50 | cols[p.y] = true; 51 | positive[toPositiveDiagonal(p)] = true; 52 | negative[toNegativeDiagonal(p)] = true; 53 | } 54 | 55 | private void unmark(Point p) { 56 | rows[p.x] = false; 57 | cols[p.y] = false; 58 | positive[toPositiveDiagonal(p)] = false; 59 | negative[toNegativeDiagonal(p)] = false; 60 | } 61 | 62 | private boolean isFeasible(Point p) { 63 | return !rows[p.x] 64 | && !cols[p.y] 65 | && !positive[toPositiveDiagonal(p)] 66 | && !negative[toNegativeDiagonal(p)]; 67 | } 68 | 69 | private int toPositiveDiagonal(Point p) { 70 | return p.x + p.y; 71 | } 72 | 73 | 74 | private int toNegativeDiagonal(Point p) { 75 | return SIZE - 1 - (p.x - p.y); 76 | } 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_13_StackOfBoxes.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import java.util.Comparator; 4 | import java.util.List; 5 | 6 | /** 7 | * You have a stack of n boxes, with widths wi, heights hi, and depths di. 8 | * The boxes cannot be rotated and can only be stacked on top of one another 9 | * if each box in the stack is strictly larger than the box above it 10 | * in width, height, and depth. 11 | *

12 | * Implement a method to compute the height of the tallest possible stack. 13 | * The height of a stack is the sum of the heights of each box. 14 | */ 15 | public class _08_13_StackOfBoxes { 16 | 17 | int createStack(List boxes) { 18 | boxes.sort(Comparator.comparing(b -> -b.h)); 19 | int[] cache = new int[boxes.size()]; 20 | int max = 0; 21 | for (int i = 0; i < boxes.size(); i++) { 22 | int h = doCreateStack(boxes, i, cache); 23 | max = Math.max(max, h); 24 | } 25 | return max; 26 | } 27 | 28 | private int doCreateStack(List boxes, int bottom, int[] cache) { 29 | if (cache[bottom] > 0) return cache[bottom]; 30 | if (bottom == boxes.size()) return 0; 31 | int max = 0; 32 | Box current = boxes.get(bottom); 33 | for (int i = bottom + 1; i < boxes.size(); i++) { 34 | Box next = boxes.get(i); 35 | if (next.canPutAbove(current)) { 36 | int h = doCreateStack(boxes, i, cache); 37 | max = Math.max(max, h); 38 | } 39 | } 40 | int total = current.h + max; 41 | cache[bottom] = total; 42 | return total; 43 | } 44 | 45 | static class Box { 46 | int w; 47 | int h; 48 | int d; 49 | 50 | Box(int w, int h, int d) { 51 | this.w = w; 52 | this.h = h; 53 | this.d = d; 54 | } 55 | 56 | boolean canPutAbove(Box that) { 57 | return that.h > h && that.w > w && that.d > d; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/recursivedp/_08_14_BooleanEvaluation.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | /** 4 | * Given a boolean expression consisting of the symbols 0 (false), 1 (true), & (AND), | (OR), and ^ (XOR), 5 | * and a desired boolean result value result, implement a function to count the number of ways of 6 | * parenthesizing the expression such that it evaluates to result. 7 | *

8 | * EXAMPLE 9 | * countEval("1^0|0|1", false) -> 2 10 | * countEval("0&0&0&1^1|0", true) -> 10 11 | */ 12 | public class _08_14_BooleanEvaluation { 13 | 14 | int evaluate(String expression, boolean result) { 15 | if (expression.isEmpty()) return 0; 16 | Pair[][] cache = new Pair[expression.length() + 1][expression.length() + 1]; 17 | Pair pair = doEvaluate(expression, 0, expression.length(), cache); 18 | return result ? pair.trueCount : pair.falseCount; 19 | } 20 | 21 | private Pair doEvaluate(String exp, int start, int end, Pair[][] cache) { 22 | if (cache[start][end] != null) { 23 | return cache[start][end]; 24 | } 25 | Pair result; 26 | if (end - start == 1) { 27 | result = countPair(exp.charAt(start) == '1'); 28 | } else { 29 | int ops = (end - start - 1) / 2; 30 | result = new Pair(0, 0); 31 | for (int i = 0; i < ops; i++) { 32 | int j = start + (i * 2) + 1; 33 | Pair leftPair = doEvaluate(exp, start, j, cache); 34 | Pair rightPair = doEvaluate(exp, j + 1, end, cache); 35 | char operator = exp.charAt(j); 36 | Pair combined = combine(leftPair, rightPair, operator); 37 | result = plus(result, combined); 38 | } 39 | } 40 | cache[start][end] = result; 41 | return result; 42 | } 43 | 44 | private Pair plus(Pair p1, Pair p2) { 45 | return new Pair(p1.trueCount + p2.trueCount, p1.falseCount + p2.falseCount); 46 | } 47 | 48 | private Pair combine(Pair left, Pair right, char operator) { 49 | int tt = left.trueCount * right.trueCount; 50 | int tf = left.trueCount * right.falseCount; 51 | int ft = left.falseCount * right.trueCount; 52 | int ff = left.falseCount * right.falseCount; 53 | switch (operator) { 54 | case '&': 55 | return new Pair(tt, tf + ft + ff); 56 | case '|': 57 | return new Pair(tt + tf + ft, ff); 58 | case '^': 59 | return new Pair(tf + ft, tt + ff); 60 | default: 61 | throw new UnsupportedOperationException(); 62 | } 63 | } 64 | 65 | private Pair countPair(boolean result) { 66 | return result ? new Pair(1, 0) : new Pair(0, 1); 67 | } 68 | 69 | 70 | static class Pair { 71 | int trueCount; 72 | int falseCount; 73 | 74 | Pair(int trueCount, int falseCount) { 75 | this.trueCount = trueCount; 76 | this.falseCount = falseCount; 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/sortingsearching/_10_01_SortedMerge.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | /** 4 | * You are given two sorted arrays, A and B, where A has a large enough buffer at the end to hold B. 5 | * Write a method to merge B into A in sorted order. 6 | */ 7 | public class _10_01_SortedMerge { 8 | 9 | int[] merge(int[] big, int[] small) { 10 | int b = big.length - small.length - 1; 11 | int s = small.length - 1; 12 | int i = big.length - 1; 13 | while (b >= 0 || s >= 0) { 14 | if (b < 0) { 15 | big[i--] = small[s--]; 16 | } else if (s < 0) { 17 | break; 18 | } else { 19 | if (small[s] > big[b]) { 20 | big[i--] = small[s--]; 21 | } else { 22 | big[i--] = big[b--]; 23 | } 24 | } 25 | } 26 | return big; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/sortingsearching/_10_02_GroupAnagrams.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | /** 7 | * Write a method to sort an array of strings so that all the anagrams are next to each other. 8 | */ 9 | public class _10_02_GroupAnagrams { 10 | 11 | /** 12 | * time o(n) ( o(nklogk) when k is the max length of a word, klogk becomes constant so we have o(n)) 13 | * space o(n) 14 | */ 15 | List groupAnagrams(List words) { 16 | if (words == null || words.isEmpty()) return words; 17 | Map> anagrams = new HashMap<>(); 18 | for (String word : words) { 19 | anagrams.computeIfAbsent(sorted(word), k -> new ArrayList<>()).add(word); 20 | } 21 | return anagrams.values().stream().flatMap(List::stream).collect(Collectors.toList()); 22 | } 23 | 24 | private String sorted(String word) { 25 | char[] chars = word.toCharArray(); 26 | Arrays.sort(chars); 27 | return String.valueOf(chars); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/sortingsearching/_10_03_SearchInRotatedArray.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Given a sorted array of n integers that has been rotated an unknown number of times, 7 | * write code to find an element in the array. You may assume that the array was originally sorted in increasing order. 8 | * EXAMPLE 9 | * input:find 5 in {15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14} 10 | * output: 8 (index of 5 in the array) 11 | */ 12 | public class _10_03_SearchInRotatedArray { 13 | 14 | int find(int[] arr, int target) { 15 | if (arr == null || arr.length == 0) return -1; 16 | int start = 0; 17 | int end = arr.length - 1; 18 | while (start <= end) { 19 | if (arr[start] <= arr[end]) { 20 | return binarySearch(arr, start, end, target); 21 | } else { 22 | int middle = start + (end - start) / 2; 23 | if (arr[middle] >= arr[start]) { 24 | if (target >= arr[start] && target <= arr[middle]) { 25 | return binarySearch(arr, start, middle, target); 26 | } else { 27 | start = middle + 1; 28 | } 29 | } else { 30 | if (target >= arr[middle] && target <= arr[end]) { 31 | return binarySearch(arr, middle, end, target); 32 | } else { 33 | end = middle - 1; 34 | } 35 | } 36 | } 37 | } 38 | return -1; 39 | } 40 | 41 | private int binarySearch(int[] arr, int start, int end, int target) { 42 | return Math.max(-1, Arrays.binarySearch(arr, start, end + 1, target)); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/sortingsearching/_10_04_SortedSearch.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * You are given an array like data structure Listy which lacks a size method. 7 | * It does, however, have an elementAt(i) method that returns the element at index i in o(1) time. 8 | * If i is beyond the bounds of the data structure, it returns -1. 9 | * (For this reason, the data structure only supports positive integers.) 10 | * Given a Listy which contains sorted, positive integers, find the index at which an element x occurs. 11 | * If x occurs multiple times, you may return any index. 12 | */ 13 | public class _10_04_SortedSearch { 14 | 15 | int sortedSearch(Listy listy, int target) { 16 | if (target <= 0) return -1; 17 | return doSearch(listy, 0, 0, target); 18 | } 19 | 20 | private int doSearch(Listy listy, int start, int end, int target) { 21 | if (end < start) return -1; 22 | if (listy.at(start) == -1) return -1; 23 | if (target <= listy.at(end)) { 24 | int mid = start + (end - start) / 2; 25 | if (target == listy.at(mid)) { 26 | return mid; 27 | } else if (target < listy.at(mid)) { 28 | return doSearch(listy, start, mid - 1, target); 29 | } else { 30 | return doSearch(listy, mid + 1, end, target); 31 | } 32 | } else if (listy.at(end) == -1) { 33 | return doSearch(listy, start, start + (end - start) / 2, target); 34 | } else { 35 | return doSearch(listy, end + 1, (end + 1) * 2, target); 36 | } 37 | } 38 | 39 | static class Listy { 40 | private int[] elems; 41 | 42 | static Listy of(int... elems) { 43 | if (elems == null || Arrays.stream(elems).anyMatch(v -> v <= 0)) { 44 | throw new IllegalArgumentException("elems should contain only positive integers"); 45 | } 46 | Listy listy = new Listy(); 47 | listy.elems = elems; 48 | return listy; 49 | } 50 | 51 | int at(int i) { 52 | if (i < elems.length && i >= 0) { 53 | return elems[i]; 54 | } 55 | return -1; 56 | } 57 | 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/sortingsearching/_10_05_SparseSearch.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Given a sorted array of strings that is interspersed with empty strings, 7 | * write a method to find the location of a given string. 8 | */ 9 | public class _10_05_SparseSearch { 10 | 11 | int find(String[] arr, String target) { 12 | if (target == null || Objects.equals("", target)) return -1; 13 | return doFind(arr, target, 0, arr.length - 1); 14 | } 15 | 16 | private int doFind(String[] arr, String target, int start, int end) { 17 | if (start > end) return -1; 18 | int mid = start + (end - start) / 2; 19 | 20 | 21 | if (arr[mid].isEmpty()) { 22 | int left = mid; 23 | int right = mid; 24 | while (true) { 25 | if (left < start && right > end) return -1; 26 | if (left >= start && !arr[left].isEmpty()) { 27 | mid = left; 28 | break; 29 | } 30 | 31 | if (right <= end && !arr[right].isEmpty()) { 32 | mid = right; 33 | break; 34 | } 35 | left--; 36 | right++; 37 | } 38 | } 39 | 40 | if (arr[mid].equals(target)) { 41 | return mid; 42 | } else if (target.compareTo(arr[mid]) < 0) { 43 | return doFind(arr, target, start, mid - 1); 44 | } else { 45 | return doFind(arr, target, mid + 1, end); 46 | } 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/stackqueue/_03_01_ThreeInOne.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import java.util.NoSuchElementException; 4 | 5 | /** 6 | * Describe how you could use a single array to implement three stacks 7 | */ 8 | class _03_01_ThreeInOne { 9 | 10 | private final int[] arr; 11 | private StackInfo[] stacks; 12 | 13 | 14 | _03_01_ThreeInOne(int initSize) { 15 | arr = new int[3 * initSize]; 16 | stacks = new StackInfo[3]; 17 | for (int i = 0; i < stacks.length; i++) { 18 | stacks[i] = new StackInfo(i * initSize, initSize); 19 | } 20 | } 21 | 22 | void push(int stackNum, int val) { 23 | checkStackNum(stackNum); 24 | StackInfo stackInfo = stacks[stackNum]; 25 | if (stackInfo.isFull()) { 26 | if (isAllFull()) throw new IllegalStateException("array is full"); 27 | expand(stackNum); 28 | } 29 | arr[adjust(stackInfo.peek() + 1)] = val; 30 | stackInfo.size++; 31 | } 32 | 33 | private boolean isAllFull() { 34 | int sum = 0; 35 | for (StackInfo stack : stacks) { 36 | sum += stack.size; 37 | } 38 | return sum >= arr.length; 39 | } 40 | 41 | private void expand(int stackNum) { 42 | shift(nextStack(stackNum)); 43 | stacks[stackNum].capacity++; 44 | } 45 | 46 | private int adjust(int i) { 47 | return ((i % arr.length) + arr.length) % arr.length; 48 | } 49 | 50 | private void shift(int stackNumb) { 51 | StackInfo stackInfo = stacks[stackNumb]; 52 | if (stackInfo.isFull()) { 53 | shift(nextStack(stackNumb)); 54 | } 55 | int cur = adjust(stackInfo.peek() + 1); 56 | while (cur != stackInfo.start) { 57 | int previous = adjust(cur - 1); 58 | arr[cur] = arr[previous]; 59 | cur = previous; 60 | } 61 | stackInfo.start = adjust(stackInfo.start + 1); 62 | } 63 | 64 | private int nextStack(int stackNumb) { 65 | return (stackNumb + 1) % stacks.length; 66 | } 67 | 68 | private void checkStackNum(int stackNum) { 69 | if (stackNum >= stacks.length || stackNum < 0) 70 | throw new IllegalArgumentException("Stack doesn't exist " + stackNum + " 0 - 2"); 71 | } 72 | 73 | int pop(int stackNum) { 74 | checkStackNum(stackNum); 75 | StackInfo stackInfo = stacks[stackNum]; 76 | if (stackInfo.isEmpty()) throw new NoSuchElementException("stack is empty"); 77 | int peekIndex = stackInfo.peek() % arr.length; 78 | int peek = arr[peekIndex]; 79 | arr[peekIndex] = 0; 80 | stackInfo.size--; 81 | return peek; 82 | } 83 | 84 | private static class StackInfo { 85 | int start; 86 | int size; 87 | int capacity; 88 | 89 | StackInfo(int start, int capacity) { 90 | this.start = start; 91 | this.capacity = capacity; 92 | } 93 | 94 | int peek() { 95 | return start + size - 1; 96 | } 97 | 98 | boolean isEmpty() { 99 | return size == 0; 100 | } 101 | 102 | boolean isFull() { 103 | return size == capacity; 104 | } 105 | } 106 | 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/stackqueue/_03_02_MinStack.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * How would you design a stack which, in addition to push and pop, has a function min which returns the minimum element? Push, pop and min should all operate in 0(1) time. 7 | */ 8 | class _03_02_MinStack { 9 | 10 | private Stack vals = new Stack<>(); 11 | private Stack mins = new Stack<>(); 12 | 13 | void push(int val) { 14 | vals.push(val); 15 | if (mins.isEmpty() || val < mins.peek()) { 16 | mins.push(val); 17 | } 18 | } 19 | 20 | int pop() { 21 | int val = vals.pop(); 22 | if (val == mins.peek()) { 23 | mins.pop(); 24 | } 25 | return val; 26 | } 27 | 28 | int min() { 29 | return mins.peek(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/stackqueue/_03_03_StackOfPlates.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import java.util.*; 4 | 5 | class _03_03_StackOfPlates { 6 | 7 | private final int threshold; 8 | private final List> stacks; 9 | 10 | _03_03_StackOfPlates(int threshold) { 11 | this.threshold = threshold; 12 | stacks = new ArrayList<>(); 13 | } 14 | 15 | void push(int val) { 16 | if (stacks.isEmpty() || isLastStackFull()) { 17 | stacks.add(new LinkedList<>()); 18 | } 19 | lastStack().push(val); 20 | } 21 | 22 | private boolean isLastStackFull() { 23 | return lastStack().size() == threshold; 24 | } 25 | 26 | private Deque lastStack() { 27 | return stacks.get(stacks.size() - 1); 28 | } 29 | 30 | int pop() { 31 | if (stacks.isEmpty()) throw new EmptyStackException(); 32 | Deque stack = lastStack(); 33 | int val = stack.pop(); 34 | if (stack.isEmpty()) removeLast(); 35 | return val; 36 | } 37 | 38 | int popAt(int stackNum) { 39 | int val = stacks.get(stackNum).pop(); 40 | for (int i = stackNum; i < stacks.size(); i++) { 41 | if (i + 1 < stacks.size()) { 42 | Deque nextStack = stacks.get(i + 1); 43 | stacks.get(i).push(nextStack.removeLast()); 44 | } 45 | } 46 | if (lastStack().isEmpty()) { 47 | removeLast(); 48 | } 49 | return val; 50 | } 51 | 52 | private void removeLast() { 53 | stacks.remove(stacks.size() - 1); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/stackqueue/_03_04_QueueViaStacks.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import java.util.Stack; 4 | 5 | class _03_04_QueueViaStacks { 6 | 7 | private final Stack inbox = new Stack<>(); 8 | private final Stack outbox = new Stack<>(); 9 | 10 | void enqueue(int val) { 11 | inbox.add(val); 12 | } 13 | 14 | int size() { 15 | return inbox.size() + outbox.size(); 16 | } 17 | 18 | int peek() { 19 | fillOutbox(); 20 | return outbox.peek(); 21 | } 22 | 23 | int dequeue() { 24 | fillOutbox(); 25 | return outbox.pop(); 26 | } 27 | 28 | private void fillOutbox() { 29 | if (outbox.isEmpty()) { 30 | while (!inbox.isEmpty()) { 31 | outbox.push(inbox.pop()); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/stackqueue/_03_05_SortStack.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Write a program to sort a stack such that the smallest items are on the top. 7 | * You can use an additional temporary stack, 8 | * but you may not copy the elements into any other data structure (such as an array). 9 | * The stack supports the following operations: push, pop, peek, and isEmpty. 10 | */ 11 | class _03_05_SortStack { 12 | 13 | Stack sort(Stack stack) { 14 | Stack tmp = new Stack<>(); 15 | while (!stack.isEmpty()) { 16 | int top = stack.pop(); 17 | if (!tmp.isEmpty() && top > tmp.peek()) { 18 | while (!tmp.isEmpty()) { 19 | stack.push(tmp.pop()); 20 | } 21 | } 22 | tmp.push(top); 23 | } 24 | return tmp; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/stackqueue/_03_06_AnimalShelter.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * An animal shelter, which holds only dogs and cats, operates on a strictly "first in, first out" basis. 7 | * People must adopt either the "oldest" (based on arrival time) of all animals at the shelter, 8 | * or they can select whether they would prefer a dog or a cat (and will receive the oldest animal of that type). 9 | * They cannot select which specific animal they would like. 10 | *

11 | * Create the data structures to maintain this system and implement operations such as 12 | * enqueue, dequeueAny, dequeueDog, and dequeueCat. 13 | *

14 | * You may use the built-in Linked list data structure. 15 | */ 16 | class _03_06_AnimalShelter { 17 | 18 | private int counter = 0; 19 | private LinkedList dogs = new LinkedList<>(); 20 | private LinkedList cats = new LinkedList<>(); 21 | 22 | void enqueueDog(int num) { 23 | dogs.add(new Animal(num, counter++)); 24 | } 25 | 26 | void enqueueCat(int num) { 27 | cats.add(new Animal(num, counter++)); 28 | } 29 | 30 | int dequeueAny() { 31 | if (dogs.isEmpty()) { 32 | return cats.remove().num; 33 | } else if (cats.isEmpty()) { 34 | return dogs.remove().num; 35 | } else { 36 | if (dogs.peek().counter < cats.peek().counter) { 37 | return dogs.remove().num; 38 | } else { 39 | return cats.remove().num; 40 | } 41 | } 42 | } 43 | 44 | int dequeueDog() { 45 | return dogs.remove().num; 46 | } 47 | 48 | int dequeueCat() { 49 | return cats.remove().num; 50 | } 51 | 52 | static class Animal { 53 | int num; 54 | int counter; 55 | 56 | Animal(int num, int counter) { 57 | this.num = num; 58 | this.counter = counter; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/treegraph/BinaryTreeNode.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | class BinaryTreeNode { 4 | int val; 5 | BinaryTreeNode left; 6 | BinaryTreeNode right; 7 | 8 | BinaryTreeNode(int val) { 9 | this.val = val; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/treegraph/Digraph.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | class Digraph { 8 | 9 | private final List> adjacent; 10 | 11 | Digraph(int vertexCount) { 12 | adjacent = new ArrayList<>(vertexCount); 13 | for (int i = 0; i < vertexCount; i++) { 14 | adjacent.add(new LinkedList<>()); 15 | } 16 | } 17 | 18 | void addEdge(int from, int to) { 19 | adjacent.get(from).add(to); 20 | } 21 | 22 | Iterable adjacent(int v) { 23 | return adjacent.get(v); 24 | } 25 | 26 | int size() { 27 | return adjacent.size(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/treegraph/ParentAwareBinaryTreeNode.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | class ParentAwareBinaryTreeNode { 4 | ParentAwareBinaryTreeNode parent; 5 | ParentAwareBinaryTreeNode left; 6 | ParentAwareBinaryTreeNode right; 7 | int val; 8 | 9 | ParentAwareBinaryTreeNode(int val) { 10 | this.val = val; 11 | } 12 | 13 | ParentAwareBinaryTreeNode addLeft(int val) { 14 | ParentAwareBinaryTreeNode left = new ParentAwareBinaryTreeNode(val); 15 | this.left = left; 16 | left.parent = this; 17 | return left; 18 | } 19 | 20 | ParentAwareBinaryTreeNode addRight(int val) { 21 | ParentAwareBinaryTreeNode right = new ParentAwareBinaryTreeNode(val); 22 | this.right = right; 23 | right.parent = this; 24 | return right; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_01_RouteBetweenNodes.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | /** 4 | * Given a directed graph, design an algorithm to find out whether 5 | * there is a route between two nodes. 6 | */ 7 | class _04_01_RouteBetweenNodes { 8 | 9 | private final Digraph digraph; 10 | private boolean[] visited; 11 | 12 | _04_01_RouteBetweenNodes(Digraph digraph) { 13 | this.digraph = digraph; 14 | } 15 | 16 | boolean hasRoute(int source, int target) { 17 | visited = new boolean[digraph.size()]; 18 | dfs(source); 19 | return visited[target]; 20 | } 21 | 22 | private void dfs(int node) { 23 | visited[node] = true; 24 | for (int n : digraph.adjacent(node)) { 25 | if (!visited[n]) { 26 | dfs(n); 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_02_MinimalTree.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | /** 4 | * Given a sorted (increasing order) array with unique integer elements, write an algorithm 5 | * to create a binary search tree with minimal height. 6 | */ 7 | class _04_02_MinimalTree { 8 | 9 | // time o(N), space o(logN) 10 | BinaryTreeNode buildMinimalTree(int[] vals) { 11 | return build(vals, 0, vals.length - 1); 12 | } 13 | 14 | private BinaryTreeNode build(int[] vals, int start, int end) { 15 | if (start == end) { 16 | return new BinaryTreeNode(vals[start]); 17 | } else if (start > end) { 18 | return null; 19 | } else { 20 | int mid = start + (end - start) / 2; 21 | BinaryTreeNode binaryTreeNode = new BinaryTreeNode(vals[mid]); 22 | binaryTreeNode.left = build(vals, start, mid - 1); 23 | binaryTreeNode.right = build(vals, mid + 1, end); 24 | return binaryTreeNode; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_03_ListOfDepths.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | class _04_03_ListOfDepths { 8 | 9 | //time o(N) space o(N) 10 | List> create(BinaryTreeNode node) { 11 | List> result = new ArrayList<>(); 12 | dfs(result, node, 0); 13 | return result; 14 | } 15 | 16 | private void dfs(List> result, BinaryTreeNode node, int depth) { 17 | if (node == null) return; 18 | if (result.size() == depth) { 19 | result.add(new LinkedList<>()); 20 | } 21 | result.get(depth).add(node.val); 22 | dfs(result, node.left, depth + 1); 23 | dfs(result, node.right, depth + 1); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_04_CheckBalanced.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | /** 4 | * Implement a function to check if a binary tree is balanced. 5 | * For the purposes of this question, a balanced tree is defined to be a tree such that 6 | * the heights of the two subtrees of any node never differ by more than one. 7 | */ 8 | class _04_04_CheckBalanced { 9 | 10 | //time o(N) space o(logN) 11 | boolean isBalanced(BinaryTreeNode root) { 12 | return isBalancedWithHeight(root) != -1; 13 | } 14 | 15 | private int isBalancedWithHeight(BinaryTreeNode root) { 16 | if (root == null) return 0; 17 | int hl = isBalancedWithHeight(root.left); 18 | int hr = isBalancedWithHeight(root.right); 19 | if (Math.abs(hl - hr) > 1 || hr == -1 || hl == -1) return -1; 20 | return Math.max(hl, hr) + 1; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_05_ValidateBST.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | /** 4 | * Implement a function to check if a binary tree is a binary search tree. 5 | */ 6 | class _04_05_ValidateBST { 7 | 8 | private int pre = Integer.MIN_VALUE; 9 | 10 | boolean isBST(BinaryTreeNode root) { 11 | return inOrder(root); 12 | } 13 | 14 | private boolean inOrder(BinaryTreeNode node) { 15 | if (node == null) return true; 16 | 17 | if (!inOrder(node.left)) return false; 18 | if (node.val < pre) return false; 19 | pre = node.val; 20 | return inOrder(node.right); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_06_Successor.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | /** 4 | * Write an algorithm to find the "next" node (i.e., in-order successor) of a given node in a binary search tree. 5 | * You may assume that each node has a link to its parent. 6 | */ 7 | class _04_06_Successor { 8 | ParentAwareBinaryTreeNode findInOrderSuccessor(ParentAwareBinaryTreeNode node) { 9 | if (node == null) return null; 10 | if (node.right != null) { 11 | return leftMost(node.right); 12 | } 13 | ParentAwareBinaryTreeNode p = node.parent; 14 | while (p != null && p.parent != null) { 15 | if (p.parent.left == p) { 16 | return p.parent; 17 | } else { 18 | p = p.parent; 19 | } 20 | } 21 | return p; 22 | } 23 | 24 | private ParentAwareBinaryTreeNode leftMost(ParentAwareBinaryTreeNode node) { 25 | if (node == null) return null; 26 | while (node.left != null) { 27 | node = node.left; 28 | } 29 | return node; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_07_BuildOrder.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * You are given a list of projects and a list of dependencies 8 | * (which is a list of pairs of projects, where the second project is dependent on the first project). 9 | * All of a project's dependencies must be built before the project is. 10 | * Find a build order that will allow the projects to be built. 11 | * If there is no valid build order, return an error. 12 | */ 13 | class _04_07_BuildOrder { 14 | 15 | private boolean onStack[]; 16 | private boolean visited[]; 17 | private Digraph digraph; 18 | private LinkedList topological = new LinkedList<>(); 19 | 20 | List findBuildOrder(Digraph digraph) { 21 | this.digraph = digraph; 22 | onStack = new boolean[digraph.size()]; 23 | visited = new boolean[digraph.size()]; 24 | for (int i = 0; i < digraph.size(); i++) { 25 | if (!visited[i]) { 26 | dfs(i); 27 | } 28 | } 29 | if (topological.size() != digraph.size()) return null; 30 | return topological; 31 | } 32 | 33 | private void dfs(int v) { 34 | onStack[v] = true; 35 | visited[v] = true; 36 | for (Integer adj : digraph.adjacent(v)) { 37 | if (visited[adj] && onStack[adj]) { 38 | return; 39 | } 40 | if (!visited[adj]) { 41 | dfs(adj); 42 | } 43 | } 44 | onStack[v] = false; 45 | topological.add(v); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_08_FindCommonAncestor.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | /** 4 | * Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. 5 | * Avoid storing additional nodes in a data structure. NOTE: This is not necessarily a binary search tree. 6 | */ 7 | class _04_08_FindCommonAncestor { 8 | 9 | ParentAwareBinaryTreeNode findCommonAncestor(ParentAwareBinaryTreeNode a, ParentAwareBinaryTreeNode b) { 10 | int da = depthOf(a); 11 | int db = depthOf(b); 12 | ParentAwareBinaryTreeNode deeper = da > db ? a : b; 13 | ParentAwareBinaryTreeNode other = da > db ? b : a; 14 | ParentAwareBinaryTreeNode c = goUp(deeper, Math.abs(da - db)); 15 | while (other != null && c != null) { 16 | if (other == c) return other; 17 | other = other.parent; 18 | c = c.parent; 19 | } 20 | return null; 21 | } 22 | 23 | private ParentAwareBinaryTreeNode goUp(ParentAwareBinaryTreeNode deeper, int delta) { 24 | while (delta > 0 && deeper != null) { 25 | deeper = deeper.parent; 26 | delta--; 27 | } 28 | return deeper; 29 | } 30 | 31 | private int depthOf(ParentAwareBinaryTreeNode node) { 32 | int depth = 0; 33 | while (node != null) { 34 | depth++; 35 | node = node.parent; 36 | } 37 | return depth; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_09_BSTSequences.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * A binary search tree was created by traversing through an array from left to right and inserting each element. 9 | * Given a binary search tree with distinct elements, print all possible arrays that could have led to this tree. 10 | */ 11 | class _04_09_BSTSequences { 12 | 13 | List> sequences(BinaryTreeNode root) { 14 | List> result = new ArrayList<>(); 15 | if (root == null) { 16 | result.add(new LinkedList<>()); 17 | return result; 18 | } 19 | LinkedList prefix = new LinkedList<>(); 20 | prefix.add(root.val); 21 | List> leftSeqs = sequences(root.left); 22 | List> rightSeqs = sequences(root.right); 23 | for (LinkedList leftSeq : leftSeqs) { 24 | for (LinkedList rightSeq : rightSeqs) { 25 | List> weaved = new ArrayList<>(); 26 | weave(leftSeq, rightSeq, weaved, prefix); 27 | result.addAll(weaved); 28 | } 29 | } 30 | return result; 31 | } 32 | 33 | private void weave(LinkedList first, LinkedList second, List> results, LinkedList prefix) { 34 | if (first.isEmpty() || second.isEmpty()) { 35 | LinkedList result = new LinkedList<>(prefix); 36 | result.addAll(first); 37 | result.addAll(second); 38 | results.add(result); 39 | return; 40 | } 41 | 42 | Integer headFirst = first.removeFirst(); 43 | prefix.addLast(headFirst); 44 | weave(first, second, results, prefix); 45 | prefix.removeLast(); 46 | first.addFirst(headFirst); 47 | 48 | Integer headSecond = second.removeFirst(); 49 | prefix.addLast(headSecond); 50 | weave(first, second, results, prefix); 51 | prefix.removeLast(); 52 | second.addFirst(headSecond); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_10_CheckSubTree.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | /** 4 | * T1 and T2 are two very large binary trees, with T1 much bigger than T2. Create an 5 | * algorithm to determine if T2 is a subtree of T1. 6 | *

7 | * A tree T2 is a subtree of T1 if there exists a node n in T1 such that the subtree of n is identical to T2. 8 | * That is, if you cut off the tree at node n, the two trees would be identical. 9 | */ 10 | class _04_10_CheckSubTree { 11 | 12 | private StringBuilder sb; 13 | 14 | boolean isSubTree(BinaryTreeNode a, BinaryTreeNode b) { 15 | sb = new StringBuilder(); 16 | preOrder(a); 17 | String preorderA = sb.toString(); 18 | sb = new StringBuilder(); 19 | preOrder(b); 20 | String preorderB = sb.toString(); 21 | return preorderA.contains(preorderB); 22 | } 23 | 24 | 25 | private void preOrder(BinaryTreeNode a) { 26 | if (a == null) { 27 | sb.append('x'); 28 | } else { 29 | sb.append(a.val); 30 | preOrder(a.left); 31 | preOrder(a.right); 32 | } 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_11_RandomNode.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * You are implementing a binary tree class from scratch 7 | * which, in addition to insert, find, and delete, has a method getRandomNode() 8 | * which returns a random node from the tree. 9 | *

10 | * All nodes should be equally likely to be chosen. 11 | * Design and implement an algorithm for getRandomNode, 12 | * and explain how you would implement the rest of the methods. 13 | */ 14 | class _04_11_RandomNode { 15 | 16 | public static class Node { 17 | private int size = 1; 18 | private Node left; 19 | private Node right; 20 | private int val; 21 | 22 | Node(int val) { 23 | this.val = val; 24 | } 25 | 26 | void insert(int val) { 27 | if (val <= this.val) { 28 | if (left != null) { 29 | left.insert(val); 30 | } else { 31 | left = new Node(val); 32 | } 33 | } else { 34 | if (right != null) { 35 | right.insert(val); 36 | } else { 37 | right = new Node(val); 38 | } 39 | } 40 | size++; 41 | } 42 | 43 | Node find(int val) { 44 | if (val == this.val) { 45 | return this; 46 | } else if (val <= this.val) { 47 | return left == null ? null : left.find(val); 48 | } else { 49 | return right == null ? null : right.find(val); 50 | } 51 | } 52 | 53 | Node getIthNode(int i) { 54 | int leftSize = left == null ? 0 : left.size; 55 | if (i < leftSize) { 56 | return left.getIthNode(i); 57 | } else if (i == leftSize) { 58 | return this; 59 | } else { 60 | return right.getIthNode(i - left.size - 1); 61 | } 62 | } 63 | 64 | public int getVal() { 65 | return val; 66 | } 67 | } 68 | 69 | static class Tree { 70 | private Node root; 71 | 72 | void insert(int val) { 73 | if (root == null) root = new Node(val); 74 | root.insert(val); 75 | } 76 | 77 | Node find(int val) { 78 | return root == null ? null : root.find(val); 79 | } 80 | 81 | Node getRandomNode() { 82 | Random random = new Random(); 83 | int i = random.nextInt(root.size); 84 | return root.getIthNode(i); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/treegraph/_04_12_PathsWithSum.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * You are given a binary tree in which each node contains an integer value (which might be positive or negative). 8 | * Design an algorithm to count the number of paths that target to a given value. 9 | * The path does not need to start or end at the root or a leaf, but it must go downwards 10 | * (traveling only from parent nodes to child nodes). 11 | */ 12 | class _04_12_PathsWithSum { 13 | 14 | 15 | private int target; 16 | private Map runningSumToCount; 17 | private int count; 18 | 19 | int countPathWithSum(BinaryTreeNode node, int sum) { 20 | count = 0; 21 | runningSumToCount = new HashMap<>(); 22 | runningSumToCount.put(0, 1); 23 | target = sum; 24 | countHelper(node, 0); 25 | return count; 26 | } 27 | 28 | private void countHelper(BinaryTreeNode node, int acc) { 29 | if (node == null) return; 30 | int runningSum = acc + node.val; 31 | runningSumToCount.merge(runningSum, 1, Math::addExact); 32 | count += runningSumToCount.getOrDefault(runningSum - target, 0); 33 | countHelper(node.left, runningSum); 34 | countHelper(node.right, runningSum); 35 | runningSumToCount.computeIfPresent(runningSum, (k, v) -> v == 1 ? null : v - 1); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_01_IsUniqueTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _01_01_IsUniqueTest { 9 | 10 | private _01_01_IsUnique s = new _01_01_IsUnique(); 11 | 12 | @Test 13 | public void withEmptyString() { 14 | assertTrue(s.isUnique("")); 15 | } 16 | 17 | @Test 18 | public void withUniqueString() { 19 | assertTrue(s.isUnique("abcde")); 20 | } 21 | 22 | @Test 23 | public void withDuplication() { 24 | assertFalse(s.isUnique("abcda")); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_02_CheckPermutationTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _01_02_CheckPermutationTest { 9 | 10 | private _01_02_CheckPermutation s = new _01_02_CheckPermutation(); 11 | 12 | @Test 13 | public void withEmptyString() { 14 | assertTrue(s.check("", "")); 15 | } 16 | 17 | @Test 18 | public void withOneSingleChar() { 19 | assertTrue(s.check("a", "a")); 20 | } 21 | 22 | @Test 23 | public void withOneSingleDifferentChar() { 24 | assertFalse(s.check("a", "b")); 25 | } 26 | 27 | @Test 28 | public void withThreeChars() { 29 | assertTrue(s.check("abc", "bac")); 30 | } 31 | 32 | @Test 33 | public void withRepeatingChars() { 34 | assertTrue(s.check("aabbc", "bcaba")); 35 | } 36 | 37 | @Test 38 | public void withDifferentLength() { 39 | assertFalse(s.check("abc", "ab")); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_03_URLifyTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertArrayEquals; 6 | 7 | public class _01_03_URLifyTest { 8 | 9 | private _01_03_URLify s = new _01_03_URLify(); 10 | 11 | @Test 12 | public void withNoSpace() { 13 | assertArrayEquals("hello".toCharArray(), s.urlify("hello".toCharArray(), 5)); 14 | } 15 | 16 | @Test(expected = IllegalArgumentException.class) 17 | public void withInsufficientLength() { 18 | s.urlify("hello world ".toCharArray(), 11); 19 | } 20 | 21 | @Test 22 | public void withOneSpace() { 23 | assertArrayEquals("hello%20world".toCharArray(), s.urlify("hello world ".toCharArray(), 11)); 24 | } 25 | 26 | @Test 27 | public void withTwoSpaces() { 28 | assertArrayEquals("hello%20world%20bob".toCharArray(), s.urlify("hello world bob ".toCharArray(), 15)); 29 | } 30 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_04_PalindromePermutationTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertTrue; 6 | 7 | public class _01_04_PalindromePermutationTest { 8 | 9 | private _01_04_PalindromePermutation s = new _01_04_PalindromePermutation(); 10 | 11 | @Test 12 | public void withEmpty() { 13 | assertTrue(s.check("")); 14 | } 15 | 16 | @Test 17 | public void withOneChar() { 18 | assertTrue(s.check("a")); 19 | } 20 | 21 | @Test 22 | public void withTwoWords_OddLetters() { 23 | assertTrue(s.check("acto tac")); 24 | } 25 | 26 | @Test 27 | public void withTwoWords_OddLetters_ThreeOccurences() { 28 | assertTrue(s.check("act atac")); 29 | } 30 | 31 | @Test 32 | public void withTwoWords_EvenLetters() { 33 | assertTrue(s.check("act cat")); 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_05_OneAwayTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _01_05_OneAwayTest { 9 | 10 | private _01_05_OneAway s = new _01_05_OneAway(); 11 | 12 | @Test 13 | public void withEmpty() { 14 | assertTrue(s.isOneAway("", "")); 15 | } 16 | 17 | @Test 18 | public void withOneEmpty() { 19 | assertTrue(s.isOneAway("", "b")); 20 | } 21 | 22 | @Test 23 | public void withTwoSingleWords() { 24 | assertTrue(s.isOneAway("a", "b")); 25 | } 26 | 27 | @Test 28 | public void withOneInsertion() { 29 | assertTrue(s.isOneAway("pae", "pale")); 30 | } 31 | 32 | @Test 33 | public void withOneDeletion() { 34 | assertTrue(s.isOneAway("pales", "paes")); 35 | } 36 | 37 | @Test 38 | public void withOneReplace() { 39 | assertTrue(s.isOneAway("pawe", "pave")); 40 | } 41 | 42 | @Test 43 | public void withMoreEdits() { 44 | assertFalse(s.isOneAway("paxye", "pamne")); 45 | } 46 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_06_StringCompressionTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _01_06_StringCompressionTest { 8 | 9 | private _01_06_StringCompression s = new _01_06_StringCompression(); 10 | 11 | @Test 12 | public void withOneSingleChar() { 13 | assertEquals("a", s.compress("a")); 14 | } 15 | 16 | @Test 17 | public void withTwoChars() { 18 | assertEquals("aa", s.compress("aa")); 19 | } 20 | 21 | @Test 22 | public void withThreeChars() { 23 | assertEquals("3a", s.compress("aaa")); 24 | } 25 | 26 | @Test 27 | public void withDifferentChars() { 28 | assertEquals("aaab", s.compress("aaab")); 29 | } 30 | 31 | @Test 32 | public void withDifferentChars_RepeatingSeveralTimes() { 33 | assertEquals("3a2b", s.compress("aaabb")); 34 | } 35 | 36 | @Test 37 | public void withDifferentChars_RepeatingInMoreSeqs() { 38 | assertEquals("3a2b2a", s.compress("aaabbaa")); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_07_RotateMatrixTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class _01_07_RotateMatrixTest { 10 | 11 | private _01_07_RotateMatrix s = new _01_07_RotateMatrix(); 12 | 13 | @Test 14 | public void withOneOne() { 15 | assertTrue(Arrays.deepEquals(new int[][]{{1}}, s.rotate(new int[][]{{1}}))); 16 | } 17 | 18 | @Test 19 | public void withTwoTwo() { 20 | assertTrue(Arrays.deepEquals(new int[][]{ 21 | {3, 1}, 22 | {4, 2}}, 23 | s.rotate(new int[][]{ 24 | {1, 2}, 25 | {3, 4}}))); 26 | } 27 | 28 | @Test 29 | public void withThreeThree() { 30 | assertTrue(Arrays.deepEquals(new int[][]{ 31 | {7, 4, 1}, 32 | {8, 5, 2}, 33 | {9, 6, 3} 34 | }, 35 | s.rotate(new int[][]{ 36 | {1, 2, 3}, 37 | {4, 5, 6}, 38 | {7, 8, 9}}))); 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_08_ZeroMatrixTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class _01_08_ZeroMatrixTest { 10 | 11 | @Test 12 | public void withEmpty() { 13 | assertTrue(Arrays.deepEquals(new int[][]{{}}, new _01_08_ZeroMatrix().zero(new int[][]{{}}))); 14 | } 15 | 16 | 17 | @Test 18 | public void withOneOne() { 19 | assertTrue(Arrays.deepEquals(new int[][]{{1}}, new _01_08_ZeroMatrix().zero(new int[][]{{1}}))); 20 | } 21 | 22 | @Test 23 | public void withOneOne_Zero() { 24 | assertTrue(Arrays.deepEquals(new int[][]{{0}}, new _01_08_ZeroMatrix().zero(new int[][]{{0}}))); 25 | } 26 | 27 | @Test 28 | public void withOneTwo() { 29 | assertTrue(Arrays.deepEquals(new int[][]{{0, 0}}, new _01_08_ZeroMatrix().zero(new int[][]{{0, 0}}))); 30 | } 31 | 32 | @Test 33 | public void withTwoTwo() { 34 | assertTrue(Arrays.deepEquals(new int[][]{{0, 0}, {0, 1}}, new _01_08_ZeroMatrix().zero(new int[][]{{0, 1}, {1, 1}}))); 35 | } 36 | 37 | @Test 38 | public void withThreeTree() { 39 | assertTrue(Arrays.deepEquals( 40 | new int[][]{ 41 | {1, 0, 3}, 42 | {0, 0, 0}, 43 | {7, 0, 9}}, new _01_08_ZeroMatrix().zero( 44 | new int[][]{ 45 | {1, 2, 3}, 46 | {4, 0, 6}, 47 | {7, 8, 9}}))); 48 | } 49 | } -------------------------------------------------------------------------------- /src/test/java/arraystring/_01_09_StringRotationTest.java: -------------------------------------------------------------------------------- 1 | package arraystring; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _01_09_StringRotationTest { 9 | 10 | private _01_09_StringRotation s = new _01_09_StringRotation(); 11 | 12 | @Test 13 | public void withEmpty() { 14 | assertTrue(s.rotated("", "")); 15 | } 16 | 17 | @Test 18 | public void withSameWord() { 19 | assertTrue(s.rotated("hello", "hello")); 20 | } 21 | 22 | @Test 23 | public void withRotated() { 24 | assertTrue(s.rotated("hello", "llohe")); 25 | } 26 | 27 | @Test 28 | public void withSubstring_ButDifferentSize() { 29 | assertFalse(s.rotated("hello", "llo")); 30 | } 31 | 32 | @Test 33 | public void withDifferentWords() { 34 | assertFalse(s.rotated("hello", "world")); 35 | } 36 | 37 | @Test 38 | public void withNotRotated() { 39 | assertFalse(s.rotated("hello", "oehll")); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_01_InsertionTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _05_01_InsertionTest { 8 | 9 | private _05_01_Insertion s = new _05_01_Insertion(); 10 | 11 | @Test 12 | public void withZeros() { 13 | assertEquals(0, s.insert(0, 0, 2, 5)); 14 | } 15 | 16 | @Test 17 | public void withLowInsertion() { 18 | int n = 0x00_00_69_00; 19 | int m = 0x00_00_00_b3; 20 | int x = 0x00_00_69_b3; 21 | int i = 0; 22 | int j = 7; 23 | assertEquals(x, s.insert(n, m, i, j)); 24 | } 25 | 26 | @Test 27 | public void withHighInsertion() { 28 | int n = 0x00_00_69_00; 29 | int m = 0x00_00_00_b3; 30 | int x = 0x00_b3_69_00; 31 | int i = 16; 32 | int j = 23; 33 | assertEquals(x, s.insert(n, m, i, j)); 34 | } 35 | 36 | @Test 37 | public void withMiddleInsertion() { 38 | int n = 0x00_00_69_00; 39 | int m = 0x00_00_00_b3; 40 | int x = 0x00_00_6b_30; 41 | int i = 4; 42 | int j = 11; 43 | assertEquals(x, s.insert(n, m, i, j)); 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_02_BinaryToStringTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _05_02_BinaryToStringTest { 8 | 9 | private _05_02_BinaryToString s = new _05_02_BinaryToString(); 10 | 11 | @Test 12 | public void withZero() { 13 | assertEquals("ERROR", s.print(0)); 14 | } 15 | 16 | @Test 17 | public void withOne() { 18 | assertEquals("ERROR", s.print(1)); 19 | } 20 | 21 | @Test 22 | public void withOneBit() { 23 | assertEquals(".1", s.print(0.5)); 24 | } 25 | 26 | @Test 27 | public void withTwoBits() { 28 | assertEquals(".11", s.print(0.75)); 29 | } 30 | 31 | @Test 32 | public void withThreeBits() { 33 | assertEquals(".101", s.print(0.625)); 34 | } 35 | 36 | @Test 37 | public void withUndoable() { 38 | assertEquals("ERROR", s.print(0.1)); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_03_FilpBitToWinTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _05_03_FilpBitToWinTest { 8 | 9 | private _05_03_FlipBitToWin s = new _05_03_FlipBitToWin(); 10 | 11 | @Test 12 | public void withZero() { 13 | assertEquals(1, s.flip(0)); 14 | } 15 | 16 | @Test 17 | public void withAllOnes() { 18 | assertEquals(32, s.flip(-1)); 19 | } 20 | 21 | @Test 22 | public void testWithOne() { 23 | assertEquals(2, s.flip(1)); 24 | } 25 | 26 | @Test 27 | public void testWithOneSegment() { 28 | assertEquals(4, s.flip(0x0000_000b)); 29 | } 30 | 31 | @Test 32 | public void testWithTwoSegments() { 33 | assertEquals(5, s.flip(0x00b8_000b)); 34 | } 35 | 36 | @Test 37 | public void WithContinuesSegment() { 38 | assertEquals(8, s.flip(0x0000_F700)); 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_04_NextBiggerNumberTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _05_04_NextBiggerNumberTest { 8 | 9 | private _05_04_NextBiggerNumber s = new _05_04_NextBiggerNumber(); 10 | 11 | @Test 12 | public void withOne() { 13 | assertEquals(2, s.nextBigger(1)); 14 | } 15 | 16 | @Test 17 | public void withIntegerTooBig() { 18 | assertEquals(-1, s.nextBigger(0x4000_0000)); 19 | } 20 | 21 | @Test 22 | public void withTen() { 23 | assertEquals(12, s.nextBigger(10)); 24 | } 25 | 26 | @Test 27 | public void withManyOnesZeros() { 28 | assertEquals(0x0008_ff03, s.nextBigger(0x0008_fee0)); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_04_NextSmallerNumberTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _05_04_NextSmallerNumberTest { 8 | 9 | private _05_04_NextSmallerNumber s = new _05_04_NextSmallerNumber(); 10 | 11 | @Test 12 | public void withOne() { 13 | assertEquals(-1, s.nextSmaller(1)); 14 | } 15 | 16 | @Test 17 | public void withIntegerTooSmall() { 18 | assertEquals(-1, s.nextSmaller(3)); 19 | } 20 | 21 | @Test 22 | public void withTen() { 23 | assertEquals(9, s.nextSmaller(10)); 24 | } 25 | 26 | @Test 27 | public void withManyOnesZeros() { 28 | assertEquals(0x0008_fee0, s.nextSmaller(0x0008_ff03)); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_05_DebuggerTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _05_05_DebuggerTest { 9 | 10 | private _05_05_Debugger s = new _05_05_Debugger(); 11 | 12 | @Test 13 | public void withZero() { 14 | assertTrue(s.debug(0)); 15 | } 16 | 17 | @Test 18 | public void withOne() { 19 | assertTrue(s.debug(1)); 20 | } 21 | 22 | @Test 23 | public void withTwo() { 24 | assertTrue(s.debug(2)); 25 | } 26 | 27 | @Test 28 | public void withThree() { 29 | assertFalse(s.debug(3)); 30 | } 31 | 32 | @Test 33 | public void withFour() { 34 | assertTrue(s.debug(4)); 35 | } 36 | 37 | @Test 38 | public void withFive() { 39 | assertFalse(s.debug(5)); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_06_ConversionTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _05_06_ConversionTest { 8 | 9 | private _05_06_Conversion s = new _05_06_Conversion(); 10 | 11 | @Test 12 | public void withZeroAndOne() { 13 | assertEquals(1, s.convert(0, 1)); 14 | } 15 | 16 | @Test 17 | public void withOneAndOne() { 18 | assertEquals(0, s.convert(1, 1)); 19 | } 20 | 21 | @Test 22 | public void withOneAndTwo() { 23 | assertEquals(2, s.convert(1, 2)); 24 | } 25 | 26 | @Test 27 | public void withZeroAndThree() { 28 | assertEquals(2, s.convert(0, 3)); 29 | } 30 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_07_PairwiseSwapTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _05_07_PairwiseSwapTest { 8 | 9 | private _05_07_PairwiseSwap s = new _05_07_PairwiseSwap(); 10 | 11 | @Test 12 | public void withZero() { 13 | assertEquals(0, s.swap(0)); 14 | } 15 | 16 | @Test 17 | public void withOne() { 18 | assertEquals(2, s.swap(1)); 19 | } 20 | 21 | @Test 22 | public void withTwo() { 23 | assertEquals(1, s.swap(2)); 24 | } 25 | 26 | @Test 27 | public void withTen() { 28 | assertEquals(5, s.swap(10)); 29 | } 30 | 31 | @Test 32 | public void withTenEveryWhere() { 33 | assertEquals(0x5555_5555, s.swap(0xaaaa_aaaa)); 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/java/bitmanipulation/_05_08_DrawLineTest.java: -------------------------------------------------------------------------------- 1 | package bitmanipulation; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertArrayEquals; 6 | 7 | public class _05_08_DrawLineTest { 8 | 9 | private _05_08_DrawLine s = new _05_08_DrawLine(); 10 | 11 | @Test 12 | public void with1Row8Columns_DrawEntireLine() { 13 | assertArrayEquals(new byte[]{(byte) 0xff}, s.drawLine(new byte[]{0}, 8, 0, 7, 0)); 14 | } 15 | 16 | @Test 17 | public void with1Row8Columns_DrawSubLine() { 18 | assertArrayEquals(new byte[]{(byte) 0x7e}, s.drawLine(new byte[]{0}, 8, 1, 6, 0)); 19 | } 20 | 21 | @Test 22 | public void with1Row8Columns_DrawSubLine_SomeBitsAlreadySet() { 23 | assertArrayEquals(new byte[]{(byte) 0xfe}, s.drawLine(new byte[]{(byte) 0x80}, 8, 1, 6, 0)); 24 | } 25 | 26 | @Test 27 | public void with1Row16Columns() { 28 | assertArrayEquals(new byte[]{(byte) 0x03, (byte) 0xfc}, s.drawLine(new byte[]{0, 0}, 16, 6, 13, 0)); 29 | } 30 | 31 | @Test 32 | public void with2Row16Columns() { 33 | assertArrayEquals(new byte[]{0, 0, (byte) 0x03, (byte) 0xfc}, s.drawLine(new byte[]{0, 0, 0, 0}, 16, 6, 13, 1)); 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_01_RemoveDupsTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class _02_01_RemoveDupsTest { 7 | 8 | private _02_01_RemoveDups s = new _02_01_RemoveDups(); 9 | 10 | @Test 11 | public void withEmptyList() { 12 | Assert.assertEquals(LinkedListNode.empty(), s.removeDups(LinkedListNode.empty())); 13 | } 14 | 15 | @Test 16 | public void withUniqueList() { 17 | Assert.assertEquals(LinkedListNode.of(1, 2, 3, 4), s.removeDups(LinkedListNode.of(1, 2, 3, 4))); 18 | } 19 | 20 | @Test 21 | public void withDuplications() { 22 | Assert.assertEquals(LinkedListNode.of(1, 2, 3, 4), s.removeDups(LinkedListNode.of(1, 2, 2, 3, 2, 4))); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_02_ReturnKthToLastTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertNull; 7 | 8 | public class _02_02_ReturnKthToLastTest { 9 | 10 | private _02_02_ReturnKthToLast s = new _02_02_ReturnKthToLast(); 11 | 12 | @Test 13 | public void withOutOfScopeK() { 14 | assertNull(s.kthToLast(LinkedListNode.of(1, 2, 3), 3)); 15 | } 16 | 17 | @Test 18 | public void withZero() { 19 | assertEquals(3, s.kthToLast(LinkedListNode.of(1, 2, 3), 0).val); 20 | } 21 | 22 | @Test 23 | public void withNoneZero() { 24 | assertEquals(2, s.kthToLast(LinkedListNode.of(1, 2, 3), 1).val); 25 | } 26 | 27 | 28 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_03_DeleteMiddleNodeTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertFalse; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | public class _02_03_DeleteMiddleNodeTest { 10 | 11 | private _02_03_DeleteMiddleNode s = new _02_03_DeleteMiddleNode(); 12 | 13 | @Test 14 | public void withNull() { 15 | assertFalse(s.deleteMiddleNode(null)); 16 | } 17 | 18 | @Test 19 | public void withLastNode() { 20 | assertFalse(s.deleteMiddleNode(LinkedListNode.of(1, 2, 3).next.next)); 21 | } 22 | 23 | @Test 24 | public void withMiddleNode() { 25 | LinkedListNode input = LinkedListNode.of(1, 2, 3); 26 | assertTrue(s.deleteMiddleNode(input.next)); 27 | Assert.assertEquals(LinkedListNode.of(1, 3), input); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_04_PartitionTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _02_04_PartitionTest { 8 | 9 | private _02_04_Partition s = new _02_04_Partition(); 10 | 11 | @Test 12 | public void withEmptyList() { 13 | assertEquals(LinkedListNode.empty(), s.partition(LinkedListNode.empty(), 8)); 14 | } 15 | 16 | @Test 17 | public void withSortedList() { 18 | assertEquals(LinkedListNode.of(1, 2, 3), s.partition(LinkedListNode.of(1, 2, 3), 2)); 19 | } 20 | 21 | @Test 22 | public void withSortedList_AndOutOfListX() { 23 | assertEquals(LinkedListNode.of(3, 2, 1), s.partition(LinkedListNode.of(1, 2, 3), 4)); 24 | } 25 | 26 | @Test 27 | public void withSortedList_AndOutOfListX_Smaller() { 28 | assertEquals(LinkedListNode.of(1, 2, 3), s.partition(LinkedListNode.of(1, 2, 3), 0)); 29 | } 30 | 31 | @Test 32 | public void withUnSortedList() { 33 | assertEquals(LinkedListNode.of(1, 2, 4, 3, 5), s.partition(LinkedListNode.of(4, 3, 2, 5, 1), 3)); 34 | } 35 | 36 | @Test 37 | public void withUnSortedList_AndOutOfScopeX() { 38 | assertEquals(LinkedListNode.of(1, 2, 4, 3, 6), s.partition(LinkedListNode.of(3, 4, 2, 6, 1), 5)); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_05_SumListReverseTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _02_05_SumListReverseTest { 8 | 9 | private _02_05_SumListReverse s = new _02_05_SumListReverse(); 10 | 11 | @Test 12 | public void withTwoEmptyLists() { 13 | assertEquals(LinkedListNode.empty(), s.sum(LinkedListNode.empty(), LinkedListNode.empty())); 14 | } 15 | 16 | @Test 17 | public void withOneEmptyList() { 18 | assertEquals(LinkedListNode.of(1, 2, 3), s.sum(LinkedListNode.empty(), LinkedListNode.of(1, 2, 3))); 19 | } 20 | 21 | @Test 22 | public void withNoCarry() { 23 | assertEquals(LinkedListNode.of(2, 4, 6), s.sum(LinkedListNode.of(1, 2, 3), LinkedListNode.of(1, 2, 3))); 24 | } 25 | 26 | @Test 27 | public void withCarry() { 28 | assertEquals(LinkedListNode.of(0, 4, 6), s.sum(LinkedListNode.of(1, 8, 3), LinkedListNode.of(9, 5, 2))); 29 | } 30 | 31 | @Test 32 | public void withCarryAtEnd() { 33 | assertEquals(LinkedListNode.of(0, 4, 2, 1), s.sum(LinkedListNode.of(1, 8, 9), LinkedListNode.of(9, 5, 2))); 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_05_SumListTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _02_05_SumListTest { 8 | 9 | private _02_05_SumList s = new _02_05_SumList(); 10 | 11 | @Test 12 | public void withTwoEmptyLists() { 13 | assertEquals(LinkedListNode.empty(), s.sum(LinkedListNode.empty(), LinkedListNode.empty())); 14 | } 15 | 16 | @Test 17 | public void withOneEmptyList() { 18 | assertEquals(LinkedListNode.of(1, 2, 3), s.sum(LinkedListNode.empty(), LinkedListNode.of(1, 2, 3))); 19 | } 20 | 21 | @Test 22 | public void withNoCarry() { 23 | assertEquals(LinkedListNode.of(2, 4, 6), s.sum(LinkedListNode.of(1, 2, 3), LinkedListNode.of(1, 2, 3))); 24 | } 25 | 26 | @Test 27 | public void withCarry() { 28 | assertEquals(LinkedListNode.of(5, 3, 5), s.sum(LinkedListNode.of(1, 8, 3), LinkedListNode.of(3, 5, 2))); 29 | } 30 | 31 | @Test 32 | public void withCarryAtEnd() { 33 | assertEquals(LinkedListNode.of(1, 1, 4, 1), s.sum(LinkedListNode.of(1, 8, 9), LinkedListNode.of(9, 5, 2))); 34 | } 35 | 36 | @Test 37 | public void withTwoListsHavingDiffrentLength() { 38 | assertEquals(LinkedListNode.of(2, 4, 1), s.sum(LinkedListNode.of(1, 8, 9), LinkedListNode.of(5, 2))); 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_06_PalindromeTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _02_06_PalindromeTest { 9 | 10 | private _02_06_Palindrome s = new _02_06_Palindrome(); 11 | 12 | @Test 13 | public void withEmptyList() { 14 | assertTrue(s.isPalindrome(LinkedListNode.empty())); 15 | } 16 | 17 | @Test 18 | public void withOneElement() { 19 | assertTrue(s.isPalindrome(LinkedListNode.of(1))); 20 | } 21 | 22 | @Test 23 | public void withThreeElements() { 24 | assertTrue(s.isPalindrome(LinkedListNode.of(1, 2, 1))); 25 | } 26 | 27 | @Test 28 | public void withFourElements() { 29 | assertTrue(s.isPalindrome(LinkedListNode.of(1, 2, 2, 1))); 30 | } 31 | 32 | @Test 33 | public void withFourElements_NotPalindrome() { 34 | assertFalse(s.isPalindrome(LinkedListNode.of(1, 2, 2, 3))); 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_07_IntersectionTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _02_07_IntersectionTest { 9 | 10 | private _02_07_Intersection s = new _02_07_Intersection(); 11 | 12 | @Test 13 | public void withTwoEmptyLists() { 14 | assertFalse(s.intersects(LinkedListNode.empty(), LinkedListNode.empty())); 15 | } 16 | 17 | @Test 18 | public void withOneEmptyList() { 19 | assertFalse(s.intersects(LinkedListNode.empty(), LinkedListNode.of(1, 2, 3))); 20 | assertFalse(s.intersects(LinkedListNode.of(1, 2, 3), LinkedListNode.empty())); 21 | } 22 | 23 | @Test 24 | public void withTwoSeparatedLists() { 25 | assertFalse(s.intersects(LinkedListNode.of(1, 2, 3), LinkedListNode.of(4, 5, 6))); 26 | } 27 | 28 | @Test 29 | public void withTwoSeparatedLists_HavingSameValue() { 30 | assertFalse(s.intersects(LinkedListNode.of(1, 2, 3), LinkedListNode.of(4, 2, 3))); 31 | } 32 | 33 | @Test 34 | public void withIntersectedLists() { 35 | LinkedListNode l1 = LinkedListNode.of(1, 2, 3, 4, 5); 36 | LinkedListNode l2 = LinkedListNode.of(6, 7, 8); 37 | l2.next.next.next = l1.next; 38 | assertTrue(s.intersects(l1, l2)); 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/java/linkedlist/_02_08_LoopDetectionTest.java: -------------------------------------------------------------------------------- 1 | package linkedlist; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertNull; 7 | 8 | public class _02_08_LoopDetectionTest { 9 | 10 | private _02_08_LoopDetection s = new _02_08_LoopDetection(); 11 | 12 | @Test 13 | public void withEmptyList() { 14 | assertNull(s.detect(LinkedListNode.empty())); 15 | } 16 | 17 | @Test 18 | public void withListWithoutLoop() { 19 | assertNull(s.detect(LinkedListNode.of(1, 2, 3))); 20 | } 21 | 22 | @Test 23 | public void testWithLoop_FromListHead() { 24 | LinkedListNode list = LinkedListNode.of(1, 2, 3, 4, 5); 25 | list.next.next.next.next.next = list; 26 | assertEquals(1, s.detect(list).val); 27 | } 28 | 29 | @Test 30 | public void testWithLoop_FromListTail() { 31 | LinkedListNode list = LinkedListNode.of(1, 2, 3, 4, 5); 32 | LinkedListNode tail = list.next.next.next.next; 33 | tail.next = tail; 34 | assertEquals(5, s.detect(list).val); 35 | } 36 | 37 | @Test 38 | public void testWithLoop_FromListMiddle() { 39 | LinkedListNode list = LinkedListNode.of(1, 2, 3, 4, 5); 40 | list.next.next.next.next.next = list.next; 41 | assertEquals(2, s.detect(list).val); 42 | } 43 | } -------------------------------------------------------------------------------- /src/test/java/moderate/_16_01_NumberSwapperTest.java: -------------------------------------------------------------------------------- 1 | package moderate; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _16_01_NumberSwapperTest { 8 | 9 | private _16_01_NumberSwapper s = new _16_01_NumberSwapper(); 10 | 11 | @Test 12 | public void test() { 13 | int[] ab = {1, 2}; 14 | s.swap(ab); 15 | assertEquals(ab[0], 2); 16 | assertEquals(ab[1], 1); 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /src/test/java/moderate/_16_06_SmallestDifferenceTest.java: -------------------------------------------------------------------------------- 1 | package moderate; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class _16_06_SmallestDifferenceTest { 7 | 8 | private _16_06_SmallestDifference s = new _16_06_SmallestDifference(); 9 | 10 | @Test 11 | public void withOneValueEach() { 12 | Assert.assertEquals(1, s.findSmallestDiff(new int[]{1}, new int[]{2})); 13 | } 14 | 15 | @Test 16 | public void withOneValueLeft_TwoValuesRight() { 17 | Assert.assertEquals(1, s.findSmallestDiff(new int[]{5}, new int[]{3, 6})); 18 | } 19 | 20 | @Test 21 | public void withMultipleValuesEach() { 22 | Assert.assertEquals(3, s.findSmallestDiff(new int[]{1, 3, 15, 11, 2}, new int[]{23, 127, 235, 19, 8})); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_01_TripleStepTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _08_01_TripleStepTest { 8 | 9 | private _08_01_TripleStep s = new _08_01_TripleStep(); 10 | 11 | @Test 12 | public void withZeroStep() { 13 | assertEquals(1, s.countWays(0)); 14 | } 15 | 16 | @Test 17 | public void withOneStep() { 18 | assertEquals(1, s.countWays(1)); 19 | } 20 | 21 | @Test 22 | public void withTwoSteps() { 23 | assertEquals(2, s.countWays(2)); 24 | } 25 | 26 | @Test 27 | public void withTreeSteps() { 28 | assertEquals(4, s.countWays(3)); 29 | } 30 | 31 | @Test 32 | public void withFourSteps() { 33 | //3+1 34 | // 3 35 | // 2+1 36 | // 1+2 37 | // 1+1+1 38 | //2+2 39 | // 2 40 | // 1+1 41 | //1+3 42 | // 1 43 | assertEquals(7, s.countWays(4)); 44 | } 45 | 46 | @Test 47 | public void withFiveSteps() { 48 | assertEquals(13, s.countWays(5)); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_02_RobotInAGridTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.awt.*; 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class _08_02_RobotInAGridTest { 12 | 13 | 14 | private _08_02_RobotInAGrid s = new _08_02_RobotInAGrid(); 15 | 16 | @Test 17 | public void withAllFeasibleCells() { 18 | boolean[][] grid = new boolean[][]{ 19 | {true, true, true}, 20 | {true, true, true}, 21 | {true, true, true} 22 | }; 23 | 24 | assertEquals(Arrays.asList( 25 | new Point(0, 0), new Point(0, 1), 26 | new Point(0, 2), new Point(1, 2), 27 | new Point(2, 2)), s.findPath(grid)); 28 | } 29 | 30 | @Test 31 | public void withSomeBrokenCells() { 32 | boolean[][] grid = new boolean[][]{ 33 | {true, true, true}, 34 | {true, true, false}, 35 | {false, true, true} 36 | }; 37 | 38 | assertEquals(Arrays.asList( 39 | new Point(0, 0), new Point(0, 1), 40 | new Point(1, 1), new Point(2, 1), 41 | new Point(2, 2)), s.findPath(grid)); 42 | } 43 | 44 | @Test 45 | public void withNoPath() { 46 | boolean[][] grid = new boolean[][]{ 47 | {true, true, true}, 48 | {true, true, false}, 49 | {false, false, true} 50 | }; 51 | 52 | assertEquals(Collections.emptyList(), s.findPath(grid)); 53 | } 54 | 55 | 56 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_03_MagicIndexTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _08_03_MagicIndexTest { 8 | 9 | private _08_03_MagicIndex s = new _08_03_MagicIndex(); 10 | 11 | @Test 12 | public void withOneElement() { 13 | assertEquals(-1, s.findMagicIndex(new int[]{2})); 14 | assertEquals(0, s.findMagicIndex(new int[]{0})); 15 | } 16 | 17 | @Test 18 | public void withMagicIndex() { 19 | assertEquals(2, s.findMagicIndex(new int[]{-1, 0, 2, 5, 7, 9})); 20 | } 21 | 22 | @Test 23 | public void withoutMagicIndex() { 24 | assertEquals(-1, s.findMagicIndex(new int[]{1, 2, 3, 4, 5, 6})); 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_04_PowerSetTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | 12 | public class _08_04_PowerSetTest { 13 | 14 | private _08_04_PowerSet s = new _08_04_PowerSet(); 15 | 16 | @Test 17 | public void withEmptySet() { 18 | assertEquals(Collections.emptySet(), s.subSets(Collections.emptySet())); 19 | } 20 | 21 | @Test 22 | public void withOneElement() { 23 | Set> subsets = new HashSet<>(); 24 | subsets.add(Collections.emptySet()); 25 | subsets.add(Collections.singleton(1)); 26 | assertEquals(subsets, s.subSets(Collections.singleton(1))); 27 | } 28 | 29 | @Test 30 | public void withTwoElements() { 31 | Set> subsets = new HashSet<>(); 32 | subsets.add(Collections.emptySet()); 33 | subsets.add(Collections.singleton(1)); 34 | subsets.add(Collections.singleton(2)); 35 | subsets.add(new HashSet<>(Arrays.asList(1, 2))); 36 | assertEquals(subsets, s.subSets(new HashSet<>(Arrays.asList(1, 2)))); 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_05_RecursiveMultiplyTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _08_05_RecursiveMultiplyTest { 8 | 9 | private _08_05_RecursiveMultiply s = new _08_05_RecursiveMultiply(); 10 | 11 | @Test 12 | public void testOneOne() { 13 | assertEquals(1, s.multiple(1, 1)); 14 | } 15 | 16 | @Test 17 | public void testOneTwo() { 18 | assertEquals(2, s.multiple(1, 2)); 19 | } 20 | 21 | @Test 22 | public void testFiveNine() { 23 | assertEquals(45, s.multiple(5, 9)); 24 | } 25 | 26 | @Test 27 | public void testThirtyForty() { 28 | assertEquals(1200, s.multiple(40, 30)); 29 | } 30 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_06_HanoiTowersTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class _08_06_HanoiTowersTest { 10 | 11 | private _08_06_HanoiTowers s = new _08_06_HanoiTowers(); 12 | 13 | @Test 14 | public void withOneDisk() { 15 | assertEquals(Arrays.asList(1, 3), s.leftToRight(1)); 16 | } 17 | 18 | @Test 19 | public void withTwoDisk() { 20 | assertEquals(Arrays.asList( 21 | 1, 2, 22 | 1, 3, 23 | 2, 3 24 | ), s.leftToRight(2)); 25 | } 26 | 27 | @Test 28 | public void withThreeDisks() { 29 | assertEquals(Arrays.asList( 30 | 1, 3, 31 | 1, 2, 32 | 3, 2, 33 | 1, 3, 34 | 2, 1, 35 | 2, 3, 36 | 1, 3 37 | ), s.leftToRight(3)); 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_07_PermutationWithoutDupTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.HashSet; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class _08_07_PermutationWithoutDupTest { 12 | 13 | private _08_07_PermutationWithoutDup s = new _08_07_PermutationWithoutDup(); 14 | 15 | @Test 16 | public void withEmptyString() { 17 | assertEquals(Collections.singleton(""), s.computePermutation("")); 18 | } 19 | 20 | @Test 21 | public void withOneChar() { 22 | assertEquals(Collections.singleton("a"), s.computePermutation("a")); 23 | } 24 | 25 | @Test 26 | public void withTwoChars() { 27 | assertEquals(new HashSet<>(Arrays.asList("ab", "ba")), s.computePermutation("ab")); 28 | assertEquals(new HashSet<>(Arrays.asList("ab", "ba")), s.computePermutation("ba")); 29 | } 30 | 31 | @Test 32 | public void withThreeChars() { 33 | HashSet result = new HashSet<>(Arrays.asList("abc", "acb", "bca", "bac", "cab", "cba")); 34 | assertEquals(result, s.computePermutation("abc")); 35 | assertEquals(result, s.computePermutation("acb")); 36 | assertEquals(result, s.computePermutation("bca")); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_08_PermutationWithDupTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.HashSet; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class _08_08_PermutationWithDupTest { 12 | 13 | private _08_08_PermutationWithDup s = new _08_08_PermutationWithDup(); 14 | 15 | @Test 16 | public void withEmptyString() { 17 | assertEquals(Collections.singleton(""), s.computePermutation("")); 18 | } 19 | 20 | @Test 21 | public void withOneChar() { 22 | assertEquals(Collections.singleton("a"), s.computePermutation("a")); 23 | } 24 | 25 | @Test 26 | public void withTwoChars() { 27 | assertEquals(Collections.singleton("aa"), s.computePermutation("aa")); 28 | } 29 | 30 | @Test 31 | public void withThreeChars() { 32 | HashSet result = new HashSet<>(Arrays.asList("aab", "aba", "baa")); 33 | assertEquals(result, s.computePermutation("aba")); 34 | } 35 | 36 | @Test 37 | public void withManySameChar() { 38 | String str = "aaaaaaaaaaaa"; 39 | assertEquals(Collections.singleton(str), s.computePermutation(str)); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_09_ParensTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | import java.util.HashSet; 9 | 10 | public class _08_09_ParensTest { 11 | 12 | private final _08_09_Parens s = new _08_09_Parens(); 13 | 14 | @Test 15 | public void withZeroPair() { 16 | Assert.assertEquals(Collections.emptySet(), s.combine(0)); 17 | } 18 | 19 | @Test 20 | public void withOnePair() { 21 | Assert.assertEquals(Collections.singleton("()"), s.combine(1)); 22 | } 23 | 24 | @Test 25 | public void withTwoPairs() { 26 | Assert.assertEquals(new HashSet<>(Arrays.asList("()()", "(())")), s.combine(2)); 27 | } 28 | 29 | @Test 30 | public void withThreePairs() { 31 | Assert.assertEquals(new HashSet<>(Arrays.asList( 32 | "((()))", 33 | "(()())", 34 | "(())()", 35 | "()(())", 36 | "()()()")), s.combine(3)); 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_10_PaintFillTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | 8 | public class _08_10_PaintFillTest { 9 | 10 | private final _08_10_PaintFill s = new _08_10_PaintFill(); 11 | 12 | @Test 13 | public void withAllOriginalColorConnected() { 14 | int[][] screen = new int[][]{ 15 | {1, 0, 1}, 16 | {0, 0, 1}, 17 | {1, 0, 0} 18 | }; 19 | 20 | int x = 1, y = 1; 21 | 22 | int newColor = 2; 23 | 24 | int[][] expected = new int[][]{ 25 | {1, 2, 1}, 26 | {2, 2, 1}, 27 | {1, 2, 2} 28 | }; 29 | Assert.assertTrue(Arrays.deepEquals(expected, s.paintFill(screen, x, y, newColor))); 30 | } 31 | 32 | @Test 33 | public void withAllOriginalColorSeparated() { 34 | int[][] screen = new int[][]{ 35 | {1, 0, 1}, 36 | {0, 1, 1}, 37 | {1, 0, 0} 38 | }; 39 | 40 | int x = 2, y = 1; 41 | 42 | int newColor = 2; 43 | 44 | int[][] expected = new int[][]{ 45 | {1, 0, 1}, 46 | {0, 1, 1}, 47 | {1, 2, 2} 48 | }; 49 | Assert.assertTrue(Arrays.deepEquals(expected, s.paintFill(screen, x, y, newColor))); 50 | } 51 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_11_CoinsTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class _08_11_CoinsTest { 7 | 8 | private final _08_11_Coins s = new _08_11_Coins(); 9 | 10 | @Test 11 | public void withZeroCent() { 12 | Assert.assertEquals(1, s.makeChangeWithQuarterDimeNickelPenny(0)); 13 | } 14 | 15 | @Test 16 | public void withOneCent() { 17 | Assert.assertEquals(1, s.makeChangeWithQuarterDimeNickelPenny(2)); 18 | } 19 | 20 | @Test 21 | public void withTwoCents() { 22 | Assert.assertEquals(1, s.makeChangeWithQuarterDimeNickelPenny(3)); 23 | } 24 | 25 | @Test 26 | public void with25Cents() { 27 | //25 28 | //10 10 5 29 | //10 10 1 1 1 1 1 30 | //10 5 5 5 31 | //10 5 5 1 1 1 1 1 32 | //10 5 1 1 1 1 1 1 1 1 1 1 33 | //10 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 34 | //5 5 5 5 5 35 | //5 5 5 5 1 1 1 1 1 36 | //5 5 5 1 1 1 1 1 1 1 1 1 1 37 | //5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 38 | //5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 39 | //1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 | Assert.assertEquals(13, s.makeChangeWithQuarterDimeNickelPenny(25)); 41 | } 42 | 43 | @Test 44 | public void with100Cents() { 45 | Assert.assertEquals(242, s.makeChangeWithQuarterDimeNickelPenny(100)); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_12_EightQueensTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.awt.*; 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | public class _08_12_EightQueensTest { 11 | 12 | private final _08_12_EightQueens s = new _08_12_EightQueens(); 13 | 14 | @Test 15 | public void withEightQueens() { 16 | List> result = s.arrange(); 17 | System.out.println("Solution size " + result.size()); 18 | result.stream() 19 | .map(points -> points.stream().map(this::replace).collect(Collectors.joining())) 20 | .forEach(System.out::println); 21 | Assert.assertEquals(92, result.size()); 22 | } 23 | 24 | private String replace(Point p) { 25 | char[] chars = " 0 0 0 0 0 0 0 0\n".toCharArray(); 26 | chars[p.y * 2 + 1] = 'x'; 27 | return String.valueOf(chars); 28 | } 29 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_13_StackOfBoxesTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import recursivedp._08_13_StackOfBoxes.Box; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | 10 | public class _08_13_StackOfBoxesTest { 11 | 12 | private final _08_13_StackOfBoxes s = new _08_13_StackOfBoxes(); 13 | 14 | 15 | @Test 16 | public void with0Box() { 17 | Assert.assertEquals(0, s.createStack(Collections.emptyList())); 18 | } 19 | 20 | @Test 21 | public void with1Box() { 22 | Assert.assertEquals(1, s.createStack(Collections.singletonList(new Box(1, 1, 1)))); 23 | } 24 | 25 | @Test 26 | public void with3Boxes() { 27 | Assert.assertEquals(5, s.createStack(Arrays.asList( 28 | new Box(2, 2, 2), 29 | new Box(3, 3, 3), 30 | new Box(3, 3, 4)))); 31 | } 32 | 33 | @Test 34 | public void with4Boxes() { 35 | Assert.assertEquals(10, s.createStack(Arrays.asList( 36 | new Box(4, 4, 4), 37 | new Box(3, 3, 3), 38 | new Box(2, 2, 2), 39 | new Box(1, 1, 1)))); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/recursivedp/_08_14_BooleanEvaluationTest.java: -------------------------------------------------------------------------------- 1 | package recursivedp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _08_14_BooleanEvaluationTest { 8 | 9 | private _08_14_BooleanEvaluation s = new _08_14_BooleanEvaluation(); 10 | 11 | 12 | @Test 13 | public void withEmptyExpression() { 14 | assertEquals(0, s.evaluate("", true)); 15 | assertEquals(0, s.evaluate("", false)); 16 | } 17 | 18 | @Test 19 | public void withOneValue() { 20 | assertEquals(0, s.evaluate("1", false)); 21 | assertEquals(1, s.evaluate("1", true)); 22 | assertEquals(0, s.evaluate("0", true)); 23 | assertEquals(1, s.evaluate("0", false)); 24 | } 25 | 26 | 27 | @Test 28 | public void withOneOperator() { 29 | assertEquals(1, s.evaluate("1&1", true)); 30 | assertEquals(0, s.evaluate("1&0", true)); 31 | assertEquals(0, s.evaluate("0&1", true)); 32 | assertEquals(0, s.evaluate("0&0", true)); 33 | 34 | assertEquals(0, s.evaluate("1&1", false)); 35 | assertEquals(1, s.evaluate("1&0", false)); 36 | assertEquals(1, s.evaluate("0&1", false)); 37 | assertEquals(1, s.evaluate("0&0", false)); 38 | 39 | assertEquals(1, s.evaluate("1|1", true)); 40 | assertEquals(1, s.evaluate("1|0", true)); 41 | assertEquals(1, s.evaluate("0|1", true)); 42 | assertEquals(0, s.evaluate("0|0", true)); 43 | 44 | assertEquals(0, s.evaluate("1|1", false)); 45 | assertEquals(0, s.evaluate("1|0", false)); 46 | assertEquals(0, s.evaluate("0|1", false)); 47 | assertEquals(1, s.evaluate("0|0", false)); 48 | 49 | assertEquals(0, s.evaluate("1^1", true)); 50 | assertEquals(1, s.evaluate("0^1", true)); 51 | assertEquals(1, s.evaluate("1^0", true)); 52 | assertEquals(0, s.evaluate("0^0", true)); 53 | 54 | assertEquals(1, s.evaluate("1^1", false)); 55 | assertEquals(0, s.evaluate("0^1", false)); 56 | assertEquals(0, s.evaluate("1^0", false)); 57 | assertEquals(1, s.evaluate("0^0", false)); 58 | } 59 | 60 | @Test 61 | public void withMultipleOperators() { 62 | assertEquals(2, s.evaluate("0|0|1", true)); 63 | } 64 | 65 | @Test 66 | public void withMoreOperators() { 67 | assertEquals(2, s.evaluate("1^0|0|1", false)); 68 | } 69 | 70 | @Test 71 | public void withMoreMoreOperators() { 72 | assertEquals(10, s.evaluate("0&0&0&1^1|0", true)); 73 | } 74 | } -------------------------------------------------------------------------------- /src/test/java/sortingsearching/_10_01_SortedMergeTest.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | 8 | public class _10_01_SortedMergeTest { 9 | 10 | private _10_01_SortedMerge s = new _10_01_SortedMerge(); 11 | 12 | @Test 13 | public void withOneElementEach() { 14 | Assert.assertTrue(Arrays.equals(new int[]{1, 2}, s.merge(new int[]{2, 0}, new int[]{1}))); 15 | } 16 | 17 | @Test 18 | public void withMultipleElementsEach() { 19 | Assert.assertTrue(Arrays.equals(new int[]{2, 3, 4, 5, 6}, s.merge(new int[]{2, 4, 6, 0, 0}, new int[]{3, 5}))); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/sortingsearching/_10_02_GroupAnagramsTest.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | 9 | public class _10_02_GroupAnagramsTest { 10 | 11 | private _10_02_GroupAnagrams s = new _10_02_GroupAnagrams(); 12 | 13 | @Test 14 | public void withEmpty() { 15 | Assert.assertEquals(Collections.emptyList(), s.groupAnagrams(Collections.emptyList())); 16 | } 17 | 18 | @Test 19 | public void withOneWord() { 20 | Assert.assertEquals(Collections.singletonList("hello"), s.groupAnagrams(Collections.singletonList("hello"))); 21 | } 22 | 23 | @Test 24 | public void withThreeWords() { 25 | Assert.assertEquals(Arrays.asList("hello", "olelh", "world"), s.groupAnagrams(Arrays.asList("hello", "world", "olelh"))); 26 | } 27 | 28 | @Test 29 | public void withFourWords() { 30 | Assert.assertEquals(Arrays.asList("hello", "olelh", "lrowd", "world"), s.groupAnagrams(Arrays.asList("hello", "lrowd", "olelh", "world"))); 31 | } 32 | } -------------------------------------------------------------------------------- /src/test/java/sortingsearching/_10_03_SearchInRotatedArrayTest.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class _10_03_SearchInRotatedArrayTest { 7 | 8 | private _10_03_SearchInRotatedArray s = new _10_03_SearchInRotatedArray(); 9 | 10 | @Test 11 | public void withOneElement() { 12 | Assert.assertEquals(-1, s.find(new int[]{1}, 2)); 13 | Assert.assertEquals(0, s.find(new int[]{1}, 1)); 14 | } 15 | 16 | @Test 17 | public void withTwoElement() { 18 | Assert.assertEquals(1, s.find(new int[]{2, 1}, 1)); 19 | Assert.assertEquals(0, s.find(new int[]{2, 1}, 2)); 20 | Assert.assertEquals(-1, s.find(new int[]{2, 1}, 0)); 21 | } 22 | 23 | @Test 24 | public void withMultipleElements() { 25 | Assert.assertEquals(8, s.find(new int[]{15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14}, 5)); 26 | } 27 | 28 | @Test 29 | public void withDuplicates() { 30 | Assert.assertEquals(8, s.find(new int[]{20, 20, 20, 20, 20, 20, 20, 20, 5, 7, 10, 14}, 5)); 31 | int r = s.find(new int[]{20, 20, 20, 20, 20, 20, 20, 20, 5, 7, 10, 14}, 20); 32 | Assert.assertTrue(r >= 0 && r <= 7); 33 | } 34 | } -------------------------------------------------------------------------------- /src/test/java/sortingsearching/_10_04_SortedSearchTest.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import sortingsearching._10_04_SortedSearch.Listy; 6 | 7 | public class _10_04_SortedSearchTest { 8 | 9 | private _10_04_SortedSearch s = new _10_04_SortedSearch(); 10 | 11 | @Test 12 | public void withEmptyListy() { 13 | Assert.assertEquals(-1, s.sortedSearch(Listy.of(), 1)); 14 | } 15 | 16 | @Test 17 | public void withOneElem() { 18 | Assert.assertEquals(0, s.sortedSearch(Listy.of(1), 1)); 19 | } 20 | 21 | @Test 22 | public void withMultipleElems() { 23 | Assert.assertEquals(3, s.sortedSearch(Listy.of(1, 3, 4, 5, 8, 10), 5)); 24 | Assert.assertEquals(-1, s.sortedSearch(Listy.of(1, 3, 4, 5, 8, 10), 6)); 25 | } 26 | 27 | @Test 28 | public void withDuplicates() { 29 | int actual = s.sortedSearch(Listy.of(1, 3, 4, 5, 5, 10), 5); 30 | Assert.assertTrue(actual == 3 || actual == 4); 31 | } 32 | } -------------------------------------------------------------------------------- /src/test/java/sortingsearching/_10_05_SparseSearchTest.java: -------------------------------------------------------------------------------- 1 | package sortingsearching; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class _10_05_SparseSearchTest { 7 | 8 | private final _10_05_SparseSearch sparseSearch = new _10_05_SparseSearch(); 9 | 10 | @Test 11 | public void withEmptyString() { 12 | Assert.assertEquals(-1, sparseSearch.find(new String[]{"hello", "", "world"}, "")); 13 | } 14 | 15 | @Test 16 | public void withValidString() { 17 | Assert.assertEquals(8, sparseSearch.find( 18 | new String[]{"hello", "", "", "idea", "", "", "", "", "world", "", "", "", "", "", "xylo", "", ""}, 19 | "world")); 20 | 21 | } 22 | 23 | @Test 24 | public void withManySparse() { 25 | Assert.assertEquals(0, sparseSearch.find( 26 | new String[]{"hello", "", "", "", "", "", "", "", "", "", "", "", "", ""}, 27 | "hello")); 28 | 29 | } 30 | @Test 31 | public void withWordInTheEnd() { 32 | Assert.assertEquals(3, sparseSearch.find( 33 | new String[]{"", "", "", "hello"}, 34 | "hello")); 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /src/test/java/stackqueue/_03_01_ThreeInOneTest.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _03_01_ThreeInOneTest { 8 | 9 | @Test 10 | public void withStackSize1() { 11 | _03_01_ThreeInOne s = new _03_01_ThreeInOne(1); 12 | s.push(0, 0); 13 | s.push(1, 1); 14 | s.push(2, 2); 15 | assertEquals(0, s.pop(0)); 16 | assertEquals(1, s.pop(1)); 17 | assertEquals(2, s.pop(2)); 18 | } 19 | 20 | 21 | @Test 22 | public void withStackSize2() { 23 | _03_01_ThreeInOne s = new _03_01_ThreeInOne(2); 24 | s.push(0, 6); 25 | s.push(1, 1); 26 | s.push(1, 2); 27 | s.push(2, 3); 28 | s.push(2, 4); 29 | s.push(2, 5); 30 | assertEquals(6, s.pop(0)); 31 | assertEquals(2, s.pop(1)); 32 | assertEquals(1, s.pop(1)); 33 | assertEquals(5, s.pop(2)); 34 | assertEquals(4, s.pop(2)); 35 | assertEquals(3, s.pop(2)); 36 | } 37 | 38 | @Test(expected = RuntimeException.class) 39 | public void withArrayLength3_Exceeded() { 40 | _03_01_ThreeInOne s = new _03_01_ThreeInOne(1); 41 | s.push(0, 1); 42 | s.push(0, 1); 43 | s.push(0, 1); 44 | s.push(0, 1); 45 | } 46 | 47 | @Test(expected = RuntimeException.class) 48 | public void withArrayLength3_StackNotExists() { 49 | _03_01_ThreeInOne s = new _03_01_ThreeInOne(3); 50 | s.push(3, 1); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/stackqueue/_03_02_MinStackTest.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.EmptyStackException; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class _03_02_MinStackTest { 10 | 11 | private _03_02_MinStack s = new _03_02_MinStack(); 12 | 13 | @Test 14 | public void withDecreasing() { 15 | s.push(3); 16 | s.push(2); 17 | s.push(1); 18 | assertEquals(1, s.min()); 19 | assertEquals(1, s.pop()); 20 | assertEquals(2, s.min()); 21 | assertEquals(2, s.pop()); 22 | assertEquals(3, s.min()); 23 | assertEquals(3, s.pop()); 24 | } 25 | 26 | @Test 27 | public void withInterleaving() { 28 | s.push(3); 29 | s.push(5); 30 | s.push(2); 31 | s.push(6); 32 | s.push(1); 33 | 34 | assertEquals(1, s.min()); 35 | assertEquals(1, s.pop()); 36 | assertEquals(2, s.min()); 37 | assertEquals(6, s.pop()); 38 | assertEquals(2, s.min()); 39 | assertEquals(2, s.pop()); 40 | assertEquals(3, s.min()); 41 | assertEquals(5, s.pop()); 42 | } 43 | 44 | @Test 45 | public void withInterleavingActions() { 46 | s.push(3); 47 | s.push(5); 48 | assertEquals(3, s.min()); 49 | s.push(4); 50 | assertEquals(3, s.min()); 51 | assertEquals(4, s.pop()); 52 | assertEquals(5, s.pop()); 53 | assertEquals(3, s.pop()); 54 | } 55 | 56 | @Test(expected = EmptyStackException.class) 57 | public void withEmptyStack() { 58 | s.pop(); 59 | } 60 | } -------------------------------------------------------------------------------- /src/test/java/stackqueue/_03_03_StackOfPlatesTest.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _03_03_StackOfPlatesTest { 8 | 9 | @Test 10 | public void withBigThreshold() { 11 | _03_03_StackOfPlates stack = new _03_03_StackOfPlates(100); 12 | stack.push(3); 13 | stack.push(4); 14 | stack.push(5); 15 | stack.push(6); 16 | assertEquals(6, stack.pop()); 17 | assertEquals(5, stack.pop()); 18 | assertEquals(4, stack.pop()); 19 | assertEquals(3, stack.pop()); 20 | } 21 | 22 | @Test 23 | public void withSmallThreshold() { 24 | _03_03_StackOfPlates stack = new _03_03_StackOfPlates(2); 25 | stack.push(3); 26 | stack.push(4); 27 | stack.push(5); 28 | stack.push(6); 29 | assertEquals(6, stack.pop()); 30 | assertEquals(5, stack.pop()); 31 | assertEquals(4, stack.pop()); 32 | assertEquals(3, stack.pop()); 33 | } 34 | 35 | @Test 36 | public void withSmallThreshold_PopAtIndex() { 37 | _03_03_StackOfPlates stack = new _03_03_StackOfPlates(2); 38 | stack.push(3); 39 | stack.push(4); 40 | stack.push(5); 41 | stack.push(6); 42 | stack.push(7); 43 | stack.push(8); 44 | 45 | assertEquals(6, stack.popAt(1)); 46 | assertEquals(7, stack.popAt(1)); 47 | assertEquals(8, stack.pop()); 48 | assertEquals(4, stack.popAt(0)); 49 | assertEquals(5, stack.pop()); 50 | assertEquals(3, stack.pop()); 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /src/test/java/stackqueue/_03_04_QueueViaStacksTest.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _03_04_QueueViaStacksTest { 8 | 9 | private _03_04_QueueViaStacks s = new _03_04_QueueViaStacks(); 10 | 11 | @Test 12 | public void withAllEnqueueAndAllDequeue() { 13 | s.enqueue(1); 14 | s.enqueue(2); 15 | s.enqueue(3); 16 | assertEquals(3, s.size()); 17 | assertEquals(1, s.dequeue()); 18 | assertEquals(2, s.size()); 19 | assertEquals(2, s.dequeue()); 20 | assertEquals(3, s.dequeue()); 21 | } 22 | 23 | @Test 24 | public void withInterleavingEnqueueAndDequeue() { 25 | s.enqueue(1); 26 | assertEquals(1, s.dequeue()); 27 | s.enqueue(2); 28 | s.enqueue(3); 29 | assertEquals(2, s.peek()); 30 | assertEquals(2, s.dequeue()); 31 | s.enqueue(4); 32 | assertEquals(3, s.dequeue()); 33 | assertEquals(4, s.dequeue()); 34 | } 35 | 36 | @Test(expected = RuntimeException.class) 37 | public void withEmptyQueue() { 38 | s.enqueue(1); 39 | s.dequeue(); 40 | s.dequeue(); 41 | } 42 | } -------------------------------------------------------------------------------- /src/test/java/stackqueue/_03_05_SortStackTest.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Stack; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class _03_05_SortStackTest { 10 | 11 | private _03_05_SortStack s = new _03_05_SortStack(); 12 | 13 | @Test 14 | public void withAlreadySorted() { 15 | Stack stack = new Stack<>(); 16 | stack.push(3); 17 | stack.push(2); 18 | stack.push(1); 19 | Stack result = s.sort(stack); 20 | assertEquals(1, result.pop().intValue()); 21 | assertEquals(2, result.pop().intValue()); 22 | assertEquals(3, result.pop().intValue()); 23 | } 24 | 25 | @Test 26 | public void withUnSorted() { 27 | Stack stack = new Stack<>(); 28 | stack.push(2); 29 | stack.push(5); 30 | stack.push(3); 31 | stack.push(4); 32 | Stack result = s.sort(stack); 33 | assertEquals(2, result.pop().intValue()); 34 | assertEquals(3, result.pop().intValue()); 35 | assertEquals(4, result.pop().intValue()); 36 | assertEquals(5, result.pop().intValue()); 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/java/stackqueue/_03_06_AnimalShelterTest.java: -------------------------------------------------------------------------------- 1 | package stackqueue; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _03_06_AnimalShelterTest { 8 | 9 | private _03_06_AnimalShelter s = new _03_06_AnimalShelter(); 10 | 11 | @Test 12 | public void withOrdinaryQueue() { 13 | s.enqueueCat(5); 14 | s.enqueueDog(4); 15 | s.enqueueCat(6); 16 | s.enqueueCat(7); 17 | 18 | assertEquals(5, s.dequeueAny()); 19 | assertEquals(4, s.dequeueAny()); 20 | assertEquals(6, s.dequeueAny()); 21 | assertEquals(7, s.dequeueAny()); 22 | } 23 | 24 | @Test 25 | public void withCatDogOledest() { 26 | s.enqueueCat(5); 27 | s.enqueueCat(3); 28 | s.enqueueDog(6); 29 | s.enqueueDog(2); 30 | s.enqueueCat(1); 31 | 32 | assertEquals(6, s.dequeueDog()); 33 | assertEquals(5, s.dequeueAny()); 34 | assertEquals(3, s.dequeueAny()); 35 | assertEquals(1, s.dequeueCat()); 36 | assertEquals(2, s.dequeueDog()); 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_01_RouteBetweenNodesTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _04_01_RouteBetweenNodesTest { 9 | 10 | @Test 11 | public void withTwoVertex() { 12 | Digraph digraph = new Digraph(2); 13 | digraph.addEdge(0, 1); 14 | _04_01_RouteBetweenNodes routeBetweenNodes = new _04_01_RouteBetweenNodes(digraph); 15 | assertTrue(routeBetweenNodes.hasRoute(0, 1)); 16 | assertFalse(routeBetweenNodes.hasRoute(1, 0)); 17 | } 18 | 19 | @Test 20 | public void withMoreVertex() { 21 | Digraph digraph = new Digraph(5); 22 | digraph.addEdge(0, 1); 23 | digraph.addEdge(0, 2); 24 | digraph.addEdge(2, 3); 25 | digraph.addEdge(2, 4); 26 | _04_01_RouteBetweenNodes routeBetweenNodes = new _04_01_RouteBetweenNodes(digraph); 27 | assertTrue(routeBetweenNodes.hasRoute(0, 4)); 28 | } 29 | 30 | @Test 31 | public void withCycle() { 32 | Digraph digraph = new Digraph(3); 33 | digraph.addEdge(0, 1); 34 | digraph.addEdge(1, 2); 35 | digraph.addEdge(2, 0); 36 | _04_01_RouteBetweenNodes routeBetweenNodes = new _04_01_RouteBetweenNodes(digraph); 37 | assertTrue(routeBetweenNodes.hasRoute(0, 1)); 38 | assertTrue(routeBetweenNodes.hasRoute(0, 2)); 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_02_MinimalTreeTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertNull; 7 | 8 | public class _04_02_MinimalTreeTest { 9 | 10 | private _04_02_MinimalTree s = new _04_02_MinimalTree(); 11 | 12 | @Test 13 | public void withOneElement() { 14 | BinaryTreeNode binaryTreeNode = s.buildMinimalTree(new int[]{1}); 15 | assertEquals(1, binaryTreeNode.val); 16 | assertNull(binaryTreeNode.left); 17 | assertNull(binaryTreeNode.right); 18 | } 19 | 20 | @Test 21 | public void withTwoElements() { 22 | BinaryTreeNode binaryTreeNode = s.buildMinimalTree(new int[]{1, 2}); 23 | assertEquals(1, binaryTreeNode.val); 24 | assertEquals(2, binaryTreeNode.right.val); 25 | assertEquals(null, binaryTreeNode.left); 26 | } 27 | 28 | @Test 29 | public void withThreeElements() { 30 | BinaryTreeNode binaryTreeNode = s.buildMinimalTree(new int[]{1, 2, 3}); 31 | assertEquals(2, binaryTreeNode.val); 32 | assertEquals(1, binaryTreeNode.left.val); 33 | assertEquals(3, binaryTreeNode.right.val); 34 | } 35 | 36 | @Test 37 | public void withFourElements() { 38 | BinaryTreeNode binaryTreeNode = s.buildMinimalTree(new int[]{1, 2, 3, 4}); 39 | assertEquals(2, binaryTreeNode.val); 40 | assertEquals(1, binaryTreeNode.left.val); 41 | assertEquals(3, binaryTreeNode.right.val); 42 | assertEquals(4, binaryTreeNode.right.right.val); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_03_ListOfDepthsTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.*; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class _04_03_ListOfDepthsTest { 10 | 11 | private _04_03_ListOfDepths s = new _04_03_ListOfDepths(); 12 | 13 | @Test 14 | public void withOneElement() { 15 | List> linkedLists = s.create(new BinaryTreeNode(1)); 16 | List> results = new ArrayList<>(); 17 | results.add(new LinkedList<>(Collections.singletonList(1))); 18 | assertEquals(results, linkedLists); 19 | } 20 | 21 | @Test 22 | public void withTwoElements() { 23 | BinaryTreeNode node = new BinaryTreeNode(1); 24 | node.left = new BinaryTreeNode(2); 25 | List> linkedLists = s.create(node); 26 | List> results = new ArrayList<>(); 27 | results.add(new LinkedList<>(Collections.singletonList(1))); 28 | results.add(new LinkedList<>(Collections.singletonList(2))); 29 | assertEquals(results, linkedLists); 30 | } 31 | 32 | @Test 33 | public void withThreeElements() { 34 | BinaryTreeNode node = new BinaryTreeNode(1); 35 | node.left = new BinaryTreeNode(2); 36 | node.right = new BinaryTreeNode(3); 37 | List> linkedLists = s.create(node); 38 | List> results = new ArrayList<>(); 39 | results.add(new LinkedList<>(Collections.singletonList(1))); 40 | results.add(new LinkedList<>(Arrays.asList(2, 3))); 41 | assertEquals(results, linkedLists); 42 | } 43 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_04_CheckBalancedTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _04_04_CheckBalancedTest { 9 | 10 | private _04_04_CheckBalanced s = new _04_04_CheckBalanced(); 11 | 12 | @Test 13 | public void withOneNode() { 14 | assertTrue(s.isBalanced(new BinaryTreeNode(1))); 15 | } 16 | 17 | @Test 18 | public void withTwoNodes() { 19 | BinaryTreeNode root = new BinaryTreeNode(1); 20 | root.left = new BinaryTreeNode(2); 21 | assertTrue(s.isBalanced(root)); 22 | } 23 | 24 | @Test 25 | public void withThreeNodes() { 26 | BinaryTreeNode root = new BinaryTreeNode(1); 27 | root.left = new BinaryTreeNode(2); 28 | root.right = new BinaryTreeNode(3); 29 | assertTrue(s.isBalanced(root)); 30 | } 31 | 32 | @Test 33 | public void withFourNodes_Unbalanced() { 34 | BinaryTreeNode root = new BinaryTreeNode(1); 35 | root.left = new BinaryTreeNode(2); 36 | root.left.left = new BinaryTreeNode(3); 37 | assertFalse(s.isBalanced(root)); 38 | } 39 | 40 | @Test 41 | public void withSameHeight_Unbalanced() { 42 | BinaryTreeNode root = new BinaryTreeNode(1); 43 | root.left = new BinaryTreeNode(2); 44 | root.left.left = new BinaryTreeNode(3); 45 | root.left.right = new BinaryTreeNode(7); 46 | root.left.left.left = new BinaryTreeNode(6); 47 | root.left.left.left.left = new BinaryTreeNode(8); 48 | root.right = new BinaryTreeNode(4); 49 | root.right.right = new BinaryTreeNode(5); 50 | root.right.right.right = new BinaryTreeNode(9); 51 | assertFalse(s.isBalanced(root)); 52 | } 53 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_05_ValidateBSTTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _04_05_ValidateBSTTest { 9 | 10 | private _04_05_ValidateBST s = new _04_05_ValidateBST(); 11 | 12 | @Test 13 | public void withOneNode() { 14 | assertTrue(s.isBST(new BinaryTreeNode(1))); 15 | } 16 | 17 | @Test 18 | public void withTwoNodes() { 19 | BinaryTreeNode node = new BinaryTreeNode(2); 20 | node.left = new BinaryTreeNode(1); 21 | assertTrue(s.isBST(node)); 22 | } 23 | 24 | @Test 25 | public void withThreeNodes() { 26 | BinaryTreeNode node = new BinaryTreeNode(2); 27 | node.left = new BinaryTreeNode(1); 28 | node.right = new BinaryTreeNode(3); 29 | assertTrue(s.isBST(node)); 30 | } 31 | 32 | @Test 33 | public void withTreeNodes_NotBalanced() { 34 | BinaryTreeNode node = new BinaryTreeNode(2); 35 | node.left = new BinaryTreeNode(1); 36 | node.right = new BinaryTreeNode(1); 37 | assertFalse(s.isBST(node)); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_06_SuccessorTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertNull; 7 | 8 | public class _04_06_SuccessorTest { 9 | 10 | private _04_06_Successor s = new _04_06_Successor(); 11 | 12 | @Test 13 | public void withOneNode() { 14 | assertNull(s.findInOrderSuccessor(new ParentAwareBinaryTreeNode(1))); 15 | } 16 | 17 | @Test 18 | public void withTwoNodes() { 19 | ParentAwareBinaryTreeNode root = new ParentAwareBinaryTreeNode(2); 20 | root.addLeft(1); 21 | assertEquals(2, s.findInOrderSuccessor(root.left).val); 22 | } 23 | 24 | @Test 25 | public void withFourNodes() { 26 | ParentAwareBinaryTreeNode root = new ParentAwareBinaryTreeNode(2); 27 | root.addLeft(1); 28 | root.addRight(4).addRight(6).addLeft(5); 29 | assertEquals(4, s.findInOrderSuccessor(root).val); 30 | } 31 | 32 | @Test 33 | public void withTargetNodeARightNode() { 34 | ParentAwareBinaryTreeNode root = new ParentAwareBinaryTreeNode(6); 35 | root.addLeft(4).addRight(5); 36 | assertEquals(6, s.findInOrderSuccessor(root.left.right).val); 37 | } 38 | 39 | @Test 40 | public void withTargetNodeARightNode_AndWithChild() { 41 | ParentAwareBinaryTreeNode root = new ParentAwareBinaryTreeNode(8); 42 | root.addLeft(4).addRight(6).addRight(7); 43 | assertEquals(7, s.findInOrderSuccessor(root.left.right).val); 44 | } 45 | 46 | @Test 47 | public void withTargetNodeADeepRightNode() { 48 | ParentAwareBinaryTreeNode root = new ParentAwareBinaryTreeNode(8); 49 | root.addLeft(1).addRight(2).addRight(3).addRight(4); 50 | assertEquals(8, s.findInOrderSuccessor(root.left.right.right.right).val); 51 | } 52 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_07_BuildOrderTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | import static org.junit.Assert.assertNull; 10 | 11 | public class _04_07_BuildOrderTest { 12 | 13 | private _04_07_BuildOrder s = new _04_07_BuildOrder(); 14 | 15 | @Test 16 | public void withOneProject() { 17 | Digraph digraph = new Digraph(1); 18 | assertEquals(Collections.singletonList(0), s.findBuildOrder(digraph)); 19 | } 20 | 21 | @Test 22 | public void withTwoProjects() { 23 | Digraph digraph = new Digraph(2); 24 | digraph.addEdge(1, 0); 25 | assertEquals(Arrays.asList(0, 1), s.findBuildOrder(digraph)); 26 | } 27 | 28 | @Test 29 | public void withMoreProjects() { 30 | Digraph digraph = new Digraph(4); 31 | digraph.addEdge(3, 1); 32 | digraph.addEdge(2, 1); 33 | digraph.addEdge(1, 0); 34 | assertEquals(Arrays.asList(0, 1, 2, 3), s.findBuildOrder(digraph)); 35 | } 36 | 37 | @Test 38 | public void withTwoGroups() { 39 | Digraph digraph = new Digraph(4); 40 | digraph.addEdge(1, 0); 41 | digraph.addEdge(3, 2); 42 | assertEquals(Arrays.asList(0, 1, 2, 3), s.findBuildOrder(digraph)); 43 | } 44 | 45 | @Test 46 | public void withCycle() { 47 | Digraph digraph = new Digraph(3); 48 | digraph.addEdge(0, 1); 49 | digraph.addEdge(1, 2); 50 | digraph.addEdge(2, 0); 51 | assertNull(s.findBuildOrder(digraph)); 52 | } 53 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_08_FindCommonAncestorTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _04_08_FindCommonAncestorTest { 8 | 9 | private _04_08_FindCommonAncestor s = new _04_08_FindCommonAncestor(); 10 | 11 | @Test 12 | public void withOneNode() { 13 | ParentAwareBinaryTreeNode node = new ParentAwareBinaryTreeNode(1); 14 | assertEquals(node, s.findCommonAncestor(node, node)); 15 | } 16 | 17 | @Test 18 | public void withTwoNodes() { 19 | ParentAwareBinaryTreeNode node = new ParentAwareBinaryTreeNode(1); 20 | node.addLeft(2); 21 | assertEquals(node, s.findCommonAncestor(node, node.left)); 22 | } 23 | 24 | @Test 25 | public void withThreeNodes() { 26 | ParentAwareBinaryTreeNode node = new ParentAwareBinaryTreeNode(1); 27 | node.addLeft(2); 28 | node.addRight(3); 29 | assertEquals(node, s.findCommonAncestor(node.left, node.right)); 30 | } 31 | 32 | @Test 33 | public void withMoreNodes() { 34 | ParentAwareBinaryTreeNode node = new ParentAwareBinaryTreeNode(1); 35 | node.addLeft(2); 36 | ParentAwareBinaryTreeNode ancestor = node.addRight(3); 37 | ParentAwareBinaryTreeNode a = ancestor.addLeft(4).addRight(5); 38 | ParentAwareBinaryTreeNode b = ancestor.addRight(6).addRight(7).addRight(8); 39 | assertEquals(ancestor, s.findCommonAncestor(a, b)); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_09_BSTSequencesTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public class _04_09_BSTSequencesTest { 11 | 12 | private _04_09_BSTSequences s = new _04_09_BSTSequences(); 13 | 14 | @Test 15 | public void withOneNode() { 16 | assertEquals(Collections.singletonList(Collections.singletonList(1)), s.sequences(new BinaryTreeNode(1))); 17 | } 18 | 19 | @Test 20 | public void withTwoNodes() { 21 | BinaryTreeNode root = new BinaryTreeNode(1); 22 | root.right = new BinaryTreeNode(2); 23 | assertEquals(Collections.singletonList(Arrays.asList(1, 2)), s.sequences(root)); 24 | } 25 | 26 | @Test 27 | public void withThreeNodes() { 28 | BinaryTreeNode root = new BinaryTreeNode(2); 29 | root.left = new BinaryTreeNode(1); 30 | root.right = new BinaryTreeNode(3); 31 | assertEquals(Arrays.asList(Arrays.asList(2, 1, 3), Arrays.asList(2, 3, 1)), s.sequences(root)); 32 | } 33 | 34 | @Test 35 | public void withMoreNodes() { 36 | BinaryTreeNode root = new BinaryTreeNode(5); 37 | root.left = new BinaryTreeNode(3); 38 | root.left.left = new BinaryTreeNode(2); 39 | root.left.right = new BinaryTreeNode(4); 40 | root.right = new BinaryTreeNode(7); 41 | assertEquals( 42 | Arrays.asList( 43 | Arrays.asList(5, 3, 2, 4, 7), 44 | Arrays.asList(5, 3, 2, 7, 4), 45 | Arrays.asList(5, 3, 7, 2, 4), 46 | Arrays.asList(5, 7, 3, 2, 4), 47 | Arrays.asList(5, 3, 4, 2, 7), 48 | Arrays.asList(5, 3, 4, 7, 2), 49 | Arrays.asList(5, 3, 7, 4, 2), 50 | Arrays.asList(5, 7, 3, 4, 2) 51 | ), 52 | s.sequences(root)); 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_10_CheckSubTreeTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertTrue; 7 | 8 | public class _04_10_CheckSubTreeTest { 9 | 10 | private _04_10_CheckSubTree s = new _04_10_CheckSubTree(); 11 | 12 | @Test 13 | public void withOneNode() { 14 | BinaryTreeNode a = new BinaryTreeNode(1); 15 | BinaryTreeNode b = new BinaryTreeNode(1); 16 | assertTrue(s.isSubTree(a, b)); 17 | } 18 | 19 | @Test 20 | public void withTwoNodes() { 21 | BinaryTreeNode a = new BinaryTreeNode(1); 22 | a.left = new BinaryTreeNode(2); 23 | BinaryTreeNode b = new BinaryTreeNode(2); 24 | assertTrue(s.isSubTree(a, b)); 25 | } 26 | 27 | @Test 28 | public void withMoreNodes() { 29 | BinaryTreeNode a = new BinaryTreeNode(1); 30 | a.right = new BinaryTreeNode(2); 31 | a.right.right = new BinaryTreeNode(3); 32 | a.right.right.left = new BinaryTreeNode(4); 33 | a.right.right.right = new BinaryTreeNode(5); 34 | 35 | BinaryTreeNode b = new BinaryTreeNode(3); 36 | b.left = new BinaryTreeNode(4); 37 | b.right = new BinaryTreeNode(5); 38 | 39 | assertTrue(s.isSubTree(a, b)); 40 | } 41 | 42 | @Test 43 | public void withDiffTree() { 44 | BinaryTreeNode a = new BinaryTreeNode(1); 45 | a.left = new BinaryTreeNode(2); 46 | a.right = new BinaryTreeNode(3); 47 | BinaryTreeNode b = new BinaryTreeNode(4); 48 | assertFalse(s.isSubTree(a, b)); 49 | } 50 | 51 | @Test 52 | public void withSamePreOrder() { 53 | BinaryTreeNode a = new BinaryTreeNode(1); 54 | a.left = new BinaryTreeNode(2); 55 | a.right = new BinaryTreeNode(3); 56 | 57 | BinaryTreeNode b = new BinaryTreeNode(1); 58 | b.right = new BinaryTreeNode(2); 59 | b.left = new BinaryTreeNode(3); 60 | 61 | assertFalse(s.isSubTree(a, b)); 62 | } 63 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_11_RandomNodeTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class _04_11_RandomNodeTest { 8 | 9 | @Test 10 | public void withSimpleCase() { 11 | _04_11_RandomNode.Tree tree = new _04_11_RandomNode.Tree(); 12 | tree.insert(5); 13 | tree.insert(2); 14 | tree.insert(1); 15 | tree.insert(3); 16 | tree.insert(6); 17 | assertEquals(3, tree.find(3).getVal()); 18 | assertNull(tree.find(4)); 19 | assertNotNull(tree.getRandomNode()); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/treegraph/_04_12_PathsWithSumTest.java: -------------------------------------------------------------------------------- 1 | package treegraph; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class _04_12_PathsWithSumTest { 8 | 9 | private _04_12_PathsWithSum s = new _04_12_PathsWithSum(); 10 | 11 | @Test 12 | public void withOneNode() { 13 | BinaryTreeNode root = new BinaryTreeNode(1); 14 | assertEquals(0, s.countPathWithSum(root, 2)); 15 | assertEquals(1, s.countPathWithSum(root, 1)); 16 | } 17 | 18 | @Test 19 | public void withThreeNodes() { 20 | BinaryTreeNode root = new BinaryTreeNode(1); 21 | root.left = new BinaryTreeNode(1); 22 | root.right = new BinaryTreeNode(2); 23 | assertEquals(2, s.countPathWithSum(root, 1)); 24 | assertEquals(2, s.countPathWithSum(root, 2)); 25 | assertEquals(1, s.countPathWithSum(root, 3)); 26 | assertEquals(0, s.countPathWithSum(root, 4)); 27 | } 28 | 29 | @Test 30 | public void withMoreDepths() { 31 | BinaryTreeNode root = new BinaryTreeNode(10); 32 | root.left = new BinaryTreeNode(5); 33 | root.left.left = new BinaryTreeNode(3); 34 | root.left.left.left = new BinaryTreeNode(3); 35 | root.left.left.right = new BinaryTreeNode(-2); 36 | root.left.right = new BinaryTreeNode(1); 37 | root.left.right.right = new BinaryTreeNode(2); 38 | 39 | root.right = new BinaryTreeNode(-3); 40 | root.right.right = new BinaryTreeNode(-11); 41 | 42 | assertEquals(2, s.countPathWithSum(root, 8)); 43 | 44 | } 45 | } --------------------------------------------------------------------------------