diff --git a/pom.xml b/pom.xml
index e19b6e5..b2bc770 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,5 +8,19 @@
leetcode-question
1.0-SNAPSHOT
+
+ UTF-8
+ UTF-8
+ 15
+ 15
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.69
+
+
\ No newline at end of file
diff --git a/src/main/java/com/shuzijun/leetcode/ListNodeUtils.java b/src/main/java/com/shuzijun/leetcode/ListNodeUtils.java
new file mode 100644
index 0000000..8bebb4c
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/ListNodeUtils.java
@@ -0,0 +1,51 @@
+package com.shuzijun.leetcode;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/19, Fri, 10:09
+ */
+public class ListNodeUtils {
+ public static int[] stringToIntegerArray(String input) {
+ input = input.trim();
+ input = input.substring(1, input.length() - 1);
+ if (input.length() == 0) {
+ return new int[0];
+ }
+
+ String[] parts = input.split(",");
+ int[] output = new int[parts.length];
+ for (int index = 0; index < parts.length; index++) {
+ String part = parts[index].trim();
+ output[index] = Integer.parseInt(part);
+ }
+ return output;
+ }
+
+ public static ListNode stringToListNode(String input) {
+ // Generate array from the input
+ int[] nodeValues = stringToIntegerArray(input);
+
+ // Now convert that list into linked list
+ ListNode dummyRoot = new ListNode(0);
+ ListNode ptr = dummyRoot;
+ for (int item : nodeValues) {
+ ptr.next = new ListNode(item);
+ ptr = ptr.next;
+ }
+ return dummyRoot.next;
+ }
+
+ public static void prettyPrintLinkedList(ListNode node) {
+ while (node != null && node.next != null) {
+ System.out.print(node.val + "->");
+ node = node.next;
+ }
+
+ if (node != null) {
+ System.out.println(node.val);
+ } else {
+ System.out.println("Empty LinkedList");
+ }
+ }
+}
diff --git a/src/main/java/com/shuzijun/leetcode/Node.java b/src/main/java/com/shuzijun/leetcode/Node.java
new file mode 100644
index 0000000..b7ac98a
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/Node.java
@@ -0,0 +1,25 @@
+package com.shuzijun.leetcode;
+
+import java.util.List;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/11, Thu, 1:21
+ */
+public class Node {
+ public int val;
+ public List children;
+
+ public Node() {
+ }
+
+ public Node(int _val) {
+ this.val = _val;
+ }
+
+ public Node(int _val, List _children) {
+ this.val = _val;
+ this.children = _children;
+ }
+}
diff --git a/src/main/java/com/shuzijun/leetcode/TreeNode.java b/src/main/java/com/shuzijun/leetcode/TreeNode.java
new file mode 100644
index 0000000..1fc99ad
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/TreeNode.java
@@ -0,0 +1,25 @@
+package com.shuzijun.leetcode;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/10, 水, 18:07
+ */
+public class TreeNode {
+ public TreeNode left;
+ public TreeNode right;
+ public int val;
+
+ TreeNode() {
+ }
+
+ public TreeNode(int val) {
+ this.val = val;
+ }
+
+ public TreeNode(int val, TreeNode left, TreeNode right) {
+ this.val = val;
+ this.left = left;
+ this.right = right;
+ }
+}
diff --git a/src/main/java/com/shuzijun/leetcode/TreeNodeUtils.java b/src/main/java/com/shuzijun/leetcode/TreeNodeUtils.java
new file mode 100644
index 0000000..682d8fc
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/TreeNodeUtils.java
@@ -0,0 +1,99 @@
+package com.shuzijun.leetcode;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/19, Fri, 10:08
+ */
+public class TreeNodeUtils {
+ public static String treeNodeToString(TreeNode root) {
+ if (root == null) {
+ return "[]";
+ }
+
+ String output = "";
+ Queue nodeQueue = new LinkedList<>();
+ nodeQueue.add(root);
+ while (!nodeQueue.isEmpty()) {
+ TreeNode node = nodeQueue.remove();
+
+ if (node == null) {
+ output += "null, ";
+ continue;
+ }
+
+ output += String.valueOf(node.val) + ", ";
+ nodeQueue.add(node.left);
+ nodeQueue.add(node.right);
+ }
+ return "[" + output.substring(0, output.length() - 2) + "]";
+ }
+
+ public static TreeNode stringToTreeNode(String input) {
+ input = input.trim();
+ input = input.substring(1, input.length() - 1);
+ if (input.length() == 0) {
+ return null;
+ }
+
+ String[] parts = input.split(",");
+ String item = parts[0];
+ TreeNode root = new TreeNode(Integer.parseInt(item));
+ Queue nodeQueue = new LinkedList<>();
+ nodeQueue.add(root);
+
+ int index = 1;
+ while (!nodeQueue.isEmpty()) {
+ TreeNode node = nodeQueue.remove();
+
+ if (index == parts.length) {
+ break;
+ }
+
+ item = parts[index++];
+ item = item.trim();
+ if (!item.equals("null")) {
+ int leftNumber = Integer.parseInt(item);
+ node.left = new TreeNode(leftNumber);
+ nodeQueue.add(node.left);
+ }
+
+ if (index == parts.length) {
+ break;
+ }
+
+ item = parts[index++];
+ item = item.trim();
+ if (!item.equals("null")) {
+ int rightNumber = Integer.parseInt(item);
+ node.right = new TreeNode(rightNumber);
+ nodeQueue.add(node.right);
+ }
+ }
+ return root;
+ }
+
+ public static void prettyPrintTree(TreeNode node, String prefix, boolean isLeft) {
+ if (node == null) {
+ System.out.println("Empty tree");
+ return;
+ }
+
+ if (node.right != null) {
+ prettyPrintTree(node.right, prefix + (isLeft ? "│ " : " "), false);
+ }
+
+ System.out.println(prefix + (isLeft ? "└── " : "┌── ") + node.val);
+
+ if (node.left != null) {
+ prettyPrintTree(node.left, prefix + (isLeft ? " " : "│ "), true);
+ }
+ }
+
+ public static void prettyPrintTree(TreeNode node) {
+ prettyPrintTree(node, "", true);
+ }
+}
diff --git a/src/main/java/com/shuzijun/leetcode/Trie.java b/src/main/java/com/shuzijun/leetcode/Trie.java
new file mode 100644
index 0000000..56d3799
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/Trie.java
@@ -0,0 +1,64 @@
+package com.shuzijun.leetcode;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/16, Tue, 12:36
+ */
+public class Trie {
+ Trie[] children;
+ boolean isWord;
+
+ /**
+ * Initialize your data structure here.
+ */
+ public Trie() {
+ this.children = new Trie[26];
+ this.isWord = false;
+ }
+
+ /**
+ * Inserts a word into the trie.
+ */
+ public void insert(String word) {
+ this.insert(word.toCharArray());
+ }
+
+ public void insert(char[] chars) {
+ Trie curr = this;
+ for (int i = 0; i < chars.length; i++) {
+ char c = chars[i];
+ if (curr.children[c - 'a'] == null) {
+ curr.children[c - 'a'] = new Trie();
+ }
+ curr = curr.children[c - 'a'];
+ }
+ curr.isWord = true;
+ }
+
+ /**
+ * Returns if the word is in the trie.
+ */
+ public boolean search(String word) {
+ Trie leaf = this.findLeafTrie(word);
+ return leaf != null && leaf.isWord;
+ }
+
+ /**
+ * Returns if there is any word in the trie that starts with the given prefix.
+ */
+ public boolean startsWith(String prefix) {
+ return this.findLeafTrie(prefix) != null;
+ }
+
+ private Trie findLeafTrie(String word) {
+ Trie curr = this;
+ for (int i = 0; i < word.length(); i++) {
+ curr = curr.children[word.charAt(i) - 'a'];
+ if (curr == null) {
+ return null;
+ }
+ }
+ return curr;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/shuzijun/leetcode/UnionFind.java b/src/main/java/com/shuzijun/leetcode/UnionFind.java
new file mode 100644
index 0000000..d62ef23
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/UnionFind.java
@@ -0,0 +1,57 @@
+package com.shuzijun.leetcode;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.IntStream;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/14, Sun, 14:56
+ */
+public class UnionFind {
+ private int[] roots;
+
+ protected UnionFind(int n) {
+ this.roots = IntStream.range(0, n).toArray();
+ }
+
+ protected int[] getRoots() {
+ return this.roots;
+ }
+
+ protected void union(int p, int q) {
+ this.roots[this.findRoot(p)] = this.findRoot(q);
+ }
+
+ protected void union(int... p) {
+ for (int i = 1; i < p.length; i++) {
+ this.union(p[i], p[0]);
+ }
+ }
+
+ protected int findRoot(int i) {
+ int root = i;
+ while (root != this.roots[root]) {
+ root = this.roots[root];
+ }
+ int t;
+ while (i != this.roots[root]) {
+ t = this.roots[i];
+ this.roots[i] = root;
+ i = t;
+ }
+ return root;
+ }
+
+ protected boolean isConnected(int p, int q) {
+ return this.findRoot(p) == this.findRoot(q);
+ }
+
+ protected int getCount() {
+ Set rootSet = new HashSet<>();
+ Arrays.stream(this.roots).forEach(root -> rootSet.add(this.findRoot(root)));
+ return rootSet.size();
+ }
+}
diff --git a/src/main/java/com/shuzijun/leetcode/Utils.java b/src/main/java/com/shuzijun/leetcode/Utils.java
new file mode 100644
index 0000000..a63b36a
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/Utils.java
@@ -0,0 +1,79 @@
+package com.shuzijun.leetcode;
+
+
+import com.alibaba.fastjson.JSONArray;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/10, 水, 18:06
+ */
+public class Utils {
+ public static TreeNode arrayToTreeNode(String s) {
+ List array = Arrays.stream(s.substring(s.indexOf("[") + 1, s.lastIndexOf("]")).split(",")).map(i ->
+ i.equals("null") ? null : Integer.valueOf(i)
+ ).collect(Collectors.toList());
+ return list2TreeNode(array);
+ }
+
+ public static TreeNode list2TreeNode(List array) {
+ if (array.isEmpty()) {
+ return null;
+ }
+ TreeNode root = new TreeNode(array.get(0));
+ Queue queue = new LinkedList<>();
+ queue.add(root);
+ boolean isLeft = true;
+ for (int i = 1; i < array.size(); i++) {
+ TreeNode node = queue.peek();
+ if (isLeft) {
+ if (array.get(i) != null) {
+ node.left = new TreeNode(array.get(i));
+ queue.offer(node.left);
+ }
+ isLeft = false;
+ } else {
+ if (array.get(i) != null) {
+ node.right = new TreeNode(array.get(i));
+ queue.offer(node.right);
+ }
+ queue.poll();
+ isLeft = true;
+ }
+ }
+ return root;
+ }
+
+ public static int[] stringToArray(String s) {
+ return Arrays.stream(s.substring(
+ s.indexOf("[") + 1, s.lastIndexOf("]")).split(",")).mapToInt(Integer::valueOf).toArray();
+ }
+
+ public static String[] stringToStringArray(String s) {
+ return ((JSONArray) JSONArray.parse(s)).toArray(new String[]{});
+ }
+
+ public static int[][] stringTo2DArray(String s) {
+ JSONArray[] arr = ((JSONArray) JSONArray.parse(s)).toArray(new JSONArray[]{});
+ int[][] result = new int[arr.length][Arrays.stream(arr).mapToInt(JSONArray::size).max().orElse(0)];
+ for (int i = 0; i < arr.length; i++) {
+ result[i] = Arrays.stream(arr[i].toArray()).mapToInt(o -> (int) o).toArray();
+ System.out.println(Arrays.toString(result[i]));
+ }
+ return result;
+ }
+
+ public static List> stringTo2DStringList(String s) {
+ JSONArray[] arr = ((JSONArray) JSONArray.parse(s)).toArray(new JSONArray[]{});
+ List> result = new ArrayList<>();
+ for (JSONArray objects : arr) {
+ List list = Arrays.stream(objects.toArray()).map(String::valueOf).collect(Collectors.toList());
+ result.add(list);
+ System.out.println(list);
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/shuzijun/leetcode/WeightUnionFind.java b/src/main/java/com/shuzijun/leetcode/WeightUnionFind.java
new file mode 100644
index 0000000..bac448b
--- /dev/null
+++ b/src/main/java/com/shuzijun/leetcode/WeightUnionFind.java
@@ -0,0 +1,62 @@
+package com.shuzijun.leetcode;
+
+import java.util.stream.IntStream;
+
+/**
+ * @author : CAOMU
+ * @version : 1.0
+ * @since : 2021/02/14, Sun, 14:55
+ */
+public class WeightUnionFind {
+
+ private int[] parent;
+
+ /**
+ * 指向的父结点的权值
+ */
+ private double[] weight;
+
+
+ public WeightUnionFind(int n) {
+ this.parent = IntStream.range(0, n).toArray();
+ this.weight = new double[n];
+ IntStream.range(0, n).forEach(i -> this.weight[i] = 1.0d);
+ }
+
+ public void union(int x, int y, double value) {
+ int rootX = this.find(x);
+ int rootY = this.find(y);
+ if (rootX == rootY) {
+ return;
+ }
+
+ this.parent[rootX] = rootY;
+ // 关系式的推导请见「参考代码」下方的示意图
+ this.weight[rootX] = this.weight[y] * value / this.weight[x];
+ }
+
+ /**
+ * 路径压缩
+ *
+ * @param x
+ * @return 根结点的 id
+ */
+ public int find(int x) {
+ if (x != this.parent[x]) {
+ int origin = this.parent[x];
+ this.parent[x] = this.find(this.parent[x]);
+ this.weight[x] *= this.weight[origin];
+ }
+ return this.parent[x];
+ }
+
+ public double isConnected(int x, int y) {
+ int rootX = this.find(x);
+ int rootY = this.find(y);
+ if (rootX == rootY) {
+ return this.weight[x] / this.weight[y];
+ } else {
+ return -1.0d;
+ }
+ }
+}