diff --git a/pom.xml b/pom.xml
index b0cf76c..bfef018 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,9 +20,9 @@
4.1.32.Final
- org.junit.jupiter
- junit-jupiter-engine
- 5.6.2
+ junit
+ junit
+ 4.13.2
test
diff --git "a/src/main/java/algorithm/array/\344\272\214\345\210\206\346\237\245\346\211\276.java" "b/src/main/java/algorithm/array/\344\272\214\345\210\206\346\237\245\346\211\276.java"
new file mode 100644
index 0000000..2de7f51
--- /dev/null
+++ "b/src/main/java/algorithm/array/\344\272\214\345\210\206\346\237\245\346\211\276.java"
@@ -0,0 +1,35 @@
+package algorithm.array;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/21
+ */
+public class 二分查找 {
+
+ public static void main(String[] args) {
+ int[] array = new int[] {1, 2, 3, 4, 5, 6};
+
+ System.out.println(binarySearch(array, 1));
+ }
+
+ public static int binarySearch(int[] array, int target) {
+ if (array == null || array.length == 0) {
+ return -1;
+ }
+
+ int left = 0;
+ int right = array.length - 1;
+ while (left <= right) {
+ int mid = (left + right) / 2;
+ if (array[mid] == target) {
+ return mid;
+ } else if (array[mid] < target) {
+ left = mid + 1;
+ } else {
+ right = mid - 1;
+ }
+ }
+
+ return -1;
+ }
+}
diff --git "a/src/main/java/algorithm/array/\344\272\214\345\210\206\346\237\245\346\211\276\345\267\246\350\276\271\347\225\214.java" "b/src/main/java/algorithm/array/\344\272\214\345\210\206\346\237\245\346\211\276\345\267\246\350\276\271\347\225\214.java"
new file mode 100644
index 0000000..f820f9d
--- /dev/null
+++ "b/src/main/java/algorithm/array/\344\272\214\345\210\206\346\237\245\346\211\276\345\267\246\350\276\271\347\225\214.java"
@@ -0,0 +1,34 @@
+package algorithm.array;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/23
+ */
+public class 二分查找左边界 {
+
+ public static int leftBoundary(int[] array, int target) {
+ if (array == null || array.length == 0) {
+ return -1;
+ }
+
+ int left = 0;
+ int right = array.length - 1;
+ while (left <= right) {
+ int mid = (left + right) / 2;
+ if (target < array[mid]) {
+ right = mid - 1;
+ } else if (target > array[mid]) {
+ left = mid + 1;
+ } else {
+ right = mid - 1;
+ }
+ }
+
+ // 检查target比数组所有元素都大的越界情况以及非越界情况但找不到target的情况
+ if (left >= array.length || array[left] != target) {
+ return -1;
+ }
+
+ return left;
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/Morris\351\201\215\345\216\206.java" "b/src/main/java/algorithm/binary_tree/Morris\351\201\215\345\216\206.java"
index ff791fd..e83beca 100644
--- "a/src/main/java/algorithm/binary_tree/Morris\351\201\215\345\216\206.java"
+++ "b/src/main/java/algorithm/binary_tree/Morris\351\201\215\345\216\206.java"
@@ -1,5 +1,6 @@
package algorithm.binary_tree;
+import algorithm.data_structure.BinarySearchTree;
import algorithm.data_structure.BinaryTree;
import algorithm.utils.TreeNode;
import com.google.common.collect.Lists;
@@ -11,9 +12,11 @@
public class Morris遍历 {
public static void main(String[] args) {
- TreeNode root = BinaryTree.create(Lists.newArrayList(1, 2, 3, 4, 5, 6, 7));
+ TreeNode head = BinarySearchTree.create(Lists.newArrayList(1, 2, 3, 4, 5, 6, 7));
- morrisTraverse(root);
+ morrisTraverse(head);
+ morrisTraverseToPreOrder(head);
+ morrisTraverseToInOrder(head);
}
public static void morrisTraverse(TreeNode head) {
@@ -25,16 +28,18 @@ public static void morrisTraverse(TreeNode head) {
TreeNode cur = head;
while (cur != null) {
mostRight = cur.left;
- while (mostRight.right != null && mostRight.right != cur) {
- mostRight = mostRight.right;
- }
+ if (mostRight != null) {
+ while (mostRight.right != null && mostRight.right != cur) {
+ mostRight = mostRight.right;
+ }
- if (mostRight.right == null) {
- mostRight.right = cur;
- cur = cur.left;
- continue;
- } else {
- mostRight.right = null;
+ if (mostRight.right == null) {
+ mostRight.right = cur;
+ cur = cur.left;
+ continue;
+ } else {
+ mostRight.right = null;
+ }
}
cur = cur.right;
diff --git "a/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\346\214\211Zigzag\346\211\223\345\215\260.java" "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\346\214\211Zigzag\346\211\223\345\215\260.java"
new file mode 100644
index 0000000..6cdb7e5
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\346\214\211Zigzag\346\211\223\345\215\260.java"
@@ -0,0 +1,77 @@
+package algorithm.binary_tree;
+
+import algorithm.data_structure.BinaryTree;
+import algorithm.utils.TreeNode;
+import com.google.common.collect.Lists;
+import java.util.Deque;
+import java.util.LinkedList;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/24
+ */
+public class 二叉树按Zigzag打印 {
+
+ public static void main(String[] args) {
+ TreeNode head = BinaryTree.create(Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+ printByZigzag1(head);
+ }
+
+ public static void printByZigzag1(TreeNode head) {
+ if (head == null) {
+ return;
+ }
+
+ Deque deque = new LinkedList<>();
+ deque.offerFirst(head);
+
+ int level = 0;
+ boolean positive = true;
+
+ printLevel(level++, positive);
+
+ TreeNode last = head;
+ TreeNode nLast = null;
+ while (!deque.isEmpty()) {
+ if (positive) {
+ head = deque.pollFirst();
+ if (head.left != null) {
+ nLast = nLast == null ? head.left : nLast;
+ deque.offerLast(head.left);
+ }
+
+ if (head.right != null) {
+ nLast = nLast == null ? head.right : nLast;
+ deque.offerLast(head.right);
+ }
+ } else {
+ head = deque.pollLast();
+ if (head.right != null) {
+ nLast = nLast == null ? head.right : nLast;
+ deque.offerFirst(head.right);
+ }
+
+ if (head.left != null) {
+ nLast = nLast == null ? head.left : nLast;
+ deque.offerFirst(head.left);
+ }
+ }
+
+ System.out.print(head.value + " ");
+ if (last == head && !deque.isEmpty()) {
+ last = nLast;
+ nLast = null;
+ positive = !positive;
+
+ System.out.println();
+ printLevel(level++, positive);
+ }
+ }
+ }
+
+ public static void printLevel(int level, boolean positive) {
+ System.out.print("Level " + level + " from ");
+ System.out.print(positive ? "left to right:" : "right to left");
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226.java" "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226.java"
new file mode 100644
index 0000000..41e31d5
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\347\232\204\345\272\217\345\210\227\345\214\226\345\222\214\345\217\215\345\272\217\345\210\227\345\214\226.java"
@@ -0,0 +1,161 @@
+package algorithm.binary_tree;
+
+import algorithm.data_structure.BinaryTree;
+import algorithm.utils.TreeNode;
+import com.google.common.collect.Lists;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Stack;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/27
+ */
+public class 二叉树的序列化和反序列化 {
+
+ private static final String EMPTY_VALUE = "#";
+
+ public static void main(String[] args) {
+ TreeNode head = BinaryTree.create(Lists.newArrayList(1, 2, 3, 4, 5, 6));
+
+ System.out.println(preSerialize(head));
+ System.out.println(preSerialize1(head));
+ }
+
+
+ public static String preSerialize(TreeNode head) {
+ // 先序遍历序列化
+ if (head == null) {
+ return "";
+ }
+
+ Stack stack = new Stack<>();
+ stack.push(head);
+
+ StringBuilder builder = new StringBuilder();
+ while (!stack.isEmpty()) {
+ TreeNode cur = stack.pop();
+
+ if (cur == null) {
+ builder.append("#!");
+ } else {
+ builder.append(cur.value)
+ .append("!");
+ }
+
+ if (cur != null) {
+ stack.push(cur.right);
+ stack.push(cur.left);
+ }
+ }
+
+ return builder.toString();
+ }
+
+ public static String preSerialize1(TreeNode head) {
+ // 先序遍历序列化
+ if (head == null) {
+ return "#!";
+ }
+
+ String result = head.value + "!";
+ result += preSerialize1(head.left);
+ result += preSerialize1(head.right);
+
+ return result;
+ }
+
+ public static TreeNode preDeserialize(String str) {
+ if (str == null || str.length() == 0) {
+ return null;
+ }
+
+ String[] segments = str.split("!");
+ Queue queue = new LinkedList<>();
+ for (String segment : segments) {
+ queue.offer(segment);
+ }
+
+ return preDeserializeRecursive(queue);
+ }
+
+ private static TreeNode preDeserializeRecursive(Queue queue) {
+ String value = queue.poll();
+ if (EMPTY_VALUE.equals(value)) {
+ return null;
+ }
+
+ TreeNode head = new TreeNode(Integer.parseInt(value));
+ head.left = preDeserializeRecursive(queue);
+ head.right = preDeserializeRecursive(queue);
+
+ return head;
+ }
+
+ public static String serializeByLevel(TreeNode head) {
+ if (head == null) {
+ return EMPTY_VALUE;
+ }
+
+ String res = head.value + "!";
+
+ Queue queue = new LinkedList<>();
+ queue.offer(head);
+
+ while (!queue.isEmpty()) {
+ head = queue.poll();
+ if (head.left != null) {
+ res += head.left.value + "!";
+ queue.offer(head.left);
+ } else {
+ res += EMPTY_VALUE;
+ }
+
+ if (head.right != null) {
+ res += head.right.value + "!";
+ queue.offer(head.right);
+ } else {
+ res += EMPTY_VALUE;
+ }
+ }
+
+ return res;
+ }
+
+ public static TreeNode deserializeByLevel(String str) {
+ String[] segments = str.split("!");
+
+ int index = 0;
+
+ TreeNode head = generateNode(segments[index++]);
+
+ Queue queue = new LinkedList<>();
+ if (head != null) {
+ queue.offer(head);
+ }
+
+ while (!queue.isEmpty()) {
+ TreeNode cur = queue.poll();
+ cur.left = generateNode(segments[index++]);
+ cur.right = generateNode(segments[index++]);
+
+ if (cur.left != null) {
+ queue.offer(cur.left);
+ }
+
+ if (cur.right != null) {
+ queue.offer(cur.right);
+ }
+ }
+
+ return head;
+ }
+
+ private static TreeNode generateNode(String segment) {
+ if (segment.equals("#")) {
+ return null;
+ }
+
+ return new TreeNode(Integer.parseInt(segment));
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\347\232\204\346\214\211\345\261\202\346\211\223\345\215\260.java" "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\347\232\204\346\214\211\345\261\202\346\211\223\345\215\260.java"
new file mode 100644
index 0000000..43fe260
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\347\232\204\346\214\211\345\261\202\346\211\223\345\215\260.java"
@@ -0,0 +1,58 @@
+package algorithm.binary_tree;
+
+import algorithm.data_structure.BinaryTree;
+import algorithm.utils.TreeNode;
+import com.google.common.collect.Lists;
+import java.util.Deque;
+import java.util.LinkedList;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/24
+ */
+public class 二叉树的按层打印 {
+
+ public static void main(String[] args) {
+ TreeNode head = BinaryTree.create(Lists.newArrayList(1, 2, 3, 4, 5, 6, 7));
+
+ printByLevel(head);
+ }
+
+ public static void printByLevel(TreeNode head) {
+ if (head == null) {
+ return;
+ }
+
+ Deque queue = new LinkedList<>();
+ queue.offer(head);
+
+ int level = 1;
+
+ System.out.print(String.format("Level %d:", level++));
+
+ TreeNode last = head;
+ TreeNode nLast = null;
+ while (!queue.isEmpty()) {
+ TreeNode cur = queue.poll();
+
+ System.out.print(cur.value);
+
+ if (cur.left != null) {
+ nLast = cur.left;
+ queue.offer(cur.left);
+ }
+
+ if (cur.right != null) {
+ nLast = cur.right;
+ queue.offer(cur.right);
+ }
+
+ // 最后一行就不打印了
+ if (last == cur && !queue.isEmpty()) {
+ last = nLast;
+
+ System.out.print(String.format("\nLevel %d:", level++));
+ }
+ }
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\350\212\202\347\202\271\351\227\264\347\232\204\346\234\200\345\244\247\350\267\235\347\246\273\351\227\256\351\242\230.java" "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\350\212\202\347\202\271\351\227\264\347\232\204\346\234\200\345\244\247\350\267\235\347\246\273\351\227\256\351\242\230.java"
new file mode 100644
index 0000000..b26176a
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\344\272\214\345\217\211\346\240\221\350\212\202\347\202\271\351\227\264\347\232\204\346\234\200\345\244\247\350\267\235\347\246\273\351\227\256\351\242\230.java"
@@ -0,0 +1,43 @@
+package algorithm.binary_tree;
+
+import algorithm.utils.TreeNode;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/18
+ */
+public class 二叉树节点间的最大距离问题 {
+
+ public static void main(String[] args) {
+
+ }
+
+ public int maxDistance(TreeNode head) {
+ return maxDistanceRecursive(head).maxDistance;
+ }
+
+ public ReturnType maxDistanceRecursive(TreeNode head) {
+ if (head == null) {
+ return new ReturnType(0, 0);
+ }
+
+ ReturnType left = maxDistanceRecursive(head.left);
+ ReturnType right = maxDistanceRecursive(head.right);
+
+ int height = Math.max(left.height, right.height) + 1;
+ int maxDistance = Math.max(left.height + right.height + 1, Math.max(left.maxDistance, right.maxDistance));
+
+ return new ReturnType(maxDistance, height);
+ }
+
+ private static class ReturnType {
+ private final int maxDistance;
+
+ private final int height;
+
+ public ReturnType(int maxDistance, int height) {
+ this.maxDistance = maxDistance;
+ this.height = height;
+ }
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255t1\346\240\221\344\270\255\346\230\257\345\220\246\346\234\211\344\270\216t2\346\240\221\346\213\223\346\211\221\347\273\223\346\236\204\345\256\214\345\205\250\347\233\270\345\220\214\347\232\204\345\255\220\346\240\221.java" "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255t1\346\240\221\344\270\255\346\230\257\345\220\246\346\234\211\344\270\216t2\346\240\221\346\213\223\346\211\221\347\273\223\346\236\204\345\256\214\345\205\250\347\233\270\345\220\214\347\232\204\345\255\220\346\240\221.java"
new file mode 100644
index 0000000..135629e
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255t1\346\240\221\344\270\255\346\230\257\345\220\246\346\234\211\344\270\216t2\346\240\221\346\213\223\346\211\221\347\273\223\346\236\204\345\256\214\345\205\250\347\233\270\345\220\214\347\232\204\345\255\220\346\240\221.java"
@@ -0,0 +1,80 @@
+package algorithm.binary_tree;
+
+import algorithm.utils.TreeNode;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/3
+ */
+public class 判断t1树中是否有与t2树拓扑结构完全相同的子树 {
+
+ public static boolean contains(TreeNode t1, TreeNode t2) {
+ String str1 = serializeByPre(t1);
+ String str2 = serializeByPre(t2);
+
+ return kmp(str1, str2) != -1;
+ }
+
+ private static int kmp(String str1, String str2) {
+ if (str1 == null || str2 == null || str2.length() < 1 || str1.length() < str2.length()) {
+ return -1;
+ }
+
+ int s1 = 0;
+ int s2 = 0;
+ char[] ss = str1.toCharArray();
+ char[] tt = str2.toCharArray();
+ int[] next = getNextArray(ss);
+ while (s1 < ss.length && s2 < tt.length) {
+ if (ss[s1] == tt[s2]) {
+ s1++;
+ s2++;
+ } else if (next[s2] == -1) {
+ // 第一位就不想等的情况
+ s1++;
+ } else {
+ s2 = next[s2];
+ }
+ }
+
+ return s2 == tt.length ? s2 - s1 : -1;
+ }
+
+ private static int[] getNextArray(char[] ss) {
+ if (ss.length == 1) {
+ return new int[]{-1};
+ }
+
+ int[] res = new int[ss.length];
+ res[0] = -1;
+ res[1] = 0;
+
+ int cnt = 0;
+ int pos = 2;
+ while (pos < ss.length) {
+ if (ss[cnt] == ss[pos]) {
+ res[pos++] = ++cnt;
+ // TODO
+ } else if (cnt > 0) {
+ // 不想等但是有共同前缀,退到相同前缀部分的下一位继续比较,如果一直都不匹配,最终会退到cnt=0
+ cnt = res[cnt];
+ } else {
+ res[pos++] = 0;
+ }
+ }
+
+ return new int[0];
+ }
+
+ private static String serializeByPre(TreeNode head) {
+ if (head == null) {
+ return "#!";
+ }
+
+ String res = head.value + "!";
+ res += serializeByPre(head.left);
+ res += serializeByPre(head.right);
+
+ return res;
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255t1\346\240\221\346\230\257\345\220\246\345\214\205\345\220\253t2\346\240\221\347\232\204\345\205\250\351\203\250\346\213\223\346\211\221\347\273\223\346\236\204.java" "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255t1\346\240\221\346\230\257\345\220\246\345\214\205\345\220\253t2\346\240\221\347\232\204\345\205\250\351\203\250\346\213\223\346\211\221\347\273\223\346\236\204.java"
new file mode 100644
index 0000000..2b4fffa
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255t1\346\240\221\346\230\257\345\220\246\345\214\205\345\220\253t2\346\240\221\347\232\204\345\205\250\351\203\250\346\213\223\346\211\221\347\273\223\346\236\204.java"
@@ -0,0 +1,44 @@
+package algorithm.binary_tree;
+
+import algorithm.data_structure.BinaryTree;
+import algorithm.utils.TreeNode;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/26
+ */
+public class 判断t1树是否包含t2树的全部拓扑结构 {
+
+ public static void main(String[] args) {
+ final TreeNode t1 = BinaryTree.create(1, 2, 3, 4, 5, 6, 7, 8);
+ final TreeNode t2 = BinaryTree.create(3, 4, 5, 8);
+ final TreeNode t3 = BinaryTree.create(2, 4, 5, 8);
+
+ System.out.println(contains(t1, t2));
+ System.out.println(contains(t1, t3));
+ }
+
+ public static boolean contains(TreeNode t1, TreeNode t2) {
+ if (t2 == null) {
+ return true;
+ }
+
+ if (t1 == null) {
+ return false;
+ }
+
+ return containsRecursive(t1, t2) || contains(t1.left, t2) || contains(t1.right, t2);
+ }
+
+ private static boolean containsRecursive(TreeNode t1, TreeNode t2) {
+ if (t2 == null) {
+ return true;
+ }
+
+ if (t1 == null || t1.value != t2.value) {
+ return false;
+ }
+
+ return containsRecursive(t1.left, t2.left) && containsRecursive(t1.right, t2.right);
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255\344\270\200\351\242\227\344\272\214\345\217\211\346\240\221\346\230\257\345\220\246\344\270\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\345\222\214\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.java" "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255\344\270\200\351\242\227\344\272\214\345\217\211\346\240\221\346\230\257\345\220\246\344\270\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\345\222\214\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.java"
new file mode 100644
index 0000000..978fb35
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255\344\270\200\351\242\227\344\272\214\345\217\211\346\240\221\346\230\257\345\220\246\344\270\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\345\222\214\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.java"
@@ -0,0 +1,91 @@
+package algorithm.binary_tree;
+
+import algorithm.data_structure.BinarySearchTree;
+import algorithm.data_structure.BinaryTree;
+import algorithm.utils.TreeNode;
+import com.google.common.collect.Lists;
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/5
+ */
+public class 判断一颗二叉树是否为搜索二叉树和完全二叉树 {
+
+ public static void main(String[] args) {
+ TreeNode head = BinarySearchTree.create(Lists.newArrayList(1, 2, 3, 4, 5, 6, 7));
+
+ System.out.println(isBST(head));
+
+ head = BinaryTree.create(Lists.newArrayList(1, 3, 2, 4, 0, 6, 7));
+
+ System.out.println(isBST(head));
+ }
+
+ public static boolean isBST(TreeNode head) {
+ if (head == null) {
+ return true;
+ }
+
+ boolean result = true;
+ TreeNode pre = null;
+ TreeNode mostRight = null;
+ while (head != null) {
+ mostRight = head.left;
+ if (mostRight != null) {
+ while (mostRight.right != null && mostRight.right != head) {
+ mostRight = mostRight.right;
+ }
+
+ if (mostRight.right == null) {
+ mostRight.right = head;
+ head = head.left;
+ continue;
+ } else {
+ mostRight.right = null;
+ }
+ }
+
+ if (pre != null && pre.value > head.value) {
+ result = false;
+ }
+
+ pre = head;
+ head = head.right;
+ }
+
+ return result;
+ }
+
+ public static boolean isCST(TreeNode head) {
+ if (head == null) {
+ return true;
+ }
+
+ boolean leaf = false;
+ Queue queue = new LinkedList<>();
+ queue.offer(head);
+ while (!queue.isEmpty()) {
+ head = queue.poll();
+
+ TreeNode left = head.left;
+ TreeNode right = head.right;
+ if ((leaf && (left != null || right != null)) || (left == null && right != null)) {
+ return false;
+ }
+
+ if (left != null) {
+ queue.offer(left);
+ }
+
+ if (right != null) {
+ queue.offer(right);
+ } else {
+ leaf = true;
+ }
+ }
+
+ return true;
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255\344\272\214\345\217\211\346\240\221\346\230\257\345\220\246\344\270\272\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.java" "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255\344\272\214\345\217\211\346\240\221\346\230\257\345\220\246\344\270\272\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.java"
new file mode 100644
index 0000000..ccd0852
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\345\210\244\346\226\255\344\272\214\345\217\211\346\240\221\346\230\257\345\220\246\344\270\272\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.java"
@@ -0,0 +1,41 @@
+package algorithm.binary_tree;
+
+import algorithm.utils.TreeNode;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/4
+ */
+public class 判断二叉树是否为平衡二叉树 {
+
+ public static boolean isBalanced(TreeNode head) {
+ return process(head).isBalanced;
+ }
+
+ private static ReturnType process(TreeNode head) {
+ if (head == null) {
+ return new ReturnType(true, 0);
+ }
+
+ ReturnType left = process(head.left);
+ ReturnType right = process(head.right);
+
+ int height = Math.max(left.height, right.height) + 1;
+
+ boolean balanced = left.isBalanced && right.isBalanced && Math.abs(left.height - right.height) < 2;
+
+ return new ReturnType(balanced, height);
+ }
+
+
+ private static class ReturnType {
+ public boolean isBalanced;
+
+ public int height;
+
+ public ReturnType(boolean isBalanced, int height) {
+ this.isBalanced = isBalanced;
+ this.height = height;
+ }
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\345\234\250\344\272\214\345\217\211\346\240\221\344\270\255\346\211\276\345\210\260\344\270\244\344\270\252\350\212\202\347\202\271\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.java" "b/src/main/java/algorithm/binary_tree/\345\234\250\344\272\214\345\217\211\346\240\221\344\270\255\346\211\276\345\210\260\344\270\244\344\270\252\350\212\202\347\202\271\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.java"
new file mode 100644
index 0000000..b33f8a8
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\345\234\250\344\272\214\345\217\211\346\240\221\344\270\255\346\211\276\345\210\260\344\270\244\344\270\252\350\212\202\347\202\271\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.java"
@@ -0,0 +1,91 @@
+package algorithm.binary_tree;
+
+import algorithm.data_structure.BinaryTree;
+import algorithm.utils.TreeNode;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.springframework.util.Assert;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/9
+ */
+public class 在二叉树中找到两个节点的最近公共祖先 {
+
+ public static void main(String[] args) {
+ TreeNode head = BinaryTree.create(1, 2, 3, 4, 5, 6, 7);
+
+ TreeNode parent = findParent1(head, new TreeNode(2), new TreeNode(4));
+
+ Assert.isTrue(parent.equals(new TreeNode(2)));
+
+ parent = findParent1(head, new TreeNode(2), new TreeNode(7));
+
+ Assert.isTrue(parent.equals(new TreeNode(1)));
+ }
+
+ public static TreeNode findParent(TreeNode head, TreeNode o1, TreeNode o2) {
+ if (head == null || head == o1 || head == o2) {
+ return head;
+ }
+
+ TreeNode left = findParent(head.left, o1, o2);
+ TreeNode right = findParent(head.right, o1, o2);
+ if (left != null && right != null) {
+ return head;
+ }
+
+ return left != null ? left : right;
+ }
+
+ public static TreeNode findParent1(TreeNode head, TreeNode o1, TreeNode o2) {
+ ParentFinder finder = new ParentFinder(head);
+ return finder.find(o1, o2);
+ }
+
+ private static class ParentFinder {
+ private Map cache;
+
+ public ParentFinder(TreeNode head) {
+ this.cache = new HashMap<>();
+ if (head != null) {
+ this.cache.put(head, null);
+ }
+
+ setMap(head);
+ }
+
+ private void setMap(TreeNode head) {
+ if (head == null) {
+ return;
+ }
+
+ if (head.left != null) {
+ this.cache.put(head.left, head);
+ }
+
+ if (head.right != null) {
+ this.cache.put(head.right, head);
+ }
+
+ setMap(head.left);
+ setMap(head.right);
+ }
+
+ public TreeNode find(TreeNode o1, TreeNode o2) {
+ Set path = new HashSet<>();
+ while (this.cache.containsKey(o1)) {
+ path.add(o1);
+ o1 = this.cache.get(o1);
+ }
+
+ while (!path.contains(o2)) {
+ o2 = this.cache.get(o2);
+ }
+
+ return o2;
+ }
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\346\211\276\345\210\260\344\272\214\345\217\211\346\240\221\344\270\255\347\254\246\345\220\210\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\346\235\241\344\273\266\347\232\204\346\234\200\345\244\247\346\213\223\346\211\221\347\273\223\346\236\204.java" "b/src/main/java/algorithm/binary_tree/\346\211\276\345\210\260\344\272\214\345\217\211\346\240\221\344\270\255\347\254\246\345\220\210\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\346\235\241\344\273\266\347\232\204\346\234\200\345\244\247\346\213\223\346\211\221\347\273\223\346\236\204.java"
new file mode 100644
index 0000000..fe33096
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\346\211\276\345\210\260\344\272\214\345\217\211\346\240\221\344\270\255\347\254\246\345\220\210\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\346\235\241\344\273\266\347\232\204\346\234\200\345\244\247\346\213\223\346\211\221\347\273\223\346\236\204.java"
@@ -0,0 +1,113 @@
+package algorithm.binary_tree;
+
+import algorithm.utils.TreeNode;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/19
+ */
+public class 找到二叉树中符合搜索二叉树条件的最大拓扑结构 {
+
+ public static void main(String[] args) {
+ String[] strs = StringUtils.split("[UG1, UG2, UG3]", "[] ,");
+
+ System.out.println(Arrays.toString(strs));
+ }
+
+ public int bstTopoSize1(TreeNode head) {
+ if (head == null) {
+ return 0;
+ }
+
+ int maxTopoSize = maxTopo(head, head);
+ maxTopoSize = Math.max(bstTopoSize1(head.left), maxTopoSize);
+ maxTopoSize = Math.max(bstTopoSize1(head.right), maxTopoSize);
+
+ return maxTopoSize;
+ }
+
+ private int maxTopo(TreeNode h, TreeNode n) {
+ if (h != null && n != null && isBSTNode(h, n, n.value)) {
+ return maxTopo(h, n.left) + maxTopo(h, n.right) + 1;
+ }
+
+ return 0;
+ }
+
+ private boolean isBSTNode(TreeNode h, TreeNode n, int value) {
+ if (h == null) {
+ return false;
+ }
+
+ if (h == n) {
+ return true;
+ }
+
+ return isBSTNode(value > h.value ? h.right : h.left, n, value);
+ }
+
+ public int bstTopoSize2(TreeNode head) {
+ Map cache = new HashMap<>();
+
+ return postOrder(head, cache);
+ }
+
+ private int postOrder(TreeNode head, Map cache) {
+ if (head == null) {
+ return 0;
+ }
+
+ int left = postOrder(head.left, cache);
+ int right = postOrder(head.right, cache);
+
+ modifyMap(head.left, head.value, cache, true);
+ modifyMap(head.right, head.value, cache, false);
+
+ Record lr = cache.get(head.left);
+ Record rr = cache.get(head.right);
+
+ int lbst = lr == null ? 0 : lr.leftCnt + lr.rightCnt + 1;
+ int rbst = rr == null ? 0 : rr.leftCnt + rr.rightCnt + 1;
+ cache.put(head, new Record(lbst, rbst));
+
+ return Math.max(lbst + rbst + 1, Math.max(left, right));
+ }
+
+ private int modifyMap(TreeNode n, int v, Map cache, boolean s) {
+ if (n == null || (!cache.containsKey(n))) {
+ return 0;
+ }
+
+ Record r = cache.get(n);
+ if ((s && n.value > v) || (!(s) && n.value < v)) {
+ cache.remove(n);
+ return r.leftCnt + r.rightCnt + 1;
+ } else {
+ int minus = modifyMap(s ? n.right : n.left, v, cache, s);
+ if (s) {
+ r.rightCnt = r.rightCnt - minus;
+ } else {
+ r.leftCnt = r.leftCnt - minus;
+ }
+
+ cache.put(n, r);
+
+ return minus;
+ }
+ }
+
+ private static class Record {
+ public int leftCnt;
+
+ public int rightCnt;
+
+ private Record(int leftCnt, int rightCnt) {
+ this.leftCnt = leftCnt;
+ this.rightCnt = rightCnt;
+ }
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\346\240\271\346\215\256\345\220\216\345\272\217\346\225\260\347\273\204\351\207\215\345\273\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.java" "b/src/main/java/algorithm/binary_tree/\346\240\271\346\215\256\345\220\216\345\272\217\346\225\260\347\273\204\351\207\215\345\273\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.java"
new file mode 100644
index 0000000..83cfd43
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\346\240\271\346\215\256\345\220\216\345\272\217\346\225\260\347\273\204\351\207\215\345\273\272\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.java"
@@ -0,0 +1,59 @@
+package algorithm.binary_tree;
+
+import algorithm.utils.TreeNode;
+import org.springframework.util.Assert;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/4
+ */
+public class 根据后序数组重建搜索二叉树 {
+
+ public static void main(String[] args) {
+ int[] post = new int[]{1, 3, 2, 5, 7, 6, 4};
+
+ TreeNode head = restoreByPost(post);
+
+ Assert.isTrue(head.value == 4);
+ Assert.isTrue(head.left.value == 2);
+ Assert.isTrue(head.right.value == 6);
+
+ head = restoreByPost(new int[0]);
+
+ Assert.isTrue(head == null);
+ }
+
+ public static TreeNode restoreByPost(int[] array) {
+ if (array == null || array.length == 0) {
+ return null;
+ }
+
+ return restoreByPostRecursively(array, 0, array.length - 1);
+ }
+
+ private static TreeNode restoreByPostRecursively(int[] array, int start, int end) {
+ if (start > end) {
+ return null;
+ }
+
+ int less = start;
+ int more = end;
+ for (int i = start; i < end; i++) {
+ if (array[end] > array[i]) {
+ less = i;
+ } else {
+ more = more == end ? end - 1 : i;
+ }
+ }
+
+ TreeNode head = new TreeNode(array[end]);
+ if (more == less) {
+ return head;
+ }
+
+ head.left = restoreByPostRecursively(array, start, less);
+ head.right = restoreByPostRecursively(array, more, end - 1);
+
+ return head;
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\350\260\203\346\225\264\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\344\270\255\344\270\244\344\270\252\351\224\231\350\257\257\347\232\204\350\212\202\347\202\271.java" "b/src/main/java/algorithm/binary_tree/\350\260\203\346\225\264\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\344\270\255\344\270\244\344\270\252\351\224\231\350\257\257\347\232\204\350\212\202\347\202\271.java"
new file mode 100644
index 0000000..52465d2
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\350\260\203\346\225\264\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221\344\270\255\344\270\244\344\270\252\351\224\231\350\257\257\347\232\204\350\212\202\347\202\271.java"
@@ -0,0 +1,60 @@
+package algorithm.binary_tree;
+
+import algorithm.data_structure.BinarySearchTree;
+import algorithm.utils.TreeNode;
+import java.util.Arrays;
+import java.util.Stack;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/4/26
+ */
+public class 调整搜索二叉树中两个错误的节点 {
+
+ public static void main(String[] args) {
+ TreeNode head = BinarySearchTree.create(5, 6, 3, 2, 1, 4, 9, 7, 8);
+ head.left.left.left.value = 9;
+ head.right.right.value = 1;
+
+ System.out.println(Arrays.toString(correct(head)));
+
+ head = BinarySearchTree.create(5, 6, 3, 2, 1, 4, 9, 7, 8);
+ head.left.left.value = 4;
+ head.left.right.value = 2;
+
+ System.out.println(Arrays.toString(correct(head)));
+ }
+
+ public static Integer[] correct(TreeNode head) {
+ if (head == null) {
+ return null;
+ }
+
+ return inOrder(head);
+ }
+
+ public static Integer[] inOrder(TreeNode head) {
+ TreeNode pre = null;
+ Integer[] result = new Integer[2];
+ Stack stack = new Stack<>();
+ while (!stack.isEmpty() || head != null) {
+ if (head != null) {
+ stack.push(head);
+ head = head.left;
+ } else {
+ head = stack.pop();
+
+ if (pre != null && pre.value > head.value) {
+ // 考虑两个错误的数字挨着的情况
+ result[0] = result[0] == null ? pre.value : result[0];
+ result[1] = head.value;
+ }
+
+ pre = head;
+ head = head.right;
+ }
+ }
+
+ return result;
+ }
+}
diff --git "a/src/main/java/algorithm/binary_tree/\351\200\232\350\277\207\346\234\211\345\272\217\346\225\260\347\273\204\347\224\237\346\210\220\345\271\263\350\241\241\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.java" "b/src/main/java/algorithm/binary_tree/\351\200\232\350\277\207\346\234\211\345\272\217\346\225\260\347\273\204\347\224\237\346\210\220\345\271\263\350\241\241\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.java"
new file mode 100644
index 0000000..d192904
--- /dev/null
+++ "b/src/main/java/algorithm/binary_tree/\351\200\232\350\277\207\346\234\211\345\272\217\346\225\260\347\273\204\347\224\237\346\210\220\345\271\263\350\241\241\346\220\234\347\264\242\344\272\214\345\217\211\346\240\221.java"
@@ -0,0 +1,31 @@
+package algorithm.binary_tree;
+
+import algorithm.utils.TreeNode;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/6
+ */
+public class 通过有序数组生成平衡搜索二叉树 {
+
+ public static TreeNode generateBST(int[] sortedArray) {
+ if (sortedArray == null || sortedArray.length == 0) {
+ return null;
+ }
+
+ return generateBSTRecursive(sortedArray, 0, sortedArray.length - 1);
+ }
+
+ private static TreeNode generateBSTRecursive(int[] sortedArray, int start, int end) {
+ if (start > end) {
+ return null;
+ }
+
+ int mid = (start + end) / 2;
+ TreeNode head = new TreeNode(sortedArray[mid]);
+ head.left = generateBSTRecursive(sortedArray, 0, mid - 1);
+ head.right = generateBSTRecursive(sortedArray, mid + 1, end);
+
+ return head;
+ }
+}
diff --git a/src/main/java/algorithm/data_structure/SortedBinaryTree.java b/src/main/java/algorithm/data_structure/BinarySearchTree.java
similarity index 78%
rename from src/main/java/algorithm/data_structure/SortedBinaryTree.java
rename to src/main/java/algorithm/data_structure/BinarySearchTree.java
index 3c07f60..f9eab5b 100644
--- a/src/main/java/algorithm/data_structure/SortedBinaryTree.java
+++ b/src/main/java/algorithm/data_structure/BinarySearchTree.java
@@ -1,13 +1,15 @@
package algorithm.data_structure;
import algorithm.utils.TreeNode;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import java.util.List;
/**
* @author Ethan Zhang
* @date 2022/4/12
*/
-public class SortedBinaryTree {
+public class BinarySearchTree {
private TreeNode root;
@@ -48,11 +50,9 @@ private boolean containsRecursive(TreeNode current, int value) {
}
public static TreeNode create(List values) {
- if (values == null || values.isEmpty()) {
- return null;
- }
+ Preconditions.checkNotNull(values);
- SortedBinaryTree binaryTree = new SortedBinaryTree();
+ BinarySearchTree binaryTree = new BinarySearchTree();
for (Integer value : values) {
binaryTree.add(value);
}
@@ -60,6 +60,12 @@ public static TreeNode create(List values) {
return binaryTree.root;
}
+ public static TreeNode create(Integer... values) {
+ Preconditions.checkNotNull(values);
+
+ return create(Lists.newArrayList(values));
+ }
+
public TreeNode getRoot() {
return root;
}
diff --git a/src/main/java/algorithm/data_structure/BinaryTree.java b/src/main/java/algorithm/data_structure/BinaryTree.java
index 90dbeb9..be4db70 100644
--- a/src/main/java/algorithm/data_structure/BinaryTree.java
+++ b/src/main/java/algorithm/data_structure/BinaryTree.java
@@ -1,6 +1,7 @@
package algorithm.data_structure;
import algorithm.utils.TreeNode;
+import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.List;
@@ -27,10 +28,17 @@ private static TreeNode createRecursive(List nums, TreeNode cur, int i)
}
public static TreeNode create(List nums) {
+ Preconditions.checkNotNull(nums);
+
BinaryTree binaryTree = new BinaryTree();
binaryTree.root = createRecursive(nums, binaryTree.root, 0);
return binaryTree.root;
}
+ public static TreeNode create(Integer... nums) {
+ Preconditions.checkNotNull(nums);
+
+ return create(Lists.newArrayList(nums));
+ }
}
diff --git "a/src/main/java/algorithm/link/\344\270\244\344\270\252\351\223\276\350\241\250\347\233\270\345\212\240.java" "b/src/main/java/algorithm/link/\344\270\244\344\270\252\351\223\276\350\241\250\347\233\270\345\212\240.java"
new file mode 100644
index 0000000..12f937f
--- /dev/null
+++ "b/src/main/java/algorithm/link/\344\270\244\344\270\252\351\223\276\350\241\250\347\233\270\345\212\240.java"
@@ -0,0 +1,48 @@
+package algorithm.link;
+
+import algorithm.utils.Node;
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/6
+ */
+public class 两个链表相加 {
+
+ public Node add(Node head1, Node head2) {
+ if (head1 == null) {
+ return head2;
+ }
+
+ if (head2 == null) {
+ return head1;
+ }
+
+ int adder = 0;
+ Node dummy = new Node(0);
+ Node head = dummy;
+ while (head1 != null || head2 != null || adder != 0) {
+ int val1 = head1 == null ? 0 : head1.value;
+ int val2 = head2 == null ? 0 : head2.value;
+
+ int sum = val1 + val2 + adder;
+ head.next = new Node(sum % 10);
+ head = head.next;
+
+ adder = sum / 10;
+
+ if (head1 != null) {
+ head1 = head1.next;
+ }
+
+ if (head2 != null) {
+ head2 = head2.next;
+ }
+ }
+
+ return dummy.next;
+ }
+
+
+}
diff --git "a/src/main/java/algorithm/link/\350\277\224\345\233\236\351\223\276\350\241\250\347\254\254K\344\270\252\350\212\202\347\202\271.java" "b/src/main/java/algorithm/link/\350\277\224\345\233\236\351\223\276\350\241\250\347\254\254K\344\270\252\350\212\202\347\202\271.java"
new file mode 100644
index 0000000..372b142
--- /dev/null
+++ "b/src/main/java/algorithm/link/\350\277\224\345\233\236\351\223\276\350\241\250\347\254\254K\344\270\252\350\212\202\347\202\271.java"
@@ -0,0 +1,30 @@
+package algorithm.link;
+
+import algorithm.utils.Node;
+
+/**
+ * @author Ethan Zhang
+ * @date 2022/5/6
+ */
+public class 返回链表第K个节点 {
+
+ public static Node k(Node head, int k) {
+ if (head == null || k < 1) {
+ return null;
+ }
+
+ Node slow, fast;
+ slow = fast = head;
+ while (k > 0) {
+ k--;
+ fast = fast.next;
+ }
+
+ while (fast != null) {
+ slow = slow.next;
+ fast = fast.next;
+ }
+
+ return slow;
+ }
+}
diff --git a/src/main/java/algorithm/utils/TreeNode.java b/src/main/java/algorithm/utils/TreeNode.java
index 422c10a..9175f42 100644
--- a/src/main/java/algorithm/utils/TreeNode.java
+++ b/src/main/java/algorithm/utils/TreeNode.java
@@ -22,6 +22,25 @@ public TreeNode(int value, TreeNode left, TreeNode right) {
this.right = right;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ TreeNode treeNode = (TreeNode) o;
+
+ return value == treeNode.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return value;
+ }
+
public int getValue() {
return value;
}