└── src ├── class01 ├── Code01_AppleMinBags.java ├── Code02_EatGrass.java ├── Code03_MSumToN.java ├── Code04_RotateMatrix.java ├── Code05_PrintMatrixSpiralOrder.java └── Code06_ZigZagPrintMatrix.java ├── class02 ├── Code01_LongestSumSubArrayLengthInPositiveArray.java ├── Code02_LongestSumSubArrayLength.java └── Code03_LongestLessSumSubArrayLength.java ├── class03 ├── Code01_RandomPool.java └── Code02_Islands.java ├── class05 ├── Code01_AVLTreeMap.java ├── Code02_SizeBalancedTreeMap.java ├── Code03_SkipListMap.java └── Compare.java ├── class06 ├── AbstractBinarySearchTree.java ├── AbstractSelfBalancingBinarySearchTree.java ├── BinarySearchTree.java └── RedBlackTree.java ├── class07 ├── Code01_CountofRangeSum.java └── Code02_SlidingWindowMedian.java └── class08 ├── Code01_AC.java ├── Code02_DifferentBTNum.java ├── Code03_10Ways.java └── Code04_UniqueBST.java /src/class01/Code01_AppleMinBags.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code01_AppleMinBags { 4 | 5 | public static int minBags(int apple) { 6 | if (apple < 0) { 7 | return -1; 8 | } 9 | int bag6 = -1; 10 | int bag8 = apple / 8; 11 | int rest = apple - 8 * bag8; 12 | while (bag8 >= 0 && rest < 24) { 13 | int restUse6 = minBagBase6(rest); 14 | if (restUse6 != -1) { 15 | bag6 = restUse6; 16 | break; 17 | } 18 | rest = apple - 8 * (--bag8); 19 | } 20 | return bag6 == -1 ? -1 : bag6 + bag8; 21 | } 22 | 23 | // 如果剩余苹果rest可以被装6个苹果的袋子搞定,返回袋子数量 24 | // 不能搞定返回-1 25 | public static int minBagBase6(int rest) { 26 | return rest % 6 == 0 ? (rest / 6) : -1; 27 | } 28 | 29 | public static int minBagAwesome(int apple) { 30 | if ((apple & 1) != 0) { // 如果是奇数,返回-1 31 | return -1; 32 | } 33 | if (apple < 18) { 34 | return apple == 0 ? 0 : (apple == 6 || apple == 8) ? 1 35 | : (apple == 12 || apple == 14 || apple == 16) ? 2 : -1; 36 | } 37 | return (apple - 18) / 8 + 3; 38 | } 39 | 40 | public static void main(String[] args) { 41 | for(int apple = 1; apple < 100;apple++) { 42 | System.out.println(apple + " : "+ minBags(apple)); 43 | } 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/class01/Code02_EatGrass.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code02_EatGrass { 4 | 5 | // n份青草放在一堆 6 | // 先手后手都绝顶聪明 7 | // string "先手" "后手" 8 | public static String winner1(int n) { 9 | // 0 1 2 3 4 10 | // 后 先 后 先 先 11 | if (n < 5) { // base case 12 | return (n == 0 || n == 2) ? "后手" : "先手"; 13 | } 14 | // n >= 5 时 15 | int base = 1; // 当前先手决定吃的草数 16 | // 当前是先手在选 17 | while (base <= n) { 18 | // 当前一共n份草,先手吃掉的是base份,n - base 是留给后手的草 19 | // 母过程 先手 在子过程里是 后手 20 | if (winner1(n - base).equals("后手")) { 21 | return "先手"; 22 | } 23 | if (base > n / 4) { // 防止base*4之后溢出 24 | break; 25 | } 26 | base *= 4; 27 | } 28 | return "后手"; 29 | } 30 | 31 | public static String winner2(int n) { 32 | if (n % 5 == 0 || n % 5 == 2) { 33 | return "后手"; 34 | } else { 35 | return "先手"; 36 | } 37 | } 38 | 39 | public static void main(String[] args) { 40 | for (int i = 0; i <= 50; i++) { 41 | System.out.println(i + " : " + winner1(i)); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/class01/Code03_MSumToN.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code03_MSumToN { 4 | 5 | public static boolean isMSum1(int num) { 6 | for (int i = 1; i <= num; i++) { 7 | int sum = i; 8 | for (int j = i + 1; j <= num; j++) { 9 | if (sum + j > num) { 10 | break; 11 | } 12 | if (sum + j == num) { 13 | return true; 14 | } 15 | sum += j; 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | public static boolean isMSum2(int num) { 22 | if (num < 3) { 23 | return false; 24 | } 25 | return (num & (num - 1)) != 0; 26 | } 27 | 28 | public static void main(String[] args) { 29 | for (int num = 1; num < 200; num++) { 30 | System.out.println(num + " : " + isMSum1(num)); 31 | } 32 | System.out.println("test begin"); 33 | for (int num = 1; num < 5000; num++) { 34 | if (isMSum1(num) != isMSum2(num)) { 35 | System.out.println("Oops!"); 36 | } 37 | } 38 | System.out.println("test end"); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/class01/Code04_RotateMatrix.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code04_RotateMatrix { 4 | 5 | public static void rotate(int[][] matrix) { 6 | int a = 0; 7 | int b = 0; 8 | int c = matrix.length - 1; 9 | int d = matrix[0].length - 1; 10 | while (a < c) { 11 | rotateEdge(matrix, a++, b++, c--, d--); 12 | } 13 | } 14 | 15 | public static void rotateEdge(int[][] m, int a, int b, int c, int d) { 16 | int tmp = 0; 17 | for (int i = 0; i < d - b; i++) { 18 | tmp = m[a][b + i]; 19 | m[a][b + i] = m[c - i][b]; 20 | m[c - i][b] = m[c][d - i]; 21 | m[c][d - i] = m[a + i][d]; 22 | m[a + i][d] = tmp; 23 | } 24 | } 25 | 26 | public static void printMatrix(int[][] matrix) { 27 | for (int i = 0; i != matrix.length; i++) { 28 | for (int j = 0; j != matrix[0].length; j++) { 29 | System.out.print(matrix[i][j] + " "); 30 | } 31 | System.out.println(); 32 | } 33 | } 34 | 35 | public static void main(String[] args) { 36 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; 37 | printMatrix(matrix); 38 | rotate(matrix); 39 | System.out.println("========="); 40 | printMatrix(matrix); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/class01/Code05_PrintMatrixSpiralOrder.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code05_PrintMatrixSpiralOrder { 4 | 5 | public static void spiralOrderPrint(int[][] matrix) { 6 | int tR = 0; 7 | int tC = 0; 8 | int dR = matrix.length - 1; 9 | int dC = matrix[0].length - 1; 10 | while (tR <= dR && tC <= dC) { 11 | printEdge(matrix, tR++, tC++, dR--, dC--); 12 | } 13 | } 14 | 15 | public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) { 16 | if (tR == dR) { 17 | for (int i = tC; i <= dC; i++) { 18 | System.out.print(m[tR][i] + " "); 19 | } 20 | } else if (tC == dC) { 21 | for (int i = tR; i <= dR; i++) { 22 | System.out.print(m[i][tC] + " "); 23 | } 24 | } else { 25 | int curC = tC; 26 | int curR = tR; 27 | while (curC != dC) { 28 | System.out.print(m[tR][curC] + " "); 29 | curC++; 30 | } 31 | while (curR != dR) { 32 | System.out.print(m[curR][dC] + " "); 33 | curR++; 34 | } 35 | while (curC != tC) { 36 | System.out.print(m[dR][curC] + " "); 37 | curC--; 38 | } 39 | while (curR != tR) { 40 | System.out.print(m[curR][tC] + " "); 41 | curR--; 42 | } 43 | } 44 | } 45 | 46 | public static void main(String[] args) { 47 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, 48 | { 13, 14, 15, 16 } }; 49 | spiralOrderPrint(matrix); 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/class01/Code06_ZigZagPrintMatrix.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code06_ZigZagPrintMatrix { 4 | 5 | public static void printMatrixZigZag(int[][] matrix) { 6 | int tR = 0; 7 | int tC = 0; 8 | int dR = 0; 9 | int dC = 0; 10 | int endR = matrix.length - 1; 11 | int endC = matrix[0].length - 1; 12 | boolean fromUp = false; 13 | while (tR != endR + 1) { 14 | printLevel(matrix, tR, tC, dR, dC, fromUp); 15 | tR = tC == endC ? tR + 1 : tR; 16 | tC = tC == endC ? tC : tC + 1; 17 | dC = dR == endR ? dC + 1 : dC; 18 | dR = dR == endR ? dR : dR + 1; 19 | fromUp = !fromUp; 20 | } 21 | System.out.println(); 22 | } 23 | 24 | public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, 25 | boolean f) { 26 | if (f) { 27 | while (tR != dR + 1) { 28 | System.out.print(m[tR++][tC--] + " "); 29 | } 30 | } else { 31 | while (dR != tR - 1) { 32 | System.out.print(m[dR--][dC++] + " "); 33 | } 34 | } 35 | } 36 | 37 | public static void main(String[] args) { 38 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 39 | printMatrixZigZag(matrix); 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/class02/Code01_LongestSumSubArrayLengthInPositiveArray.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code01_LongestSumSubArrayLengthInPositiveArray { 4 | 5 | public static int getMaxLength(int[] arr, int K) { 6 | if (arr == null || arr.length == 0 || K <= 0) { 7 | return 0; 8 | } 9 | int left = 0; 10 | int right = 0; 11 | int sum = arr[0]; 12 | int len = 0; 13 | while (right < arr.length) { 14 | if (sum == K) { 15 | len = Math.max(len, right - left + 1); 16 | sum -= arr[left++]; 17 | } else if (sum < K) { 18 | right++; 19 | if (right == arr.length) { 20 | break; 21 | } 22 | sum += arr[right]; 23 | } else { 24 | sum -= arr[left++]; 25 | } 26 | } 27 | return len; 28 | } 29 | 30 | // for test 31 | public static int right(int[] arr, int K) { 32 | int max = 0; 33 | for (int i = 0; i < arr.length; i++) { 34 | for (int j = i; j < arr.length; j++) { 35 | if (valid(arr, i, j, K)) { 36 | max = Math.max(max, j - i + 1); 37 | } 38 | } 39 | } 40 | return max; 41 | } 42 | 43 | // for test 44 | public static boolean valid(int[] arr, int L, int R, int K) { 45 | int sum = 0; 46 | for (int i = L; i <= R; i++) { 47 | sum += arr[i]; 48 | } 49 | return sum == K; 50 | } 51 | 52 | // for test 53 | public static int[] generatePositiveArray(int size, int value) { 54 | int[] ans = new int[size]; 55 | for (int i = 0; i != size; i++) { 56 | ans[i] = (int) (Math.random() * value) + 1; 57 | } 58 | return ans; 59 | } 60 | 61 | // for test 62 | public static void printArray(int[] arr) { 63 | for (int i = 0; i != arr.length; i++) { 64 | System.out.print(arr[i] + " "); 65 | } 66 | System.out.println(); 67 | } 68 | 69 | public static void main(String[] args) { 70 | int len = 50; 71 | int value = 100; 72 | int testTime = 500000; 73 | System.out.println("test begin"); 74 | for (int i = 0; i < testTime; i++) { 75 | int[] arr = generatePositiveArray(len, value); 76 | int K = (int) (Math.random() * value) + 1; 77 | int ans1 = getMaxLength(arr, K); 78 | int ans2 = right(arr, K); 79 | if (ans1 != ans2) { 80 | System.out.println("Oops!"); 81 | printArray(arr); 82 | System.out.println("K : " + K); 83 | System.out.println(ans1); 84 | System.out.println(ans2); 85 | break; 86 | } 87 | } 88 | System.out.println("test end"); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/class02/Code02_LongestSumSubArrayLength.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code02_LongestSumSubArrayLength { 6 | 7 | public static int maxLength(int[] arr, int k) { 8 | if (arr == null || arr.length == 0) { 9 | return 0; 10 | } 11 | HashMap map = new HashMap(); 12 | map.put(0, -1); // important 13 | int len = 0; 14 | int sum = 0; 15 | for (int i = 0; i < arr.length; i++) { 16 | sum += arr[i]; 17 | if (map.containsKey(sum - k)) { 18 | len = Math.max(i - map.get(sum - k), len); 19 | } 20 | if (!map.containsKey(sum)) { 21 | map.put(sum, i); 22 | } 23 | } 24 | return len; 25 | } 26 | 27 | // for test 28 | public static int right(int[] arr, int K) { 29 | int max = 0; 30 | for (int i = 0; i < arr.length; i++) { 31 | for (int j = i; j < arr.length; j++) { 32 | if (valid(arr, i, j, K)) { 33 | max = Math.max(max, j - i + 1); 34 | } 35 | } 36 | } 37 | return max; 38 | } 39 | 40 | // for test 41 | public static boolean valid(int[] arr, int L, int R, int K) { 42 | int sum = 0; 43 | for (int i = L; i <= R; i++) { 44 | sum += arr[i]; 45 | } 46 | return sum == K; 47 | } 48 | 49 | // for test 50 | public static int[] generateRandomArray(int size, int value) { 51 | int[] ans = new int[(int) (Math.random() * size) + 1]; 52 | for (int i = 0; i < ans.length; i++) { 53 | ans[i] = (int) (Math.random() * value) - (int) (Math.random() * value); 54 | } 55 | return ans; 56 | } 57 | 58 | // for test 59 | public static void printArray(int[] arr) { 60 | for (int i = 0; i != arr.length; i++) { 61 | System.out.print(arr[i] + " "); 62 | } 63 | System.out.println(); 64 | } 65 | 66 | public static void main(String[] args) { 67 | int len = 50; 68 | int value = 100; 69 | int testTime = 500000; 70 | 71 | System.out.println("test begin"); 72 | for (int i = 0; i < testTime; i++) { 73 | int[] arr = generateRandomArray(len, value); 74 | int K = (int) (Math.random() * value) - (int) (Math.random() * value); 75 | int ans1 = maxLength(arr, K); 76 | int ans2 = right(arr, K); 77 | if (ans1 != ans2) { 78 | System.out.println("Oops!"); 79 | printArray(arr); 80 | System.out.println("K : " + K); 81 | System.out.println(ans1); 82 | System.out.println(ans2); 83 | break; 84 | } 85 | } 86 | System.out.println("test end"); 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/class02/Code03_LongestLessSumSubArrayLength.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code03_LongestLessSumSubArrayLength { 4 | 5 | public static int maxLengthAwesome(int[] arr, int k) { 6 | if (arr == null || arr.length == 0) { 7 | return 0; 8 | } 9 | int[] minSums = new int[arr.length]; 10 | int[] minSumEnds = new int[arr.length]; 11 | minSums[arr.length - 1] = arr[arr.length - 1]; 12 | minSumEnds[arr.length - 1] = arr.length - 1; 13 | for (int i = arr.length - 2; i >= 0; i--) { 14 | if (minSums[i + 1] < 0) { 15 | minSums[i] = arr[i] + minSums[i + 1]; 16 | minSumEnds[i] = minSumEnds[i + 1]; 17 | } else { 18 | minSums[i] = arr[i]; 19 | minSumEnds[i] = i; 20 | } 21 | } 22 | int end = 0; 23 | int sum = 0; 24 | int res = 0; 25 | // i是窗口的最左的位置,end扩出来的最右有效块儿的最后一个位置的,再下一个位置 26 | // end也是下一块儿的开始位置 27 | // 窗口:[i~end) 28 | for (int i = 0; i < arr.length; i++) { 29 | // while循环结束之后: 30 | // 1) 如果以i开头的情况下,累加和<=k的最长子数组是arr[i..end-1],看看这个子数组长度能不能更新res; 31 | // 2) 如果以i开头的情况下,累加和<=k的最长子数组比arr[i..end-1]短,更新还是不更新res都不会影响最终结果; 32 | while (end < arr.length && sum + minSums[end] <= k) { 33 | sum += minSums[end]; 34 | end = minSumEnds[end] + 1; 35 | } 36 | res = Math.max(res, end - i); 37 | if (end > i) { // 窗口内还有数 [i~end) [4,4) 38 | sum -= arr[i]; 39 | } else { // 窗口内已经没有数了,说明从i开头的所有子数组累加和都不可能<=k 40 | end = i + 1; 41 | } 42 | } 43 | return res; 44 | } 45 | 46 | public static int maxLength(int[] arr, int k) { 47 | int[] h = new int[arr.length + 1]; 48 | int sum = 0; 49 | h[0] = sum; 50 | for (int i = 0; i != arr.length; i++) { 51 | sum += arr[i]; 52 | h[i + 1] = Math.max(sum, h[i]); 53 | } 54 | sum = 0; 55 | int res = 0; 56 | int pre = 0; 57 | int len = 0; 58 | for (int i = 0; i != arr.length; i++) { 59 | sum += arr[i]; 60 | pre = getLessIndex(h, sum - k); 61 | len = pre == -1 ? 0 : i - pre + 1; 62 | res = Math.max(res, len); 63 | } 64 | return res; 65 | } 66 | 67 | public static int getLessIndex(int[] arr, int num) { 68 | int low = 0; 69 | int high = arr.length - 1; 70 | int mid = 0; 71 | int res = -1; 72 | while (low <= high) { 73 | mid = (low + high) / 2; 74 | if (arr[mid] >= num) { 75 | res = mid; 76 | high = mid - 1; 77 | } else { 78 | low = mid + 1; 79 | } 80 | } 81 | return res; 82 | } 83 | 84 | // for test 85 | public static int[] generateRandomArray(int len, int maxValue) { 86 | int[] res = new int[len]; 87 | for (int i = 0; i != res.length; i++) { 88 | res[i] = (int) (Math.random() * maxValue) - (maxValue / 3); 89 | } 90 | return res; 91 | } 92 | 93 | public static void main(String[] args) { 94 | System.out.println("test begin"); 95 | for (int i = 0; i < 10000000; i++) { 96 | int[] arr = generateRandomArray(10, 20); 97 | int k = (int) (Math.random() * 20) - 5; 98 | if (maxLengthAwesome(arr, k) != maxLength(arr, k)) { 99 | System.out.println("Oops!"); 100 | } 101 | } 102 | System.out.println("test finish"); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/class03/Code01_RandomPool.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code01_RandomPool { 6 | 7 | public static class Pool { 8 | private HashMap keyIndexMap; 9 | private HashMap indexKeyMap; 10 | private int size; 11 | 12 | public Pool() { 13 | this.keyIndexMap = new HashMap(); 14 | this.indexKeyMap = new HashMap(); 15 | this.size = 0; 16 | } 17 | 18 | public void insert(K key) { 19 | if (!this.keyIndexMap.containsKey(key)) { 20 | this.keyIndexMap.put(key, this.size); 21 | this.indexKeyMap.put(this.size++, key); 22 | } 23 | } 24 | 25 | public void delete(K key) { 26 | if (this.keyIndexMap.containsKey(key)) { 27 | int deleteIndex = this.keyIndexMap.get(key); 28 | int lastIndex = --this.size; 29 | K lastKey = this.indexKeyMap.get(lastIndex); 30 | this.keyIndexMap.put(lastKey, deleteIndex); 31 | this.indexKeyMap.put(deleteIndex, lastKey); 32 | this.keyIndexMap.remove(key); 33 | this.indexKeyMap.remove(lastIndex); 34 | } 35 | } 36 | 37 | public K getRandom() { 38 | if (this.size == 0) { 39 | return null; 40 | } 41 | int randomIndex = (int) (Math.random() * this.size); // 0 ~ size -1 42 | return this.indexKeyMap.get(randomIndex); 43 | } 44 | 45 | } 46 | 47 | public static void main(String[] args) { 48 | Pool pool = new Pool(); 49 | pool.insert("zuo"); 50 | pool.insert("cheng"); 51 | pool.insert("yun"); 52 | System.out.println(pool.getRandom()); 53 | System.out.println(pool.getRandom()); 54 | System.out.println(pool.getRandom()); 55 | System.out.println(pool.getRandom()); 56 | System.out.println(pool.getRandom()); 57 | System.out.println(pool.getRandom()); 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/class03/Code02_Islands.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Stack; 7 | 8 | public class Code02_Islands { 9 | 10 | public static int countIslands1(int[][] m) { 11 | if (m == null || m[0] == null) { 12 | return 0; 13 | } 14 | int N = m.length; 15 | int M = m[0].length; 16 | int res = 0; 17 | for (int i = 0; i < N; i++) { 18 | for (int j = 0; j < M; j++) { 19 | if (m[i][j] == 1) { 20 | res++; 21 | infect(m, i, j, N, M); 22 | } 23 | } 24 | } 25 | return res; 26 | } 27 | 28 | public static void infect(int[][] m, int i, int j, int N, int M) { 29 | if (i < 0 || i >= N || j < 0 || j >= M || m[i][j] != 1) { 30 | return; 31 | } 32 | m[i][j] = 2; 33 | infect(m, i + 1, j, N, M); 34 | infect(m, i - 1, j, N, M); 35 | infect(m, i, j + 1, N, M); 36 | infect(m, i, j - 1, N, M); 37 | } 38 | 39 | public static class Element { 40 | public V value; 41 | 42 | public Element(V value) { 43 | this.value = value; 44 | } 45 | 46 | } 47 | 48 | public static class UnionFindSet { 49 | // a -> a 生成的点 50 | public HashMap> elementMap; 51 | public HashMap, Element> fatherMap; 52 | // sizeMap中的key,每一个key都一定是集合的头节点(代表节点) 53 | public HashMap, Integer> sizeMap; 54 | 55 | public UnionFindSet(List list) { 56 | elementMap = new HashMap<>(); 57 | fatherMap = new HashMap<>(); 58 | sizeMap = new HashMap<>(); 59 | for (V value : list) { 60 | Element element = new Element(value); 61 | elementMap.put(value, element); 62 | fatherMap.put(element, element); 63 | sizeMap.put(element, 1); 64 | } 65 | } 66 | 67 | // 从输入参数element出发,往上一直找,找到不能再往上的头节点,返回 68 | private Element findHead(Element element) { 69 | // 把往上找的过程中,沿途的点都记录在path里 70 | Stack> path = new Stack<>(); 71 | while (element != fatherMap.get(element)) { 72 | path.push(element); 73 | element = fatherMap.get(element); 74 | } 75 | while (!path.isEmpty()) { 76 | fatherMap.put(path.pop(), element); 77 | } 78 | return element; 79 | } 80 | 81 | public boolean isSameSet(V a, V b) { 82 | if (elementMap.containsKey(a) && elementMap.containsKey(b)) { 83 | return findHead(elementMap.get(a)) == findHead(elementMap.get(b)); 84 | } 85 | return false; 86 | } 87 | 88 | public void union(V a, V b) { 89 | if (elementMap.containsKey(a) && elementMap.containsKey(b)) { 90 | Element aF = findHead(elementMap.get(a)); 91 | Element bF = findHead(elementMap.get(b)); 92 | if (aF != bF) { 93 | Element big = sizeMap.get(aF) >= sizeMap.get(bF) ? aF : bF; 94 | Element small = big == aF ? bF : aF; 95 | fatherMap.put(small, big); 96 | sizeMap.put(big, sizeMap.get(aF) + sizeMap.get(bF)); 97 | sizeMap.remove(small); 98 | } 99 | } 100 | } 101 | 102 | public int getSetNum() { 103 | return sizeMap.size(); 104 | } 105 | 106 | } 107 | 108 | public static int countIslands2(int[][] m) { 109 | List list = new ArrayList<>(); 110 | for (int row = 0; row < m.length; row++) { 111 | for (int col = 0; col < m[0].length; col++) { 112 | if (m[row][col] == 1) { 113 | String position = String.valueOf(row) + "_" + String.valueOf(col); 114 | list.add(position); 115 | } 116 | } 117 | } 118 | UnionFindSet unionSet = new UnionFindSet<>(list); 119 | for (int row = 0; row < m.length; row++) { 120 | for (int col = 0; col < m[0].length; col++) { 121 | if (m[row][col] == 1) { 122 | // row,col 5, 3 -> 5_3 123 | String position = String.valueOf(row) + "_" + String.valueOf(col); 124 | if (row - 1 >= 0 && m[row - 1][col] == 1) { 125 | String up = String.valueOf(row - 1) + "_" + String.valueOf(col); 126 | unionSet.union(up, position); 127 | } 128 | if (col - 1 >= 0 && m[row][col - 1] == 1) { 129 | String left = String.valueOf(row) + "_" + String.valueOf(col - 1); 130 | unionSet.union(left, position); 131 | } 132 | } 133 | } 134 | } 135 | return unionSet.getSetNum(); 136 | } 137 | 138 | public static void main(String[] args) { 139 | int[][] m1 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, 140 | { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, 141 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; 142 | System.out.println(countIslands1(m1)); 143 | 144 | int[][] m1Other = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, 145 | { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, 146 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; 147 | System.out.println(countIslands2(m1Other)); 148 | 149 | int[][] m2 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, 150 | { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, 151 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; 152 | System.out.println(countIslands1(m2)); 153 | 154 | int[][] m2Other = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, 155 | { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, 156 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; 157 | 158 | System.out.println(countIslands2(m2Other)); 159 | 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/class05/Code01_AVLTreeMap.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | public class Code01_AVLTreeMap { 4 | 5 | public static class AVLNode, V> { 6 | public K k; 7 | public V v; 8 | public AVLNode l; 9 | public AVLNode r; 10 | public int h; 11 | 12 | public AVLNode(K key, V value) { 13 | k = key; 14 | v = value; 15 | h = 1; 16 | } 17 | } 18 | 19 | public static class AVLTreeMap, V> { 20 | private AVLNode root; 21 | private int size; 22 | 23 | public AVLTreeMap() { 24 | root = null; 25 | size = 0; 26 | } 27 | 28 | private AVLNode rightRotate(AVLNode cur) { 29 | AVLNode left = cur.l; 30 | cur.l = left.r; 31 | left.r = cur; 32 | cur.h = Math.max((cur.l != null ? cur.l.h : 0), (cur.r != null ? cur.r.h : 0)) + 1; 33 | left.h = Math.max((left.l != null ? left.l.h : 0), (left.r != null ? left.r.h : 0)) + 1; 34 | return left; 35 | } 36 | 37 | private AVLNode leftRotate(AVLNode cur) { 38 | AVLNode right = cur.r; 39 | cur.r = right.l; 40 | right.l = cur; 41 | cur.h = Math.max((cur.l != null ? cur.l.h : 0), (cur.r != null ? cur.r.h : 0)) + 1; 42 | right.h = Math.max((right.l != null ? right.l.h : 0), (right.r != null ? right.r.h : 0)) + 1; 43 | return right; 44 | } 45 | 46 | private AVLNode maintain(AVLNode cur) { 47 | if (cur == null) { 48 | return null; 49 | } 50 | int leftHeight = cur.l != null ? cur.l.h : 0; 51 | int rightHeight = cur.r != null ? cur.r.h : 0; 52 | if (Math.abs(leftHeight - rightHeight) > 1) { 53 | if (leftHeight > rightHeight) { 54 | int leftLeftHeight = cur.l != null && cur.l.l != null ? cur.l.l.h : 0; 55 | int leftRightHeight = cur.l != null && cur.l.r != null ? cur.l.r.h : 0; 56 | if (leftLeftHeight >= leftRightHeight) { 57 | cur = rightRotate(cur); 58 | } else { 59 | cur.l = leftRotate(cur.l); 60 | cur = rightRotate(cur); 61 | } 62 | } else { 63 | int rightLeftHeight = cur.r != null && cur.r.l != null ? cur.r.l.h : 0; 64 | int rightRightHeight = cur.r != null && cur.r.r != null ? cur.r.r.h : 0; 65 | if (rightRightHeight >= rightLeftHeight) { 66 | cur = leftRotate(cur); 67 | } else { 68 | cur.r = rightRotate(cur.r); 69 | cur = leftRotate(cur); 70 | } 71 | } 72 | } 73 | return cur; 74 | } 75 | 76 | private AVLNode findLastIndex(K key) { 77 | AVLNode pre = root; 78 | AVLNode cur = root; 79 | while (cur != null) { 80 | pre = cur; 81 | if (key.compareTo(cur.k) == 0) { 82 | break; 83 | } else if (key.compareTo(cur.k) < 0) { 84 | cur = cur.l; 85 | } else { 86 | cur = cur.r; 87 | } 88 | } 89 | return pre; 90 | } 91 | 92 | private AVLNode findLastNoSmallIndex(K key) { 93 | AVLNode ans = null; 94 | AVLNode cur = root; 95 | while (cur != null) { 96 | if (key.compareTo(cur.k) == 0) { 97 | ans = cur; 98 | break; 99 | } else if (key.compareTo(cur.k) < 0) { 100 | ans = cur; 101 | cur = cur.l; 102 | } else { 103 | cur = cur.r; 104 | } 105 | } 106 | return ans; 107 | } 108 | 109 | private AVLNode findLastNoBigIndex(K key) { 110 | AVLNode ans = null; 111 | AVLNode cur = root; 112 | while (cur != null) { 113 | if (key.compareTo(cur.k) == 0) { 114 | ans = cur; 115 | break; 116 | } else if (key.compareTo(cur.k) < 0) { 117 | cur = cur.l; 118 | } else { 119 | ans = cur; 120 | cur = cur.r; 121 | } 122 | } 123 | return ans; 124 | } 125 | 126 | private AVLNode add(AVLNode cur, K key, V value) { 127 | if (cur == null) { 128 | return new AVLNode(key, value); 129 | } else { 130 | if (key.compareTo(cur.k) < 0) { 131 | cur.l = add(cur.l, key, value); 132 | } else { 133 | cur.r = add(cur.r, key, value); 134 | } 135 | cur.h = Math.max(cur.l != null ? cur.l.h : 0, cur.r != null ? cur.r.h : 0) + 1; 136 | return maintain(cur); 137 | } 138 | } 139 | 140 | // 在cur这棵树上,删掉key所代表的节点 141 | // 返回cur这棵树的新头部 142 | private AVLNode delete(AVLNode cur, K key) { 143 | if (key.compareTo(cur.k) > 0) { 144 | cur.r = delete(cur.r, key); 145 | } else if (key.compareTo(cur.k) < 0) { 146 | cur.l = delete(cur.l, key); 147 | } else { 148 | if (cur.l == null && cur.r == null) { 149 | cur = null; 150 | } else if (cur.l == null && cur.r != null) { 151 | cur = cur.r; 152 | } else if (cur.l != null && cur.r == null) { 153 | cur = cur.l; 154 | } else { 155 | AVLNode des = cur.r; 156 | while (des.l != null) { 157 | des = des.l; 158 | } 159 | cur.r = delete(cur.r, des.k); 160 | des.l = cur.l; 161 | des.r = cur.r; 162 | cur = des; 163 | } 164 | } 165 | if (cur != null) { 166 | cur.h = Math.max(cur.l != null ? cur.l.h : 0, cur.r != null ? cur.r.h : 0) + 1; 167 | } 168 | return maintain(cur); 169 | } 170 | 171 | public int size() { 172 | return size; 173 | } 174 | 175 | public boolean containsKey(K key) { 176 | if (key == null) { 177 | return false; 178 | } 179 | AVLNode lastNode = findLastIndex(key); 180 | return lastNode != null && key.compareTo(lastNode.k) == 0 ? true : false; 181 | } 182 | 183 | public void put(K key, V value) { 184 | if (key == null) { 185 | return; 186 | } 187 | AVLNode lastNode = findLastIndex(key); 188 | if (lastNode != null && key.compareTo(lastNode.k) == 0) { 189 | lastNode.v = value; 190 | } else { 191 | size++; 192 | root = add(root, key, value); 193 | } 194 | } 195 | 196 | public void remove(K key) { 197 | if (key == null) { 198 | return; 199 | } 200 | if (containsKey(key)) { 201 | size--; 202 | root = delete(root, key); 203 | } 204 | } 205 | 206 | public V get(K key) { 207 | if (key == null) { 208 | return null; 209 | } 210 | AVLNode lastNode = findLastIndex(key); 211 | if (lastNode != null && key.compareTo(lastNode.k) == 0) { 212 | return lastNode.v; 213 | } 214 | return null; 215 | } 216 | 217 | public K firstKey() { 218 | if (root == null) { 219 | return null; 220 | } 221 | AVLNode cur = root; 222 | while (cur.l != null) { 223 | cur = cur.l; 224 | } 225 | return cur.k; 226 | } 227 | 228 | public K lastKey() { 229 | if (root == null) { 230 | return null; 231 | } 232 | AVLNode cur = root; 233 | while (cur.r != null) { 234 | cur = cur.r; 235 | } 236 | return cur.k; 237 | } 238 | 239 | public K floorKey(K key) { 240 | if (key == null) { 241 | return null; 242 | } 243 | AVLNode lastNoBigNode = findLastNoBigIndex(key); 244 | return lastNoBigNode == null ? null : lastNoBigNode.k; 245 | } 246 | 247 | public K ceilingKey(K key) { 248 | if (key == null) { 249 | return null; 250 | } 251 | AVLNode lastNoSmallNode = findLastNoSmallIndex(key); 252 | return lastNoSmallNode == null ? null : lastNoSmallNode.k; 253 | } 254 | 255 | } 256 | 257 | } 258 | -------------------------------------------------------------------------------- /src/class05/Code02_SizeBalancedTreeMap.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | public class Code02_SizeBalancedTreeMap { 4 | 5 | public static class SBTNode, V> { 6 | public K key; 7 | public V value; 8 | public SBTNode l; 9 | public SBTNode r; 10 | public int size; // 不同的key的数量 11 | 12 | public SBTNode(K key, V value) { 13 | this.key = key; 14 | this.value = value; 15 | size = 1; 16 | } 17 | } 18 | 19 | public static class SizeBalancedTreeMap, V> { 20 | private SBTNode root; 21 | 22 | private SBTNode rightRotate(SBTNode cur) { 23 | SBTNode leftNode = cur.l; 24 | cur.l = leftNode.r; 25 | leftNode.r = cur; 26 | leftNode.size = cur.size; 27 | cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; 28 | return leftNode; 29 | } 30 | 31 | private SBTNode leftRotate(SBTNode cur) { 32 | SBTNode rightNode = cur.r; 33 | cur.r = rightNode.l; 34 | rightNode.l = cur; 35 | rightNode.size = cur.size; 36 | cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; 37 | return rightNode; 38 | } 39 | 40 | private SBTNode maintain(SBTNode cur) { 41 | if (cur == null) { 42 | return null; 43 | } 44 | int leftSize = cur.l != null ? cur.l.size : 0; 45 | int leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0; 46 | int leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0; 47 | int rightSize = cur.r != null ? cur.r.size : 0; 48 | int rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0; 49 | int rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0; 50 | if (leftLeftSize > rightSize) { 51 | cur = rightRotate(cur); 52 | cur.r = maintain(cur.r); 53 | cur = maintain(cur); 54 | } else if (leftRightSize > rightSize) { 55 | cur.l = leftRotate(cur.l); 56 | cur = rightRotate(cur); 57 | cur.l = maintain(cur.l); 58 | cur.r = maintain(cur.r); 59 | cur = maintain(cur); 60 | } else if (rightRightSize > leftSize) { 61 | cur = leftRotate(cur); 62 | cur.l = maintain(cur.l); 63 | cur = maintain(cur); 64 | } else if (rightLeftSize > leftSize) { 65 | cur.r = rightRotate(cur.r); 66 | cur = leftRotate(cur); 67 | cur.l = maintain(cur.l); 68 | cur.r = maintain(cur.r); 69 | cur = maintain(cur); 70 | } 71 | return cur; 72 | } 73 | 74 | private SBTNode findLastIndex(K key) { 75 | SBTNode pre = root; 76 | SBTNode cur = root; 77 | while (cur != null) { 78 | pre = cur; 79 | if (key.compareTo(cur.key) == 0) { 80 | break; 81 | } else if (key.compareTo(cur.key) < 0) { 82 | cur = cur.l; 83 | } else { 84 | cur = cur.r; 85 | } 86 | } 87 | return pre; 88 | } 89 | 90 | private SBTNode findLastNoSmallIndex(K key) { 91 | SBTNode ans = null; 92 | SBTNode cur = root; 93 | while (cur != null) { 94 | if (key.compareTo(cur.key) == 0) { 95 | ans = cur; 96 | break; 97 | } else if (key.compareTo(cur.key) < 0) { 98 | ans = cur; 99 | cur = cur.l; 100 | } else { 101 | cur = cur.r; 102 | } 103 | } 104 | return ans; 105 | } 106 | 107 | private SBTNode findLastNoBigIndex(K key) { 108 | SBTNode ans = null; 109 | SBTNode cur = root; 110 | while (cur != null) { 111 | if (key.compareTo(cur.key) == 0) { 112 | ans = cur; 113 | break; 114 | } else if (key.compareTo(cur.key) < 0) { 115 | cur = cur.l; 116 | } else { 117 | ans = cur; 118 | cur = cur.r; 119 | } 120 | } 121 | return ans; 122 | } 123 | 124 | // 现在,以cur为头的树上,新增,加(key, value)这样的记录 125 | // 加完之后,会对cur做检查,该调整调整 126 | // 返回,调整完之后,整棵树的新头部 127 | private SBTNode add(SBTNode cur, K key, V value) { 128 | if (cur == null) { 129 | return new SBTNode(key, value); 130 | } else { 131 | cur.size++; 132 | if (key.compareTo(cur.key) < 0) { 133 | cur.l = add(cur.l, key, value); 134 | } else { 135 | cur.r = add(cur.r, key, value); 136 | } 137 | return maintain(cur); 138 | } 139 | } 140 | 141 | // 在cur这棵树上,删掉key所代表的节点 142 | // 返回cur这棵树的新头部 143 | private SBTNode delete(SBTNode cur, K key) { 144 | cur.size--; 145 | if (key.compareTo(cur.key) > 0) { 146 | cur.r = delete(cur.r, key); 147 | } else if (key.compareTo(cur.key) < 0) { 148 | cur.l = delete(cur.l, key); 149 | } else { // 当前要删掉cur 150 | if (cur.l == null && cur.r == null) { 151 | // free cur memory -> C++ 152 | cur = null; 153 | } else if (cur.l == null && cur.r != null) { 154 | // free cur memory -> C++ 155 | cur = cur.r; 156 | } else if (cur.l != null && cur.r == null) { 157 | // free cur memory -> C++ 158 | cur = cur.l; 159 | } else { // 有左有右 160 | SBTNode pre = null; 161 | SBTNode des = cur.r; 162 | des.size--; 163 | while (des.l != null) { 164 | pre = des; 165 | des = des.l; 166 | des.size--; 167 | } 168 | if (pre != null) { 169 | pre.l = des.r; 170 | des.r = cur.r; 171 | } 172 | des.l = cur.l; 173 | des.size = des.l.size + (des.r == null ? 0 : des.r.size) + 1; 174 | // free cur memory -> C++ 175 | cur = des; 176 | } 177 | } 178 | // cur = maintain(cur); 179 | return cur; 180 | } 181 | 182 | private SBTNode getIndex(SBTNode cur, int kth) { 183 | if (kth == (cur.l != null ? cur.l.size : 0) + 1) { 184 | return cur; 185 | } else if (kth <= (cur.l != null ? cur.l.size : 0)) { 186 | return getIndex(cur.l, kth); 187 | } else { 188 | return getIndex(cur.r, kth - (cur.l != null ? cur.l.size : 0) - 1); 189 | } 190 | } 191 | 192 | public int size() { 193 | return root == null ? 0 : root.size; 194 | } 195 | 196 | public boolean containsKey(K key) { 197 | if (key == null) { 198 | throw new RuntimeException("invalid parameter."); 199 | } 200 | SBTNode lastNode = findLastIndex(key); 201 | return lastNode != null && key.compareTo(lastNode.key) == 0 ? true : false; 202 | } 203 | 204 | // (key,value) put -> 有序表 新增、改value 205 | public void put(K key, V value) { 206 | if (key == null) { 207 | throw new RuntimeException("invalid parameter."); 208 | } 209 | SBTNode lastNode = findLastIndex(key); 210 | if (lastNode != null && key.compareTo(lastNode.key) == 0) { 211 | lastNode.value = value; 212 | } else { 213 | root = add(root, key, value); 214 | } 215 | } 216 | 217 | public void remove(K key) { 218 | if (key == null) { 219 | throw new RuntimeException("invalid parameter."); 220 | } 221 | if (containsKey(key)) { 222 | root = delete(root, key); 223 | } 224 | } 225 | 226 | public K getIndexKey(int index) { 227 | if (index < 0 || index >= this.size()) { 228 | throw new RuntimeException("invalid parameter."); 229 | } 230 | return getIndex(root, index + 1).key; 231 | } 232 | 233 | public V getIndexValue(int index) { 234 | if (index < 0 || index >= this.size()) { 235 | throw new RuntimeException("invalid parameter."); 236 | } 237 | return getIndex(root, index + 1).value; 238 | } 239 | 240 | public V get(K key) { 241 | if (key == null) { 242 | throw new RuntimeException("invalid parameter."); 243 | } 244 | SBTNode lastNode = findLastIndex(key); 245 | if (lastNode != null && key.compareTo(lastNode.key) == 0) { 246 | return lastNode.value; 247 | } else { 248 | return null; 249 | } 250 | } 251 | 252 | public K firstKey() { 253 | if (root == null) { 254 | return null; 255 | } 256 | SBTNode cur = root; 257 | while (cur.l != null) { 258 | cur = cur.l; 259 | } 260 | return cur.key; 261 | } 262 | 263 | public K lastKey() { 264 | if (root == null) { 265 | return null; 266 | } 267 | SBTNode cur = root; 268 | while (cur.r != null) { 269 | cur = cur.r; 270 | } 271 | return cur.key; 272 | } 273 | 274 | public K floorKey(K key) { 275 | if (key == null) { 276 | throw new RuntimeException("invalid parameter."); 277 | } 278 | SBTNode lastNoBigNode = findLastNoBigIndex(key); 279 | return lastNoBigNode == null ? null : lastNoBigNode.key; 280 | } 281 | 282 | public K ceilingKey(K key) { 283 | if (key == null) { 284 | throw new RuntimeException("invalid parameter."); 285 | } 286 | SBTNode lastNoSmallNode = findLastNoSmallIndex(key); 287 | return lastNoSmallNode == null ? null : lastNoSmallNode.key; 288 | } 289 | 290 | } 291 | 292 | // for test 293 | public static void printAll(SBTNode head) { 294 | System.out.println("Binary Tree:"); 295 | printInOrder(head, 0, "H", 17); 296 | System.out.println(); 297 | } 298 | 299 | // for test 300 | public static void printInOrder(SBTNode head, int height, String to, int len) { 301 | if (head == null) { 302 | return; 303 | } 304 | printInOrder(head.r, height + 1, "v", len); 305 | String val = to + "(" + head.key + "," + head.value + ")" + to; 306 | int lenM = val.length(); 307 | int lenL = (len - lenM) / 2; 308 | int lenR = len - lenM - lenL; 309 | val = getSpace(lenL) + val + getSpace(lenR); 310 | System.out.println(getSpace(height * len) + val); 311 | printInOrder(head.l, height + 1, "^", len); 312 | } 313 | 314 | // for test 315 | public static String getSpace(int num) { 316 | String space = " "; 317 | StringBuffer buf = new StringBuffer(""); 318 | for (int i = 0; i < num; i++) { 319 | buf.append(space); 320 | } 321 | return buf.toString(); 322 | } 323 | 324 | public static void main(String[] args) { 325 | SizeBalancedTreeMap sbt = new SizeBalancedTreeMap(); 326 | sbt.put("d", 4); 327 | sbt.put("c", 3); 328 | sbt.put("a", 1); 329 | sbt.put("b", 2); 330 | // sbt.put("e", 5); 331 | sbt.put("g", 7); 332 | sbt.put("f", 6); 333 | sbt.put("h", 8); 334 | sbt.put("i", 9); 335 | sbt.put("a", 111); 336 | System.out.println(sbt.get("a")); 337 | sbt.put("a", 1); 338 | System.out.println(sbt.get("a")); 339 | for (int i = 0; i < sbt.size(); i++) { 340 | System.out.println(sbt.getIndexKey(i) + " , " + sbt.getIndexValue(i)); 341 | } 342 | printAll(sbt.root); 343 | System.out.println(sbt.firstKey()); 344 | System.out.println(sbt.lastKey()); 345 | System.out.println(sbt.floorKey("g")); 346 | System.out.println(sbt.ceilingKey("g")); 347 | System.out.println(sbt.floorKey("e")); 348 | System.out.println(sbt.ceilingKey("e")); 349 | System.out.println(sbt.floorKey("")); 350 | System.out.println(sbt.ceilingKey("")); 351 | System.out.println(sbt.floorKey("j")); 352 | System.out.println(sbt.ceilingKey("j")); 353 | sbt.remove("d"); 354 | printAll(sbt.root); 355 | sbt.remove("f"); 356 | printAll(sbt.root); 357 | 358 | } 359 | 360 | } 361 | -------------------------------------------------------------------------------- /src/class05/Code03_SkipListMap.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Code03_SkipListMap { 6 | 7 | // 跳表的节点定义 8 | public static class SkipListNode, V> { 9 | public K key; 10 | public V val; 11 | public ArrayList> nextNodes; 12 | 13 | public SkipListNode(K k, V v) { 14 | key = k; 15 | val = v; 16 | nextNodes = new ArrayList>(); 17 | } 18 | 19 | // 遍历的时候,如果是往右遍历到的null(next == null), 遍历结束 20 | // 头(null), 头节点的null,认为最小 21 | // node -> 头,node(null, "") node.isKeyLess(!null) true 22 | // node里面的key是否比otherKey小,true,不是false 23 | public boolean isKeyLess(K otherKey) { 24 | // otherKey == null -> false 25 | return otherKey != null && (key == null || key.compareTo(otherKey) < 0); 26 | } 27 | 28 | public boolean isKeyEqual(K otherKey) { 29 | return (key == null && otherKey == null) 30 | || (key != null && otherKey != null && key.compareTo(otherKey) == 0); 31 | } 32 | 33 | } 34 | 35 | public static class SkipListMap, V> { 36 | private static final double PROBABILITY = 0.5; // < 0.5 继续做,>=0.5 停 37 | private SkipListNode head; 38 | private int size; 39 | private int maxLevel; 40 | 41 | public SkipListMap() { 42 | head = new SkipListNode(null, null); 43 | head.nextNodes.add(null); // 0 44 | size = 0; 45 | maxLevel = 0; 46 | } 47 | 48 | // 从最高层开始,一路找下去, 49 | // 最终,找到第0层的 mostRightLessNodeInTree(K key) { 51 | if (key == null) { 52 | return null; 53 | } 54 | int level = maxLevel; 55 | SkipListNode cur = head; 56 | while (level >= 0) { // 从上层跳下层 57 | // cur level -> level-1 58 | cur = mostRightLessNodeInLevel(key, cur, level--); 59 | } 60 | return cur; 61 | } 62 | 63 | // 在level层里,如何往右移动 64 | // 现在来到的节点是cur,来到了cur的level层,在level层上,找到 mostRightLessNodeInLevel(K key, 66 | SkipListNode cur, 67 | int level) { 68 | SkipListNode next = cur.nextNodes.get(level); 69 | while (next != null && next.isKeyLess(key)) { 70 | cur = next; 71 | next = cur.nextNodes.get(level); 72 | } 73 | return cur; 74 | } 75 | 76 | public boolean containsKey(K key) { 77 | if (key == null) { 78 | return false; 79 | } 80 | SkipListNode less = mostRightLessNodeInTree(key); 81 | SkipListNode next = less.nextNodes.get(0); 82 | return next != null && next.isKeyEqual(key); 83 | } 84 | 85 | // 新增、改value 86 | public void put(K key, V value) { 87 | if (key == null) { 88 | return; 89 | } 90 | // 0层上,最右一个,< key 的Node -> >key 91 | SkipListNode less = mostRightLessNodeInTree(key); 92 | SkipListNode find = less.nextNodes.get(0); 93 | if (find != null && find.isKeyEqual(key)) { 94 | find.val = value; 95 | } else { // find == null 8 7 9 96 | size++; 97 | int newNodeLevel = 0; 98 | while (Math.random() < PROBABILITY) { 99 | newNodeLevel++; 100 | } 101 | // newNodeLevel 102 | while (newNodeLevel > maxLevel) { 103 | head.nextNodes.add(null); 104 | maxLevel++; 105 | } 106 | SkipListNode newNode = new SkipListNode(key, value); 107 | for (int i = 0; i <= newNodeLevel; i++) { 108 | newNode.nextNodes.add(null); 109 | } 110 | int level = maxLevel; 111 | SkipListNode pre = head; 112 | while (level >= 0) { 113 | // level 层中,找到最右的 < key 的节点 114 | pre = mostRightLessNodeInLevel(key, pre, level); 115 | if (level <= newNodeLevel) { 116 | newNode.nextNodes.set(level, pre.nextNodes.get(level)); 117 | pre.nextNodes.set(level, newNode); 118 | } 119 | level--; 120 | } 121 | } 122 | } 123 | 124 | public V get(K key) { 125 | if (key == null) { 126 | return null; 127 | } 128 | SkipListNode less = mostRightLessNodeInTree(key); 129 | SkipListNode next = less.nextNodes.get(0); 130 | return next != null && next.isKeyEqual(key) ? next.val : null; 131 | } 132 | 133 | public void remove(K key) { 134 | if (containsKey(key)) { 135 | size--; 136 | int level = maxLevel; 137 | SkipListNode pre = head; 138 | while (level >= 0) { 139 | pre = mostRightLessNodeInLevel(key, pre, level); 140 | SkipListNode next = pre.nextNodes.get(level); 141 | // 1)在这一层中,pre下一个就是key 142 | // 2)在这一层中,pre的下一个key是>要删除key 143 | if (next != null && next.isKeyEqual(key)) { 144 | // free delete node memory -> C++ 145 | // level : pre -> next(key) -> ... 146 | pre.nextNodes.set(level, next.nextNodes.get(level)); 147 | } 148 | // 在level层只有一个节点了,就是默认节点head 149 | if (level != 0 && pre == head && pre.nextNodes.get(level) == null) { 150 | head.nextNodes.remove(level); 151 | maxLevel--; 152 | } 153 | level--; 154 | } 155 | } 156 | } 157 | 158 | public K firstKey() { 159 | return head.nextNodes.get(0) != null ? head.nextNodes.get(0).key : null; 160 | } 161 | 162 | public K lastKey() { 163 | int level = maxLevel; 164 | SkipListNode cur = head; 165 | while (level >= 0) { 166 | SkipListNode next = cur.nextNodes.get(level); 167 | while (next != null) { 168 | cur = next; 169 | next = cur.nextNodes.get(level); 170 | } 171 | level--; 172 | } 173 | return cur.key; 174 | } 175 | 176 | public K ceilingKey(K key) { 177 | if (key == null) { 178 | return null; 179 | } 180 | SkipListNode less = mostRightLessNodeInTree(key); 181 | SkipListNode next = less.nextNodes.get(0); 182 | return next != null ? next.key : null; 183 | } 184 | 185 | public K floorKey(K key) { 186 | if (key == null) { 187 | return null; 188 | } 189 | SkipListNode less = mostRightLessNodeInTree(key); 190 | SkipListNode next = less.nextNodes.get(0); 191 | return next != null && next.isKeyEqual(key) ? next.key : less.key; 192 | } 193 | 194 | public int size() { 195 | return size; 196 | } 197 | 198 | } 199 | 200 | // for test 201 | public static void printAll(SkipListMap obj) { 202 | for (int i = obj.maxLevel; i >= 0; i--) { 203 | System.out.print("Level " + i + " : "); 204 | SkipListNode cur = obj.head; 205 | while (cur.nextNodes.get(i) != null) { 206 | SkipListNode next = cur.nextNodes.get(i); 207 | System.out.print("(" + next.key + " , " + next.val + ") "); 208 | cur = next; 209 | } 210 | System.out.println(); 211 | } 212 | } 213 | 214 | public static void main(String[] args) { 215 | SkipListMap test = new SkipListMap<>(); 216 | printAll(test); 217 | System.out.println("======================"); 218 | test.put("A", "10"); 219 | printAll(test); 220 | System.out.println("======================"); 221 | test.remove("A"); 222 | printAll(test); 223 | System.out.println("======================"); 224 | test.put("E", "E"); 225 | test.put("B", "B"); 226 | test.put("A", "A"); 227 | test.put("F", "F"); 228 | test.put("C", "C"); 229 | test.put("D", "D"); 230 | printAll(test); 231 | System.out.println("======================"); 232 | System.out.println(test.containsKey("B")); 233 | System.out.println(test.containsKey("Z")); 234 | System.out.println(test.firstKey()); 235 | System.out.println(test.lastKey()); 236 | System.out.println(test.floorKey("D")); 237 | System.out.println(test.ceilingKey("D")); 238 | System.out.println("======================"); 239 | test.remove("D"); 240 | printAll(test); 241 | System.out.println("======================"); 242 | System.out.println(test.floorKey("D")); 243 | System.out.println(test.ceilingKey("D")); 244 | 245 | 246 | } 247 | 248 | } 249 | -------------------------------------------------------------------------------- /src/class05/Compare.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | import java.util.TreeMap; 4 | 5 | import class05.Code01_AVLTreeMap.AVLTreeMap; 6 | import class05.Code02_SizeBalancedTreeMap.SizeBalancedTreeMap; 7 | import class05.Code03_SkipListMap.SkipListMap; 8 | 9 | // 本文件为avl、sbt、skiplist三种结构的测试文件 10 | public class Compare { 11 | 12 | public static void functionTest() { 13 | System.out.println("功能测试开始"); 14 | TreeMap treeMap = new TreeMap<>(); 15 | AVLTreeMap avl = new AVLTreeMap<>(); 16 | SizeBalancedTreeMap sbt = new SizeBalancedTreeMap<>(); 17 | SkipListMap skip = new SkipListMap<>(); 18 | int maxK = 500; 19 | int maxV = 50000; 20 | int testTime = 1000000; 21 | for (int i = 0; i < testTime; i++) { 22 | int addK = (int) (Math.random() * maxK); 23 | int addV = (int) (Math.random() * maxV); 24 | treeMap.put(addK, addV); 25 | avl.put(addK, addV); 26 | sbt.put(addK, addV); 27 | skip.put(addK, addV); 28 | 29 | int removeK = (int) (Math.random() * maxK); 30 | treeMap.remove(removeK); 31 | avl.remove(removeK); 32 | sbt.remove(removeK); 33 | skip.remove(removeK); 34 | 35 | int querryK = (int) (Math.random() * maxK); 36 | if (treeMap.containsKey(querryK) != avl.containsKey(querryK) 37 | || sbt.containsKey(querryK) != skip.containsKey(querryK) 38 | || treeMap.containsKey(querryK) != sbt.containsKey(querryK)) { 39 | System.out.println("containsKey Oops"); 40 | System.out.println(treeMap.containsKey(querryK)); 41 | System.out.println(avl.containsKey(querryK)); 42 | System.out.println(sbt.containsKey(querryK)); 43 | System.out.println(skip.containsKey(querryK)); 44 | break; 45 | } 46 | 47 | if (treeMap.containsKey(querryK)) { 48 | int v1 = treeMap.get(querryK); 49 | int v2 = avl.get(querryK); 50 | int v3 = sbt.get(querryK); 51 | int v4 = skip.get(querryK); 52 | if (v1 != v2 || v3 != v4 || v1 != v3) { 53 | System.out.println("get Oops"); 54 | System.out.println(treeMap.get(querryK)); 55 | System.out.println(avl.get(querryK)); 56 | System.out.println(sbt.get(querryK)); 57 | System.out.println(skip.get(querryK)); 58 | break; 59 | } 60 | Integer f1 = treeMap.floorKey(querryK); 61 | Integer f2 = avl.floorKey(querryK); 62 | Integer f3 = sbt.floorKey(querryK); 63 | Integer f4 = skip.floorKey(querryK); 64 | if (f1 == null && (f2 != null || f3 != null || f4 != null)) { 65 | System.out.println("floorKey Oops"); 66 | System.out.println(treeMap.floorKey(querryK)); 67 | System.out.println(avl.floorKey(querryK)); 68 | System.out.println(sbt.floorKey(querryK)); 69 | System.out.println(skip.floorKey(querryK)); 70 | break; 71 | } 72 | if (f1 != null && (f2 == null || f3 == null || f4 == null)) { 73 | System.out.println("floorKey Oops"); 74 | System.out.println(treeMap.floorKey(querryK)); 75 | System.out.println(avl.floorKey(querryK)); 76 | System.out.println(sbt.floorKey(querryK)); 77 | System.out.println(skip.floorKey(querryK)); 78 | break; 79 | } 80 | if (f1 != null) { 81 | int ans1 = f1; 82 | int ans2 = f2; 83 | int ans3 = f3; 84 | int ans4 = f4; 85 | if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { 86 | System.out.println("floorKey Oops"); 87 | System.out.println(treeMap.floorKey(querryK)); 88 | System.out.println(avl.floorKey(querryK)); 89 | System.out.println(sbt.floorKey(querryK)); 90 | System.out.println(skip.floorKey(querryK)); 91 | break; 92 | } 93 | } 94 | f1 = treeMap.ceilingKey(querryK); 95 | f2 = avl.ceilingKey(querryK); 96 | f3 = sbt.ceilingKey(querryK); 97 | f4 = skip.ceilingKey(querryK); 98 | if (f1 == null && (f2 != null || f3 != null || f4 != null)) { 99 | System.out.println("ceilingKey Oops"); 100 | System.out.println(treeMap.ceilingKey(querryK)); 101 | System.out.println(avl.ceilingKey(querryK)); 102 | System.out.println(sbt.ceilingKey(querryK)); 103 | System.out.println(skip.ceilingKey(querryK)); 104 | break; 105 | } 106 | if (f1 != null && (f2 == null || f3 == null || f4 == null)) { 107 | System.out.println("ceilingKey Oops"); 108 | System.out.println(treeMap.ceilingKey(querryK)); 109 | System.out.println(avl.ceilingKey(querryK)); 110 | System.out.println(sbt.ceilingKey(querryK)); 111 | System.out.println(skip.ceilingKey(querryK)); 112 | break; 113 | } 114 | if (f1 != null) { 115 | int ans1 = f1; 116 | int ans2 = f2; 117 | int ans3 = f3; 118 | int ans4 = f4; 119 | if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { 120 | System.out.println("ceilingKey Oops"); 121 | System.out.println(treeMap.ceilingKey(querryK)); 122 | System.out.println(avl.ceilingKey(querryK)); 123 | System.out.println(sbt.ceilingKey(querryK)); 124 | System.out.println(skip.ceilingKey(querryK)); 125 | break; 126 | } 127 | } 128 | 129 | } 130 | 131 | Integer f1 = treeMap.firstKey(); 132 | Integer f2 = avl.firstKey(); 133 | Integer f3 = sbt.firstKey(); 134 | Integer f4 = skip.firstKey(); 135 | if (f1 == null && (f2 != null || f3 != null || f4 != null)) { 136 | System.out.println("firstKey Oops"); 137 | System.out.println(treeMap.firstKey()); 138 | System.out.println(avl.firstKey()); 139 | System.out.println(sbt.firstKey()); 140 | System.out.println(skip.firstKey()); 141 | break; 142 | } 143 | if (f1 != null && (f2 == null || f3 == null || f4 == null)) { 144 | System.out.println("firstKey Oops"); 145 | System.out.println(treeMap.firstKey()); 146 | System.out.println(avl.firstKey()); 147 | System.out.println(sbt.firstKey()); 148 | System.out.println(skip.firstKey()); 149 | break; 150 | } 151 | if (f1 != null) { 152 | int ans1 = f1; 153 | int ans2 = f2; 154 | int ans3 = f3; 155 | int ans4 = f4; 156 | if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { 157 | System.out.println("firstKey Oops"); 158 | System.out.println(treeMap.firstKey()); 159 | System.out.println(avl.firstKey()); 160 | System.out.println(sbt.firstKey()); 161 | System.out.println(skip.firstKey()); 162 | break; 163 | } 164 | } 165 | 166 | f1 = treeMap.lastKey(); 167 | f2 = avl.lastKey(); 168 | f3 = sbt.lastKey(); 169 | f4 = skip.lastKey(); 170 | if (f1 == null && (f2 != null || f3 != null || f4 != null)) { 171 | System.out.println("lastKey Oops"); 172 | System.out.println(treeMap.lastKey()); 173 | System.out.println(avl.lastKey()); 174 | System.out.println(sbt.lastKey()); 175 | System.out.println(skip.lastKey()); 176 | break; 177 | } 178 | if (f1 != null && (f2 == null || f3 == null || f4 == null)) { 179 | System.out.println("firstKey Oops"); 180 | System.out.println(treeMap.lastKey()); 181 | System.out.println(avl.lastKey()); 182 | System.out.println(sbt.lastKey()); 183 | System.out.println(skip.lastKey()); 184 | break; 185 | } 186 | if (f1 != null) { 187 | int ans1 = f1; 188 | int ans2 = f2; 189 | int ans3 = f3; 190 | int ans4 = f4; 191 | if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { 192 | System.out.println("lastKey Oops"); 193 | System.out.println(treeMap.lastKey()); 194 | System.out.println(avl.lastKey()); 195 | System.out.println(sbt.lastKey()); 196 | System.out.println(skip.lastKey()); 197 | break; 198 | } 199 | } 200 | if (treeMap.size() != avl.size() || sbt.size() != skip.size() || treeMap.size() != sbt.size()) { 201 | System.out.println("size Oops"); 202 | System.out.println(treeMap.size()); 203 | System.out.println(avl.size()); 204 | System.out.println(sbt.size()); 205 | System.out.println(skip.size()); 206 | break; 207 | } 208 | } 209 | System.out.println("功能测试结束"); 210 | } 211 | 212 | public static void performanceTest() { 213 | System.out.println("性能测试开始"); 214 | TreeMap treeMap; 215 | AVLTreeMap avl; 216 | SizeBalancedTreeMap sbt; 217 | SkipListMap skip; 218 | long start; 219 | long end; 220 | int max = 1000000; 221 | treeMap = new TreeMap<>(); 222 | avl = new AVLTreeMap<>(); 223 | sbt = new SizeBalancedTreeMap<>(); 224 | skip = new SkipListMap<>(); 225 | System.out.println("顺序递增加入测试,数据规模 : " + max); 226 | start = System.currentTimeMillis(); 227 | for (int i = 0; i < max; i++) { 228 | treeMap.put(i, i); 229 | } 230 | end = System.currentTimeMillis(); 231 | System.out.println("treeMap 运行时间 : " + (end - start) + "ms"); 232 | 233 | start = System.currentTimeMillis(); 234 | for (int i = 0; i < max; i++) { 235 | avl.put(i, i); 236 | } 237 | end = System.currentTimeMillis(); 238 | System.out.println("avl 运行时间 : " + (end - start) + "ms"); 239 | 240 | start = System.currentTimeMillis(); 241 | for (int i = 0; i < max; i++) { 242 | sbt.put(i, i); 243 | } 244 | end = System.currentTimeMillis(); 245 | System.out.println("sbt 运行时间 : " + (end - start) + "ms"); 246 | 247 | start = System.currentTimeMillis(); 248 | for (int i = 0; i < max; i++) { 249 | skip.put(i, i); 250 | } 251 | end = System.currentTimeMillis(); 252 | System.out.println("skip 运行时间 : " + (end - start) + "ms"); 253 | 254 | System.out.println("顺序递增删除测试,数据规模 : " + max); 255 | start = System.currentTimeMillis(); 256 | for (int i = 0; i < max; i++) { 257 | treeMap.remove(i); 258 | } 259 | end = System.currentTimeMillis(); 260 | System.out.println("treeMap 运行时间 : " + (end - start) + "ms"); 261 | 262 | start = System.currentTimeMillis(); 263 | for (int i = 0; i < max; i++) { 264 | avl.remove(i); 265 | } 266 | end = System.currentTimeMillis(); 267 | System.out.println("avl 运行时间 : " + (end - start) + "ms"); 268 | 269 | start = System.currentTimeMillis(); 270 | for (int i = 0; i < max; i++) { 271 | sbt.remove(i); 272 | } 273 | end = System.currentTimeMillis(); 274 | System.out.println("sbt 运行时间 : " + (end - start) + "ms"); 275 | 276 | start = System.currentTimeMillis(); 277 | for (int i = 0; i < max; i++) { 278 | skip.remove(i); 279 | } 280 | end = System.currentTimeMillis(); 281 | System.out.println("skip 运行时间 : " + (end - start) + "ms"); 282 | 283 | System.out.println("顺序递减加入测试,数据规模 : " + max); 284 | start = System.currentTimeMillis(); 285 | for (int i = max; i >= 0; i--) { 286 | treeMap.put(i, i); 287 | } 288 | end = System.currentTimeMillis(); 289 | System.out.println("treeMap 运行时间 : " + (end - start) + "ms"); 290 | 291 | start = System.currentTimeMillis(); 292 | for (int i = max; i >= 0; i--) { 293 | avl.put(i, i); 294 | } 295 | end = System.currentTimeMillis(); 296 | System.out.println("avl 运行时间 : " + (end - start) + "ms"); 297 | 298 | start = System.currentTimeMillis(); 299 | for (int i = max; i >= 0; i--) { 300 | sbt.put(i, i); 301 | } 302 | end = System.currentTimeMillis(); 303 | System.out.println("sbt 运行时间 : " + (end - start) + "ms"); 304 | 305 | start = System.currentTimeMillis(); 306 | for (int i = max; i >= 0; i--) { 307 | skip.put(i, i); 308 | } 309 | end = System.currentTimeMillis(); 310 | System.out.println("skip 运行时间 : " + (end - start) + "ms"); 311 | 312 | System.out.println("顺序递减删除测试,数据规模 : " + max); 313 | start = System.currentTimeMillis(); 314 | for (int i = max; i >= 0; i--) { 315 | treeMap.remove(i); 316 | } 317 | end = System.currentTimeMillis(); 318 | System.out.println("treeMap 运行时间 : " + (end - start) + "ms"); 319 | 320 | start = System.currentTimeMillis(); 321 | for (int i = max; i >= 0; i--) { 322 | avl.remove(i); 323 | } 324 | end = System.currentTimeMillis(); 325 | System.out.println("avl 运行时间 : " + (end - start) + "ms"); 326 | 327 | start = System.currentTimeMillis(); 328 | for (int i = max; i >= 0; i--) { 329 | sbt.remove(i); 330 | } 331 | end = System.currentTimeMillis(); 332 | System.out.println("sbt 运行时间 : " + (end - start) + "ms"); 333 | 334 | start = System.currentTimeMillis(); 335 | for (int i = max; i >= 0; i--) { 336 | skip.remove(i); 337 | } 338 | end = System.currentTimeMillis(); 339 | System.out.println("skip 运行时间 : " + (end - start) + "ms"); 340 | 341 | System.out.println("随机加入测试,数据规模 : " + max); 342 | start = System.currentTimeMillis(); 343 | for (int i = 0; i < max; i++) { 344 | treeMap.put((int) (Math.random() * i), i); 345 | } 346 | end = System.currentTimeMillis(); 347 | System.out.println("treeMap 运行时间 : " + (end - start) + "ms"); 348 | 349 | start = System.currentTimeMillis(); 350 | for (int i = max; i >= 0; i--) { 351 | avl.put((int) (Math.random() * i), i); 352 | } 353 | end = System.currentTimeMillis(); 354 | System.out.println("avl 运行时间 : " + (end - start) + "ms"); 355 | 356 | start = System.currentTimeMillis(); 357 | for (int i = max; i >= 0; i--) { 358 | sbt.put((int) (Math.random() * i), i); 359 | } 360 | end = System.currentTimeMillis(); 361 | System.out.println("sbt 运行时间 : " + (end - start) + "ms"); 362 | 363 | start = System.currentTimeMillis(); 364 | for (int i = max; i >= 0; i--) { 365 | skip.put((int) (Math.random() * i), i); 366 | } 367 | end = System.currentTimeMillis(); 368 | System.out.println("skip 运行时间 : " + (end - start) + "ms"); 369 | 370 | System.out.println("随机删除测试,数据规模 : " + max); 371 | start = System.currentTimeMillis(); 372 | for (int i = 0; i < max; i++) { 373 | treeMap.remove((int) (Math.random() * i)); 374 | } 375 | end = System.currentTimeMillis(); 376 | System.out.println("treeMap 运行时间 : " + (end - start) + "ms"); 377 | 378 | start = System.currentTimeMillis(); 379 | for (int i = max; i >= 0; i--) { 380 | avl.remove((int) (Math.random() * i)); 381 | } 382 | end = System.currentTimeMillis(); 383 | System.out.println("avl 运行时间 : " + (end - start) + "ms"); 384 | 385 | start = System.currentTimeMillis(); 386 | for (int i = max; i >= 0; i--) { 387 | sbt.remove((int) (Math.random() * i)); 388 | } 389 | end = System.currentTimeMillis(); 390 | System.out.println("sbt 运行时间 : " + (end - start) + "ms"); 391 | 392 | start = System.currentTimeMillis(); 393 | for (int i = max; i >= 0; i--) { 394 | skip.remove((int) (Math.random() * i)); 395 | } 396 | end = System.currentTimeMillis(); 397 | System.out.println("skip 运行时间 : " + (end - start) + "ms"); 398 | 399 | System.out.println("性能测试结束"); 400 | } 401 | 402 | public static void main(String[] args) { 403 | functionTest(); 404 | System.out.println("======"); 405 | performanceTest(); 406 | } 407 | 408 | } 409 | -------------------------------------------------------------------------------- /src/class06/AbstractBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | /** 4 | * Not implemented by zuochengyun 5 | * 6 | * Abstract binary search tree implementation. Its basically fully implemented 7 | * binary search tree, just template method is provided for creating Node (other 8 | * trees can have slightly different nodes with more info). This way some code 9 | * from standart binary search tree can be reused for other kinds of binary 10 | * trees. 11 | * 12 | * @author Ignas Lelys 13 | * @created Jun 29, 2011 14 | * 15 | */ 16 | public class AbstractBinarySearchTree { 17 | 18 | /** Root node where whole tree starts. */ 19 | public Node root; 20 | 21 | /** Tree size. */ 22 | protected int size; 23 | 24 | /** 25 | * Because this is abstract class and various trees have different 26 | * additional information on different nodes subclasses uses this abstract 27 | * method to create nodes (maybe of class {@link Node} or maybe some 28 | * different node sub class). 29 | * 30 | * @param value 31 | * Value that node will have. 32 | * @param parent 33 | * Node's parent. 34 | * @param left 35 | * Node's left child. 36 | * @param right 37 | * Node's right child. 38 | * @return Created node instance. 39 | */ 40 | protected Node createNode(int value, Node parent, Node left, Node right) { 41 | return new Node(value, parent, left, right); 42 | } 43 | 44 | /** 45 | * Finds a node with concrete value. If it is not found then null is 46 | * returned. 47 | * 48 | * @param element 49 | * Element value. 50 | * @return Node with value provided, or null if not found. 51 | */ 52 | public Node search(int element) { 53 | Node node = root; 54 | while (node != null && node.value != null && node.value != element) { 55 | if (element < node.value) { 56 | node = node.left; 57 | } else { 58 | node = node.right; 59 | } 60 | } 61 | return node; 62 | } 63 | 64 | /** 65 | * Insert new element to tree. 66 | * 67 | * @param element 68 | * Element to insert. 69 | */ 70 | public Node insert(int element) { 71 | if (root == null) { 72 | root = createNode(element, null, null, null); 73 | size++; 74 | return root; 75 | } 76 | 77 | Node insertParentNode = null; 78 | Node searchTempNode = root; 79 | while (searchTempNode != null && searchTempNode.value != null) { 80 | insertParentNode = searchTempNode; 81 | if (element < searchTempNode.value) { 82 | searchTempNode = searchTempNode.left; 83 | } else { 84 | searchTempNode = searchTempNode.right; 85 | } 86 | } 87 | 88 | Node newNode = createNode(element, insertParentNode, null, null); 89 | if (insertParentNode.value > newNode.value) { 90 | insertParentNode.left = newNode; 91 | } else { 92 | insertParentNode.right = newNode; 93 | } 94 | 95 | size++; 96 | return newNode; 97 | } 98 | 99 | /** 100 | * Removes element if node with such value exists. 101 | * 102 | * @param element 103 | * Element value to remove. 104 | * 105 | * @return New node that is in place of deleted node. Or null if element for 106 | * delete was not found. 107 | */ 108 | public Node delete(int element) { 109 | Node deleteNode = search(element); 110 | if (deleteNode != null) { 111 | return delete(deleteNode); 112 | } else { 113 | return null; 114 | } 115 | } 116 | 117 | /** 118 | * Delete logic when node is already found. 119 | * 120 | * @param deleteNode 121 | * Node that needs to be deleted. 122 | * 123 | * @return New node that is in place of deleted node. Or null if element for 124 | * delete was not found. 125 | */ 126 | protected Node delete(Node deleteNode) { 127 | if (deleteNode != null) { 128 | Node nodeToReturn = null; 129 | if (deleteNode != null) { 130 | if (deleteNode.left == null) { 131 | // transplant(a,b) b去替换a的环境,a断连掉,把b返回 132 | nodeToReturn = transplant(deleteNode, deleteNode.right); 133 | } else if (deleteNode.right == null) { 134 | nodeToReturn = transplant(deleteNode, deleteNode.left); 135 | } else { 136 | Node successorNode = getMinimum(deleteNode.right); 137 | if (successorNode.parent != deleteNode) { 138 | transplant(successorNode, successorNode.right); 139 | successorNode.right = deleteNode.right; 140 | successorNode.right.parent = successorNode; 141 | } 142 | transplant(deleteNode, successorNode); 143 | successorNode.left = deleteNode.left; 144 | successorNode.left.parent = successorNode; 145 | nodeToReturn = successorNode; 146 | } 147 | size--; 148 | } 149 | return nodeToReturn; 150 | } 151 | return null; 152 | } 153 | 154 | /** 155 | * Put one node from tree (newNode) to the place of another (nodeToReplace). 156 | * 157 | * @param nodeToReplace 158 | * Node which is replaced by newNode and removed from tree. 159 | * @param newNode 160 | * New node. 161 | * 162 | * @return New replaced node. 163 | */ 164 | private Node transplant(Node nodeToReplace, Node newNode) { 165 | if (nodeToReplace.parent == null) { 166 | this.root = newNode; 167 | } else if (nodeToReplace == nodeToReplace.parent.left) { 168 | nodeToReplace.parent.left = newNode; 169 | } else { 170 | nodeToReplace.parent.right = newNode; 171 | } 172 | if (newNode != null) { 173 | newNode.parent = nodeToReplace.parent; 174 | } 175 | return newNode; 176 | } 177 | 178 | /** 179 | * @param element 180 | * @return true if tree contains element. 181 | */ 182 | public boolean contains(int element) { 183 | return search(element) != null; 184 | } 185 | 186 | /** 187 | * @return Minimum element in tree. 188 | */ 189 | public int getMinimum() { 190 | return getMinimum(root).value; 191 | } 192 | 193 | /** 194 | * @return Maximum element in tree. 195 | */ 196 | public int getMaximum() { 197 | return getMaximum(root).value; 198 | } 199 | 200 | /** 201 | * Get next element element who is bigger than provided element. 202 | * 203 | * @param element 204 | * Element for whom descendand element is searched 205 | * @return Successor value. 206 | */ 207 | // TODO Predecessor 208 | public int getSuccessor(int element) { 209 | return getSuccessor(search(element)).value; 210 | } 211 | 212 | /** 213 | * @return Number of elements in the tree. 214 | */ 215 | public int getSize() { 216 | return size; 217 | } 218 | 219 | /** 220 | * Tree traversal with printing element values. In order method. 221 | */ 222 | public void printTreeInOrder() { 223 | printTreeInOrder(root); 224 | } 225 | 226 | /** 227 | * Tree traversal with printing element values. Pre order method. 228 | */ 229 | public void printTreePreOrder() { 230 | printTreePreOrder(root); 231 | } 232 | 233 | /** 234 | * Tree traversal with printing element values. Post order method. 235 | */ 236 | public void printTreePostOrder() { 237 | printTreePostOrder(root); 238 | } 239 | 240 | /*-------------------PRIVATE HELPER METHODS-------------------*/ 241 | 242 | private void printTreeInOrder(Node entry) { 243 | if (entry != null) { 244 | printTreeInOrder(entry.left); 245 | if (entry.value != null) { 246 | System.out.println(entry.value); 247 | } 248 | printTreeInOrder(entry.right); 249 | } 250 | } 251 | 252 | private void printTreePreOrder(Node entry) { 253 | if (entry != null) { 254 | if (entry.value != null) { 255 | System.out.println(entry.value); 256 | } 257 | printTreeInOrder(entry.left); 258 | printTreeInOrder(entry.right); 259 | } 260 | } 261 | 262 | private void printTreePostOrder(Node entry) { 263 | if (entry != null) { 264 | printTreeInOrder(entry.left); 265 | printTreeInOrder(entry.right); 266 | if (entry.value != null) { 267 | System.out.println(entry.value); 268 | } 269 | } 270 | } 271 | 272 | protected Node getMinimum(Node node) { 273 | while (node.left != null) { 274 | node = node.left; 275 | } 276 | return node; 277 | } 278 | 279 | protected Node getMaximum(Node node) { 280 | while (node.right != null) { 281 | node = node.right; 282 | } 283 | return node; 284 | } 285 | 286 | protected Node getSuccessor(Node node) { 287 | // if there is right branch, then successor is leftmost node of that 288 | // subtree 289 | if (node.right != null) { 290 | return getMinimum(node.right); 291 | } else { // otherwise it is a lowest ancestor whose left child is also 292 | // ancestor of node 293 | Node currentNode = node; 294 | Node parentNode = node.parent; 295 | while (parentNode != null && currentNode == parentNode.right) { 296 | // go up until we find parent that currentNode is not in right 297 | // subtree. 298 | currentNode = parentNode; 299 | parentNode = parentNode.parent; 300 | } 301 | return parentNode; 302 | } 303 | } 304 | 305 | // -------------------------------- TREE PRINTING 306 | // ------------------------------------ 307 | 308 | public void printTree() { 309 | printSubtree(root); 310 | } 311 | 312 | public void printSubtree(Node node) { 313 | if (node.right != null) { 314 | printTree(node.right, true, ""); 315 | } 316 | printNodeValue(node); 317 | if (node.left != null) { 318 | printTree(node.left, false, ""); 319 | } 320 | } 321 | 322 | private void printNodeValue(Node node) { 323 | if (node.value == null) { 324 | System.out.print(""); 325 | } else { 326 | System.out.print(node.value.toString()); 327 | } 328 | System.out.println(); 329 | } 330 | 331 | private void printTree(Node node, boolean isRight, String indent) { 332 | if (node.right != null) { 333 | printTree(node.right, true, indent + (isRight ? " " : " | ")); 334 | } 335 | System.out.print(indent); 336 | if (isRight) { 337 | System.out.print(" /"); 338 | } else { 339 | System.out.print(" \\"); 340 | } 341 | System.out.print("----- "); 342 | printNodeValue(node); 343 | if (node.left != null) { 344 | printTree(node.left, false, indent + (isRight ? " | " : " ")); 345 | } 346 | } 347 | 348 | public static class Node { 349 | public Node(Integer value, Node parent, Node left, Node right) { 350 | super(); 351 | this.value = value; 352 | this.parent = parent; 353 | this.left = left; 354 | this.right = right; 355 | } 356 | 357 | public Integer value; 358 | public Node parent; 359 | public Node left; 360 | public Node right; 361 | 362 | public boolean isLeaf() { 363 | return left == null && right == null; 364 | } 365 | 366 | @Override 367 | public int hashCode() { 368 | final int prime = 31; 369 | int result = 1; 370 | result = prime * result + ((value == null) ? 0 : value.hashCode()); 371 | return result; 372 | } 373 | 374 | @Override 375 | public boolean equals(Object obj) { 376 | if (this == obj) 377 | return true; 378 | if (obj == null) 379 | return false; 380 | if (getClass() != obj.getClass()) 381 | return false; 382 | Node other = (Node) obj; 383 | if (value == null) { 384 | if (other.value != null) 385 | return false; 386 | } else if (!value.equals(other.value)) 387 | return false; 388 | return true; 389 | } 390 | 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /src/class06/AbstractSelfBalancingBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | /** 4 | * Not implemented by zuochengyun 5 | * 6 | * Abstract class for self balancing binary search trees. Contains some methods 7 | * that is used for self balancing trees. 8 | * 9 | * @author Ignas Lelys 10 | * @created Jul 24, 2011 11 | * 12 | */ 13 | public abstract class AbstractSelfBalancingBinarySearchTree 14 | extends AbstractBinarySearchTree { 15 | 16 | /** 17 | * Rotate to the left. 18 | * 19 | * @param node Node on which to rotate. 20 | * @return Node that is in place of provided node after rotation. 21 | */ 22 | protected Node rotateLeft(Node node) { 23 | Node temp = node.right; 24 | temp.parent = node.parent; 25 | 26 | node.right = temp.left; 27 | if (node.right != null) { 28 | node.right.parent = node; 29 | } 30 | 31 | temp.left = node; 32 | node.parent = temp; 33 | 34 | // temp took over node's place so now its parent should point to temp 35 | if (temp.parent != null) { 36 | if (node == temp.parent.left) { 37 | temp.parent.left = temp; 38 | } else { 39 | temp.parent.right = temp; 40 | } 41 | } else { 42 | root = temp; 43 | } 44 | 45 | return temp; 46 | } 47 | 48 | /** 49 | * Rotate to the right. 50 | * 51 | * @param node Node on which to rotate. 52 | * @return Node that is in place of provided node after rotation. 53 | */ 54 | protected Node rotateRight(Node node) { 55 | Node temp = node.left; 56 | temp.parent = node.parent; 57 | 58 | node.left = temp.right; 59 | if (node.left != null) { 60 | node.left.parent = node; 61 | } 62 | 63 | temp.right = node; 64 | node.parent = temp; 65 | 66 | // temp took over node's place so now its parent should point to temp 67 | if (temp.parent != null) { 68 | if (node == temp.parent.left) { 69 | temp.parent.left = temp; 70 | } else { 71 | temp.parent.right = temp; 72 | } 73 | } else { 74 | root = temp; 75 | } 76 | 77 | return temp; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/class06/BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | /** 4 | * Not implemented by zuochengyun 5 | * 6 | * Binary search tree implementation. 7 | * 8 | * In computer science, a binary search tree (BST), which may sometimes also be 9 | * called an ordered or sorted binary tree, is a node-based binary tree data 10 | * structure which has the following properties: 11 | * 12 | * a) The left subtree of a node contains only nodes with keys less than the node's key.
13 | * b) The right subtree of a node contains only nodes with keys greater than the node's key.
14 | * c) Both the left and right subtrees must also be binary search trees.
15 | * 16 | * @author Ignas Lelys 17 | * @created May 6, 2011 18 | * 19 | */ 20 | public class BinarySearchTree extends AbstractBinarySearchTree { 21 | 22 | @Override 23 | protected Node createNode(int value, Node parent, Node left, Node right) { 24 | return new Node(value, parent, left, right); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/class06/RedBlackTree.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | /** 4 | * Not implemented by zuochengyun 5 | * 6 | * Red-Black tree implementation. From Introduction to Algorithms 3rd edition. 7 | * 8 | * @author Ignas Lelys 9 | * @created May 6, 2011 10 | * 11 | */ 12 | public class RedBlackTree extends AbstractSelfBalancingBinarySearchTree { 13 | 14 | protected enum ColorEnum { 15 | RED, 16 | BLACK 17 | }; 18 | 19 | protected static final RedBlackNode nilNode = new RedBlackNode(null, null, null, null, ColorEnum.BLACK); 20 | 21 | /** 22 | * @see trees.AbstractBinarySearchTree#insert(int) 23 | */ 24 | @Override 25 | public Node insert(int element) { 26 | Node newNode = super.insert(element); 27 | newNode.left = nilNode; 28 | newNode.right = nilNode; 29 | root.parent = nilNode; 30 | insertRBFixup((RedBlackNode) newNode); 31 | return newNode; 32 | } 33 | 34 | /** 35 | * Slightly modified delete routine for red-black tree. 36 | * 37 | * {@inheritDoc} 38 | */ 39 | @Override 40 | protected Node delete(Node deleteNode) { 41 | Node replaceNode = null; // track node that replaces removedOrMovedNode 42 | if (deleteNode != null && deleteNode != nilNode) { 43 | Node removedOrMovedNode = deleteNode; // same as deleteNode if it has only one child, and otherwise it replaces deleteNode 44 | ColorEnum removedOrMovedNodeColor = ((RedBlackNode)removedOrMovedNode).color; 45 | 46 | if (deleteNode.left == nilNode) { 47 | replaceNode = deleteNode.right; 48 | rbTreeTransplant(deleteNode, deleteNode.right); 49 | } else if (deleteNode.right == nilNode) { 50 | replaceNode = deleteNode.left; 51 | rbTreeTransplant(deleteNode, deleteNode.left); 52 | } else { 53 | removedOrMovedNode = getMinimum(deleteNode.right); 54 | removedOrMovedNodeColor = ((RedBlackNode)removedOrMovedNode).color; 55 | replaceNode = removedOrMovedNode.right; 56 | if (removedOrMovedNode.parent == deleteNode) { 57 | replaceNode.parent = removedOrMovedNode; 58 | } else { 59 | rbTreeTransplant(removedOrMovedNode, removedOrMovedNode.right); 60 | removedOrMovedNode.right = deleteNode.right; 61 | removedOrMovedNode.right.parent = removedOrMovedNode; 62 | } 63 | rbTreeTransplant(deleteNode, removedOrMovedNode); 64 | removedOrMovedNode.left = deleteNode.left; 65 | removedOrMovedNode.left.parent = removedOrMovedNode; 66 | ((RedBlackNode)removedOrMovedNode).color = ((RedBlackNode)deleteNode).color; 67 | } 68 | 69 | size--; 70 | if (removedOrMovedNodeColor == ColorEnum.BLACK) { 71 | deleteRBFixup((RedBlackNode)replaceNode); 72 | } 73 | } 74 | 75 | return replaceNode; 76 | } 77 | 78 | /** 79 | * @see trees.AbstractBinarySearchTree#createNode(int, trees.AbstractBinarySearchTree.Node, trees.AbstractBinarySearchTree.Node, trees.AbstractBinarySearchTree.Node) 80 | */ 81 | @Override 82 | protected Node createNode(int value, Node parent, Node left, Node right) { 83 | return new RedBlackNode(value, parent, left, right, ColorEnum.RED); 84 | } 85 | 86 | /** 87 | * {@inheritDoc} 88 | */ 89 | @Override 90 | protected Node getMinimum(Node node) { 91 | while (node.left != nilNode) { 92 | node = node.left; 93 | } 94 | return node; 95 | } 96 | 97 | /** 98 | * {@inheritDoc} 99 | */ 100 | @Override 101 | protected Node getMaximum(Node node) { 102 | while (node.right != nilNode) { 103 | node = node.right; 104 | } 105 | return node; 106 | } 107 | 108 | /** 109 | * {@inheritDoc} 110 | */ 111 | @Override 112 | protected Node rotateLeft(Node node) { 113 | Node temp = node.right; 114 | temp.parent = node.parent; 115 | 116 | node.right = temp.left; 117 | if (node.right != nilNode) { 118 | node.right.parent = node; 119 | } 120 | 121 | temp.left = node; 122 | node.parent = temp; 123 | 124 | // temp took over node's place so now its parent should point to temp 125 | if (temp.parent != nilNode) { 126 | if (node == temp.parent.left) { 127 | temp.parent.left = temp; 128 | } else { 129 | temp.parent.right = temp; 130 | } 131 | } else { 132 | root = temp; 133 | } 134 | 135 | return temp; 136 | } 137 | 138 | /** 139 | * {@inheritDoc} 140 | */ 141 | @Override 142 | protected Node rotateRight(Node node) { 143 | Node temp = node.left; 144 | temp.parent = node.parent; 145 | 146 | node.left = temp.right; 147 | if (node.left != nilNode) { 148 | node.left.parent = node; 149 | } 150 | 151 | temp.right = node; 152 | node.parent = temp; 153 | 154 | // temp took over node's place so now its parent should point to temp 155 | if (temp.parent != nilNode) { 156 | if (node == temp.parent.left) { 157 | temp.parent.left = temp; 158 | } else { 159 | temp.parent.right = temp; 160 | } 161 | } else { 162 | root = temp; 163 | } 164 | 165 | return temp; 166 | } 167 | 168 | 169 | /** 170 | * Similar to original transplant() method in BST but uses nilNode instead of null. 171 | */ 172 | private Node rbTreeTransplant(Node nodeToReplace, Node newNode) { 173 | if (nodeToReplace.parent == nilNode) { 174 | this.root = newNode; 175 | } else if (nodeToReplace == nodeToReplace.parent.left) { 176 | nodeToReplace.parent.left = newNode; 177 | } else { 178 | nodeToReplace.parent.right = newNode; 179 | } 180 | newNode.parent = nodeToReplace.parent; 181 | return newNode; 182 | } 183 | 184 | /** 185 | * Restores Red-Black tree properties after delete if needed. 186 | */ 187 | private void deleteRBFixup(RedBlackNode x) { 188 | while (x != root && isBlack(x)) { 189 | 190 | if (x == x.parent.left) { 191 | RedBlackNode w = (RedBlackNode)x.parent.right; 192 | if (isRed(w)) { // case 1 - sibling is red 193 | w.color = ColorEnum.BLACK; 194 | ((RedBlackNode)x.parent).color = ColorEnum.RED; 195 | rotateLeft(x.parent); 196 | w = (RedBlackNode)x.parent.right; // converted to case 2, 3 or 4 197 | } 198 | // case 2 sibling is black and both of its children are black 199 | if (isBlack(w.left) && isBlack(w.right)) { 200 | w.color = ColorEnum.RED; 201 | x = (RedBlackNode)x.parent; 202 | } else if (w != nilNode) { 203 | if (isBlack(w.right)) { // case 3 sibling is black and its left child is red and right child is black 204 | ((RedBlackNode)w.left).color = ColorEnum.BLACK; 205 | w.color = ColorEnum.RED; 206 | rotateRight(w); 207 | w = (RedBlackNode)x.parent.right; 208 | } 209 | w.color = ((RedBlackNode)x.parent).color; // case 4 sibling is black and right child is red 210 | ((RedBlackNode)x.parent).color = ColorEnum.BLACK; 211 | ((RedBlackNode)w.right).color = ColorEnum.BLACK; 212 | rotateLeft(x.parent); 213 | x = (RedBlackNode)root; 214 | } else { 215 | x.color = ColorEnum.BLACK; 216 | x = (RedBlackNode)x.parent; 217 | } 218 | } else { 219 | RedBlackNode w = (RedBlackNode)x.parent.left; 220 | if (isRed(w)) { // case 1 - sibling is red 221 | w.color = ColorEnum.BLACK; 222 | ((RedBlackNode)x.parent).color = ColorEnum.RED; 223 | rotateRight(x.parent); 224 | w = (RedBlackNode)x.parent.left; // converted to case 2, 3 or 4 225 | } 226 | // case 2 sibling is black and both of its children are black 227 | if (isBlack(w.left) && isBlack(w.right)) { 228 | w.color = ColorEnum.RED; 229 | x = (RedBlackNode)x.parent; 230 | } else if (w != nilNode) { 231 | if (isBlack(w.left)) { // case 3 sibling is black and its right child is red and left child is black 232 | ((RedBlackNode)w.right).color = ColorEnum.BLACK; 233 | w.color = ColorEnum.RED; 234 | rotateLeft(w); 235 | w = (RedBlackNode)x.parent.left; 236 | } 237 | w.color = ((RedBlackNode)x.parent).color; // case 4 sibling is black and left child is red 238 | ((RedBlackNode)x.parent).color = ColorEnum.BLACK; 239 | ((RedBlackNode)w.left).color = ColorEnum.BLACK; 240 | rotateRight(x.parent); 241 | x = (RedBlackNode)root; 242 | } else { 243 | x.color = ColorEnum.BLACK; 244 | x = (RedBlackNode)x.parent; 245 | } 246 | } 247 | 248 | } 249 | } 250 | 251 | private boolean isBlack(Node node) { 252 | return node != null ? ((RedBlackNode)node).color == ColorEnum.BLACK : false; 253 | } 254 | 255 | private boolean isRed(Node node) { 256 | return node != null ? ((RedBlackNode)node).color == ColorEnum.RED : false; 257 | } 258 | 259 | /** 260 | * Restores Red-Black tree properties after insert if needed. Insert can 261 | * break only 2 properties: root is red or if node is red then children must 262 | * be black. 263 | */ 264 | private void insertRBFixup(RedBlackNode currentNode) { 265 | // current node is always RED, so if its parent is red it breaks 266 | // Red-Black property, otherwise no fixup needed and loop can terminate 267 | while (currentNode.parent != root && ((RedBlackNode) currentNode.parent).color == ColorEnum.RED) { 268 | RedBlackNode parent = (RedBlackNode) currentNode.parent; 269 | RedBlackNode grandParent = (RedBlackNode) parent.parent; 270 | if (parent == grandParent.left) { 271 | RedBlackNode uncle = (RedBlackNode) grandParent.right; 272 | // case1 - uncle and parent are both red 273 | // re color both of them to black 274 | if (((RedBlackNode) uncle).color == ColorEnum.RED) { 275 | parent.color = ColorEnum.BLACK; 276 | uncle.color = ColorEnum.BLACK; 277 | grandParent.color = ColorEnum.RED; 278 | // grandparent was recolored to red, so in next iteration we 279 | // check if it does not break Red-Black property 280 | currentNode = grandParent; 281 | } 282 | // case 2/3 uncle is black - then we perform rotations 283 | else { 284 | if (currentNode == parent.right) { // case 2, first rotate left 285 | currentNode = parent; 286 | rotateLeft(currentNode); 287 | } 288 | // do not use parent 289 | parent.color = ColorEnum.BLACK; // case 3 290 | grandParent.color = ColorEnum.RED; 291 | rotateRight(grandParent); 292 | } 293 | } else if (parent == grandParent.right) { 294 | RedBlackNode uncle = (RedBlackNode) grandParent.left; 295 | // case1 - uncle and parent are both red 296 | // re color both of them to black 297 | if (((RedBlackNode) uncle).color == ColorEnum.RED) { 298 | parent.color = ColorEnum.BLACK; 299 | uncle.color = ColorEnum.BLACK; 300 | grandParent.color = ColorEnum.RED; 301 | // grandparent was recolored to red, so in next iteration we 302 | // check if it does not break Red-Black property 303 | currentNode = grandParent; 304 | } 305 | // case 2/3 uncle is black - then we perform rotations 306 | else { 307 | if (currentNode == parent.left) { // case 2, first rotate right 308 | currentNode = parent; 309 | rotateRight(currentNode); 310 | } 311 | // do not use parent 312 | parent.color = ColorEnum.BLACK; // case 3 313 | grandParent.color = ColorEnum.RED; 314 | rotateLeft(grandParent); 315 | } 316 | } 317 | 318 | } 319 | // ensure root is black in case it was colored red in fixup 320 | ((RedBlackNode) root).color = ColorEnum.BLACK; 321 | } 322 | 323 | protected static class RedBlackNode extends Node { 324 | public ColorEnum color; 325 | 326 | public RedBlackNode(Integer value, Node parent, Node left, Node right, ColorEnum color) { 327 | super(value, parent, left, right); 328 | this.color = color; 329 | } 330 | } 331 | 332 | } 333 | -------------------------------------------------------------------------------- /src/class07/Code01_CountofRangeSum.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | import java.util.HashSet; 4 | 5 | public class Code01_CountofRangeSum { 6 | 7 | public static int countRangeSum1(int[] nums, int lower, int upper) { 8 | int n = nums.length; 9 | long[] sums = new long[n + 1]; 10 | for (int i = 0; i < n; ++i) 11 | sums[i + 1] = sums[i] + nums[i]; 12 | return countWhileMergeSort(sums, 0, n + 1, lower, upper); 13 | } 14 | 15 | private static int countWhileMergeSort(long[] sums, int start, int end, int lower, int upper) { 16 | if (end - start <= 1) 17 | return 0; 18 | int mid = (start + end) / 2; 19 | int count = countWhileMergeSort(sums, start, mid, lower, upper) 20 | + countWhileMergeSort(sums, mid, end, lower, upper); 21 | int j = mid, k = mid, t = mid; 22 | long[] cache = new long[end - start]; 23 | for (int i = start, r = 0; i < mid; ++i, ++r) { 24 | while (k < end && sums[k] - sums[i] < lower) 25 | k++; 26 | while (j < end && sums[j] - sums[i] <= upper) 27 | j++; 28 | while (t < end && sums[t] < sums[i]) 29 | cache[r++] = sums[t++]; 30 | cache[r] = sums[i]; 31 | count += j - k; 32 | } 33 | System.arraycopy(cache, 0, sums, start, t - start); 34 | return count; 35 | } 36 | 37 | public static class SBTNode { 38 | public long key; 39 | public SBTNode l; 40 | public SBTNode r; 41 | public long size; // 不同key的size 42 | public long all; // 总的size 43 | 44 | public SBTNode(long k) { 45 | key = k; 46 | size = 1; 47 | all = 1; 48 | } 49 | } 50 | 51 | public static class SizeBalancedTreeSet { 52 | private SBTNode root; 53 | private HashSet set = new HashSet<>(); 54 | 55 | private SBTNode rightRotate(SBTNode cur) { 56 | long same = cur.all - (cur.l != null ? cur.l.all : 0) - (cur.r != null ? cur.r.all : 0); 57 | SBTNode leftNode = cur.l; 58 | cur.l = leftNode.r; 59 | leftNode.r = cur; 60 | leftNode.size = cur.size; 61 | cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; 62 | // all modify 63 | leftNode.all = cur.all; 64 | cur.all = (cur.l != null ? cur.l.all : 0) + (cur.r != null ? cur.r.all : 0) + same; 65 | return leftNode; 66 | } 67 | 68 | private SBTNode leftRotate(SBTNode cur) { 69 | long same = cur.all - (cur.l != null ? cur.l.all : 0) - (cur.r != null ? cur.r.all : 0); 70 | SBTNode rightNode = cur.r; 71 | cur.r = rightNode.l; 72 | rightNode.l = cur; 73 | rightNode.size = cur.size; 74 | cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; 75 | // all modify 76 | rightNode.all = cur.all; 77 | cur.all = (cur.l != null ? cur.l.all : 0) + (cur.r != null ? cur.r.all : 0) + same; 78 | return rightNode; 79 | } 80 | 81 | private SBTNode maintain(SBTNode cur) { 82 | if (cur == null) { 83 | return null; 84 | } 85 | long leftSize = cur.l != null ? cur.l.size : 0; 86 | long leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0; 87 | long leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0; 88 | long rightSize = cur.r != null ? cur.r.size : 0; 89 | long rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0; 90 | long rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0; 91 | if (leftLeftSize > rightSize) { 92 | cur = rightRotate(cur); 93 | cur.r = maintain(cur.r); 94 | cur = maintain(cur); 95 | } else if (leftRightSize > rightSize) { 96 | cur.l = leftRotate(cur.l); 97 | cur = rightRotate(cur); 98 | cur.l = maintain(cur.l); 99 | cur.r = maintain(cur.r); 100 | cur = maintain(cur); 101 | } else if (rightRightSize > leftSize) { 102 | cur = leftRotate(cur); 103 | cur.l = maintain(cur.l); 104 | cur = maintain(cur); 105 | } else if (rightLeftSize > leftSize) { 106 | cur.r = rightRotate(cur.r); 107 | cur = leftRotate(cur); 108 | cur.l = maintain(cur.l); 109 | cur.r = maintain(cur.r); 110 | cur = maintain(cur); 111 | } 112 | return cur; 113 | } 114 | 115 | private SBTNode add(SBTNode cur, long key, boolean contains) { 116 | if (cur == null) { 117 | return new SBTNode(key); 118 | } else { 119 | cur.all++; 120 | if (key == cur.key) { 121 | return cur; 122 | } else { // 还在左滑或者右滑 123 | if (!contains) { 124 | cur.size++; 125 | } 126 | if (key < cur.key) { 127 | cur.l = add(cur.l, key, contains); 128 | } else { 129 | cur.r = add(cur.r, key, contains); 130 | } 131 | return maintain(cur); 132 | } 133 | } 134 | } 135 | 136 | public void add(long sum) { 137 | boolean contains = set.contains(sum); 138 | root = add(root, sum, contains); 139 | set.add(sum); 140 | } 141 | 142 | public long lessKeySize(long key) { 143 | SBTNode cur = root; 144 | long ans = 0; 145 | while (cur != null) { 146 | if (key == cur.key) { 147 | return ans + (cur.l != null ? cur.l.all : 0); 148 | } else if (key < cur.key) { 149 | cur = cur.l; 150 | } else { 151 | ans += cur.all - (cur.r != null ? cur.r.all : 0); 152 | cur = cur.r; 153 | } 154 | } 155 | return ans; 156 | } 157 | 158 | // > 7 8... 159 | // <8 ...<=7 160 | public long moreKeySize(long key) { 161 | return root != null ? (root.all - lessKeySize(key + 1)) : 0; 162 | } 163 | 164 | } 165 | 166 | public static int countRangeSum2(int[] nums, int lower, int upper) { 167 | SizeBalancedTreeSet treeSet = new SizeBalancedTreeSet(); 168 | long sum = 0; 169 | int ans = 0; 170 | treeSet.add(0);// 一个数都没有的时候,就已经有一个前缀和累加和为0, 171 | for (int i = 0; i < nums.length; i++) { 172 | sum += nums[i]; 173 | // sum i结尾的时候[lower, upper] 174 | // 之前所有前缀累加和中,有多少累加和落在[sum - upper, sum - lower] 175 | // 查 ? < sum - lower + 1 a 176 | // 查 ? < sum - upper b 177 | // a - b 178 | 179 | long a = treeSet.lessKeySize(sum - lower + 1); 180 | long b = treeSet.lessKeySize(sum - upper); 181 | ans += a - b; 182 | treeSet.add(sum); 183 | } 184 | return ans; 185 | } 186 | 187 | // for test 188 | public static void printArray(int[] arr) { 189 | for (int i = 0; i < arr.length; i++) { 190 | System.out.print(arr[i] + " "); 191 | } 192 | System.out.println(); 193 | } 194 | 195 | // for test 196 | public static int[] generateArray(int len, int varible) { 197 | int[] arr = new int[len]; 198 | for (int i = 0; i < arr.length; i++) { 199 | arr[i] = (int) (Math.random() * varible); 200 | } 201 | return arr; 202 | } 203 | 204 | public static void main(String[] args) { 205 | int len = 200; 206 | int varible = 50; 207 | for (int i = 0; i < 10000; i++) { 208 | int[] test = generateArray(len, varible); 209 | int lower = (int) (Math.random() * varible) - (int) (Math.random() * varible); 210 | int upper = lower + (int) (Math.random() * varible); 211 | int ans1 = countRangeSum1(test, lower, upper); 212 | int ans2 = countRangeSum2(test, lower, upper); 213 | if (ans1 != ans2) { 214 | printArray(test); 215 | System.out.println(lower); 216 | System.out.println(upper); 217 | System.out.println(ans1); 218 | System.out.println(ans2); 219 | } 220 | } 221 | 222 | } 223 | 224 | } 225 | -------------------------------------------------------------------------------- /src/class07/Code02_SlidingWindowMedian.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | public class Code02_SlidingWindowMedian { 4 | 5 | public static class SBTNode> { 6 | public K key; 7 | public SBTNode l; 8 | public SBTNode r; 9 | public int size; 10 | 11 | public SBTNode(K k) { 12 | key = k; 13 | size = 1; 14 | } 15 | } 16 | 17 | public static class SizeBalancedTreeMap> { 18 | private SBTNode root; 19 | 20 | private SBTNode rightRotate(SBTNode cur) { 21 | SBTNode leftNode = cur.l; 22 | cur.l = leftNode.r; 23 | leftNode.r = cur; 24 | leftNode.size = cur.size; 25 | cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; 26 | return leftNode; 27 | } 28 | 29 | private SBTNode leftRotate(SBTNode cur) { 30 | SBTNode rightNode = cur.r; 31 | cur.r = rightNode.l; 32 | rightNode.l = cur; 33 | rightNode.size = cur.size; 34 | cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1; 35 | return rightNode; 36 | } 37 | 38 | private SBTNode maintain(SBTNode cur) { 39 | if (cur == null) { 40 | return null; 41 | } 42 | int leftSize = cur.l != null ? cur.l.size : 0; 43 | int leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0; 44 | int leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0; 45 | int rightSize = cur.r != null ? cur.r.size : 0; 46 | int rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0; 47 | int rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0; 48 | if (leftLeftSize > rightSize) { 49 | cur = rightRotate(cur); 50 | cur.r = maintain(cur.r); 51 | cur = maintain(cur); 52 | } else if (leftRightSize > rightSize) { 53 | cur.l = leftRotate(cur.l); 54 | cur = rightRotate(cur); 55 | cur.l = maintain(cur.l); 56 | cur.r = maintain(cur.r); 57 | cur = maintain(cur); 58 | } else if (rightRightSize > leftSize) { 59 | cur = leftRotate(cur); 60 | cur.l = maintain(cur.l); 61 | cur = maintain(cur); 62 | } else if (rightLeftSize > leftSize) { 63 | cur.r = rightRotate(cur.r); 64 | cur = leftRotate(cur); 65 | cur.l = maintain(cur.l); 66 | cur.r = maintain(cur.r); 67 | cur = maintain(cur); 68 | } 69 | return cur; 70 | } 71 | 72 | private SBTNode findLastIndex(K key) { 73 | SBTNode pre = root; 74 | SBTNode cur = root; 75 | while (cur != null) { 76 | pre = cur; 77 | if (key.compareTo(cur.key) == 0) { 78 | break; 79 | } else if (key.compareTo(cur.key) < 0) { 80 | cur = cur.l; 81 | } else { 82 | cur = cur.r; 83 | } 84 | } 85 | return pre; 86 | } 87 | 88 | private SBTNode add(SBTNode cur, K key) { 89 | if (cur == null) { 90 | return new SBTNode(key); 91 | } else { 92 | cur.size++; 93 | if (key.compareTo(cur.key) < 0) { 94 | cur.l = add(cur.l, key); 95 | } else { 96 | cur.r = add(cur.r, key); 97 | } 98 | return maintain(cur); 99 | } 100 | } 101 | 102 | private SBTNode delete(SBTNode cur, K key) { 103 | cur.size--; 104 | if (key.compareTo(cur.key) > 0) { 105 | cur.r = delete(cur.r, key); 106 | } else if (key.compareTo(cur.key) < 0) { 107 | cur.l = delete(cur.l, key); 108 | } else { 109 | if (cur.l == null && cur.r == null) { 110 | // free cur memory -> C++ 111 | cur = null; 112 | } else if (cur.l == null && cur.r != null) { 113 | // free cur memory -> C++ 114 | cur = cur.r; 115 | } else if (cur.l != null && cur.r == null) { 116 | // free cur memory -> C++ 117 | cur = cur.l; 118 | } else { 119 | SBTNode pre = null; 120 | SBTNode des = cur.r; 121 | des.size--; 122 | while (des.l != null) { 123 | pre = des; 124 | des = des.l; 125 | des.size--; 126 | } 127 | if (pre != null) { 128 | pre.l = des.r; 129 | des.r = cur.r; 130 | } 131 | des.l = cur.l; 132 | des.size = des.l.size + (des.r == null ? 0 : des.r.size) + 1; 133 | // free cur memory -> C++ 134 | cur = des; 135 | } 136 | } 137 | return cur; 138 | } 139 | 140 | private SBTNode getIndex(SBTNode cur, int kth) { 141 | if (kth == (cur.l != null ? cur.l.size : 0) + 1) { 142 | return cur; 143 | } else if (kth <= (cur.l != null ? cur.l.size : 0)) { 144 | return getIndex(cur.l, kth); 145 | } else { 146 | return getIndex(cur.r, kth - (cur.l != null ? cur.l.size : 0) - 1); 147 | } 148 | } 149 | 150 | public int size() { 151 | return root == null ? 0 : root.size; 152 | } 153 | 154 | public boolean containsKey(K key) { 155 | if (key == null) { 156 | throw new RuntimeException("invalid parameter."); 157 | } 158 | SBTNode lastNode = findLastIndex(key); 159 | return lastNode != null && key.compareTo(lastNode.key) == 0 ? true : false; 160 | } 161 | 162 | public void add(K key) { 163 | if (key == null) { 164 | throw new RuntimeException("invalid parameter."); 165 | } 166 | SBTNode lastNode = findLastIndex(key); 167 | if (lastNode == null || key.compareTo(lastNode.key) != 0) { 168 | root = add(root, key); 169 | } 170 | } 171 | 172 | public void remove(K key) { 173 | if (key == null) { 174 | throw new RuntimeException("invalid parameter."); 175 | } 176 | if (containsKey(key)) { 177 | root = delete(root, key); 178 | } 179 | } 180 | 181 | public K getIndexKey(int index) { 182 | if (index < 0 || index >= this.size()) { 183 | throw new RuntimeException("invalid parameter."); 184 | } 185 | return getIndex(root, index + 1).key; 186 | } 187 | 188 | } 189 | 190 | public static class Node implements Comparable { 191 | public int index; 192 | public int value; 193 | 194 | public Node(int i, int v) { 195 | index = i; 196 | value = v; 197 | } 198 | 199 | @Override 200 | public int compareTo(Node o) { 201 | return value != o.value ? Integer.valueOf(value).compareTo(o.value) 202 | : Integer.valueOf(index).compareTo(o.index); 203 | } 204 | } 205 | 206 | public static double[] medianSlidingWindow(int[] nums, int k) { 207 | SizeBalancedTreeMap map = new SizeBalancedTreeMap<>(); 208 | for (int i = 0; i < k - 1; i++) { 209 | map.add(new Node(i, nums[i])); 210 | } 211 | double[] ans = new double[nums.length - k + 1]; 212 | int index = 0; 213 | for (int i = k - 1; i < nums.length; i++) { 214 | map.add(new Node(i, nums[i])); 215 | if (map.size() % 2 == 0) { 216 | Node upmid = map.getIndexKey(map.size() / 2 - 1); 217 | Node downmid = map.getIndexKey(map.size() / 2); 218 | ans[index++] = ((double) upmid.value + (double) downmid.value) / 2; 219 | } else { 220 | Node mid = map.getIndexKey(map.size() / 2); 221 | ans[index++] = (double) mid.value; 222 | } 223 | map.remove(new Node(i - k + 1, nums[i - k + 1])); 224 | } 225 | return ans; 226 | } 227 | 228 | } 229 | -------------------------------------------------------------------------------- /src/class08/Code01_AC.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | public class Code01_AC { 9 | 10 | // 前缀树的节点 11 | public static class Node { 12 | // 如果一个node,end为空,不是结尾 13 | // 如果end不为空,表示这个点是某个字符串的结尾,end的值就是这个字符串 14 | public String end; 15 | // 只有在上面的end变量不为空的时候,endUse才有意义 16 | // 表示,这个字符串之前有没有加入过答案 17 | public boolean endUse; 18 | public Node fail; 19 | public Node[] nexts; 20 | public Node() { 21 | endUse = false; 22 | end = null; 23 | fail = null; 24 | nexts = new Node[26]; 25 | } 26 | } 27 | 28 | public static class ACAutomation { 29 | private Node root; 30 | 31 | public ACAutomation() { 32 | root = new Node(); 33 | } 34 | 35 | public void insert(String s) { 36 | char[] str = s.toCharArray(); 37 | Node cur = root; 38 | int index = 0; 39 | for (int i = 0; i < str.length; i++) { 40 | index = str[i] - 'a'; 41 | if (cur.nexts[index] == null) { 42 | Node next = new Node(); 43 | cur.nexts[index] = next; 44 | } 45 | cur = cur.nexts[index]; 46 | } 47 | cur.end = s; 48 | } 49 | 50 | public void build() { 51 | Queue queue = new LinkedList<>(); 52 | queue.add(root); 53 | Node cur = null; 54 | Node cfail = null; 55 | while (!queue.isEmpty()) { 56 | // 当前节点弹出, 57 | // 当前节点的所有后代加入到队列里去, 58 | // 当前节点给它的子去设置fail指针 59 | // cur -> 父亲 60 | cur = queue.poll(); 61 | for (int i = 0; i < 26; i++) { // 所有的路 62 | if (cur.nexts[i] != null) { // 找到所有有效的路 63 | // cur.nexts[i] 子 64 | cur.nexts[i].fail = root; // 65 | cfail = cur.fail; 66 | while (cfail != null) { 67 | if (cfail.nexts[i] != null) { 68 | cur.nexts[i].fail = cfail.nexts[i]; 69 | break; 70 | } 71 | cfail = cfail.fail; 72 | } 73 | queue.add(cur.nexts[i]); 74 | } 75 | } 76 | } 77 | } 78 | 79 | public List containWords(String content) { 80 | char[] str = content.toCharArray(); 81 | Node cur = root; 82 | Node follow = null; 83 | int path = 0; 84 | List ans = new ArrayList<>(); 85 | for (int i = 0; i < str.length; i++) { // 依次遍历文章中的字符,i位置 86 | path = str[i] - 'a'; // 路 87 | // 如果当前字符在这条路上没配出来,就随着fail方向走向下条路径 88 | // 如果当前cur节点,没有path的路,就通过fail,跳到别的前缀上去 89 | while (cur.nexts[path] == null && cur != root) { 90 | cur = cur.fail; 91 | } 92 | // 1) 现在来到的路径,是可以继续匹配的 93 | // 2) 现在来到的节点,已经是头了 94 | cur = cur.nexts[path] != null ? cur.nexts[path] : root; 95 | follow = cur; 96 | while (follow != root) { 97 | if(follow.endUse) { 98 | break; 99 | } 100 | // 不同的需求,在这一段之间修改 101 | if (follow.end != null) { 102 | ans.add(follow.end); 103 | follow.endUse = true; 104 | } 105 | // 不同的需求,在这一段之间修改 106 | follow = follow.fail; 107 | } 108 | } 109 | return ans; 110 | } 111 | 112 | } 113 | 114 | public static void main(String[] args) { 115 | ACAutomation ac = new ACAutomation(); 116 | ac.insert("dhe"); 117 | ac.insert("he"); 118 | ac.insert("abcdheks"); 119 | // 设置fail指针 120 | ac.build(); 121 | 122 | List contains = ac.containWords("abcdhekskdjfafhasldkflskdjhwqaeruv"); 123 | for (String word : contains) { 124 | System.out.println(word); 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/class08/Code02_DifferentBTNum.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | public class Code02_DifferentBTNum { 4 | 5 | // k(0) = 1, k(1) = 1 6 | // 7 | // k(n) = k(0) * k(n - 1) + k(1) * k(n - 2) + ... + k(n - 2) * k(1) + k(n - 1) * k(0) 8 | // 或者 9 | // k(n) = c(2n, n) / (n + 1) 10 | // 或者 11 | // k(n) = c(2n, n) - c(2n, n-1) 12 | 13 | public static long num1(int N) { 14 | if (N < 0) { 15 | return 0; 16 | } 17 | if (N < 2) { 18 | return 1; 19 | } 20 | long[] dp = new long[N + 1]; 21 | dp[0] = 1; 22 | dp[1] = 1; 23 | for (int i = 2; i <= N; i++) { 24 | for (int leftSize = 0; leftSize < i; leftSize++) { 25 | dp[i] += dp[leftSize] * dp[i - 1 - leftSize]; 26 | } 27 | } 28 | return dp[N]; 29 | } 30 | 31 | public static long num2(int N) { 32 | if (N < 0) { 33 | return 0; 34 | } 35 | if (N < 2) { 36 | return 1; 37 | } 38 | long a = 1; 39 | long b = 1; 40 | for (int i = 1, j = N + 1; i <= N; i++, j++) { 41 | a *= i; 42 | b *= j; 43 | long gcd = gcd(a, b); 44 | a /= gcd; 45 | b /= gcd; 46 | } 47 | return (b / a) / (N + 1); 48 | } 49 | 50 | public static long gcd(long m, long n) { 51 | return n == 0 ? m : gcd(n, m % n); 52 | } 53 | 54 | public static void main(String[] args) { 55 | System.out.println("test begin"); 56 | for (int i = 0; i < 15; i++) { 57 | long ans1 = num1(i); 58 | long ans2 = num2(i); 59 | if (ans1 != ans2) { 60 | System.out.println("Oops!"); 61 | } 62 | } 63 | System.out.println("test finish"); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/class08/Code03_10Ways.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.LinkedList; 4 | 5 | public class Code03_10Ways { 6 | 7 | public static long ways1(int N) { 8 | int zero = N; 9 | int one = N; 10 | LinkedList path = new LinkedList<>(); 11 | LinkedList> ans = new LinkedList<>(); 12 | process(zero, one, path, ans); 13 | long count = 0; 14 | for (LinkedList cur : ans) { 15 | int status = 0; 16 | for (Integer num : cur) { 17 | if (num == 0) { 18 | status++; 19 | } else { 20 | status--; 21 | } 22 | if (status < 0) { 23 | break; 24 | } 25 | } 26 | if (status == 0) { 27 | count++; 28 | } 29 | } 30 | return count; 31 | } 32 | 33 | public static void process(int zero, int one, LinkedList path, LinkedList> ans) { 34 | if (zero == 0 && one == 0) { 35 | LinkedList cur = new LinkedList<>(); 36 | for (Integer num : path) { 37 | cur.add(num); 38 | } 39 | ans.add(cur); 40 | } else { 41 | if (zero == 0) { 42 | path.addLast(1); 43 | process(zero, one - 1, path, ans); 44 | path.removeLast(); 45 | } else if (one == 0) { 46 | path.addLast(0); 47 | process(zero - 1, one, path, ans); 48 | path.removeLast(); 49 | } else { 50 | path.addLast(1); 51 | process(zero, one - 1, path, ans); 52 | path.removeLast(); 53 | path.addLast(0); 54 | process(zero - 1, one, path, ans); 55 | path.removeLast(); 56 | } 57 | } 58 | } 59 | 60 | public static long ways2(int N) { 61 | if (N < 0) { 62 | return 0; 63 | } 64 | if (N < 2) { 65 | return 1; 66 | } 67 | long a = 1; 68 | long b = 1; 69 | long limit = N << 1; 70 | for (long i = 1; i <= limit; i++) { 71 | if (i <= N) { 72 | a *= i; 73 | } else { 74 | b *= i; 75 | } 76 | } 77 | return (b / a) / (N + 1); 78 | } 79 | 80 | public static void main(String[] args) { 81 | System.out.println("test begin"); 82 | for (int i = 0; i < 10; i++) { 83 | long ans1 = ways1(i); 84 | long ans2 = ways2(i); 85 | if (ans1 != ans2) { 86 | System.out.println("Oops!"); 87 | } 88 | } 89 | System.out.println("test finish"); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/class08/Code04_UniqueBST.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.List; 4 | import java.util.LinkedList; 5 | 6 | public class Code04_UniqueBST { 7 | 8 | public static class Node { 9 | public int value; 10 | public Node left; 11 | public Node right; 12 | 13 | public Node(int data) { 14 | this.value = data; 15 | } 16 | } 17 | 18 | public static List generateTrees(int n) { 19 | return generate(1, n); 20 | } 21 | 22 | public static List generate(int start, int end) { 23 | List res = new LinkedList(); 24 | if (start > end) { 25 | res.add(null); 26 | } 27 | Node head = null; 28 | for (int i = start; i < end + 1; i++) { 29 | head = new Node(i); 30 | List lSubs = generate(start, i - 1); 31 | List rSubs = generate(i + 1, end); 32 | for (Node l : lSubs) { 33 | for (Node r : rSubs) { 34 | head.left = l; 35 | head.right = r; 36 | res.add(cloneTree(head)); 37 | } 38 | } 39 | } 40 | return res; 41 | } 42 | 43 | public static Node cloneTree(Node head) { 44 | if (head == null) { 45 | return null; 46 | } 47 | Node res = new Node(head.value); 48 | res.left = cloneTree(head.left); 49 | res.right = cloneTree(head.right); 50 | return res; 51 | } 52 | 53 | // for test -- print tree 54 | public static void printTree(Node head) { 55 | System.out.println("Binary Tree:"); 56 | printInOrder(head, 0, "H", 17); 57 | System.out.println(); 58 | } 59 | 60 | public static void printInOrder(Node head, int height, String to, int len) { 61 | if (head == null) { 62 | return; 63 | } 64 | printInOrder(head.right, height + 1, "v", len); 65 | String val = to + head.value + to; 66 | int lenM = val.length(); 67 | int lenL = (len - lenM) / 2; 68 | int lenR = len - lenM - lenL; 69 | val = getSpace(lenL) + val + getSpace(lenR); 70 | System.out.println(getSpace(height * len) + val); 71 | printInOrder(head.left, height + 1, "^", len); 72 | } 73 | 74 | public static String getSpace(int num) { 75 | String space = " "; 76 | StringBuffer buf = new StringBuffer(""); 77 | for (int i = 0; i < num; i++) { 78 | buf.append(space); 79 | } 80 | return buf.toString(); 81 | } 82 | 83 | public static void main(String[] args) { 84 | int n = 4; 85 | List res = generateTrees(n); 86 | for (Node node : res) { 87 | printTree(node); 88 | } 89 | } 90 | 91 | } 92 | --------------------------------------------------------------------------------