+ * 课程视频中分别为左右子树高度写了重复的方法 + * 此处为同一段代码复用 + * + * @param node + * @return + */ + public int height(Node node) { + if (node == null) { + return 0; + } + return node.height(); + } + + /** + * 右旋 + */ + public void rightRotate() { + // 1. node --> newNode + Node newRight = new Node(this.value); + // 2. node.right --> newNode.right + newRight.right = this.right; + // 3. node.left.right --> newNode.left + newRight.left = left.right; + // 4. node.left --> node + this.value = left.value; + // 5. node.left.left --> node.left + this.left = left.left; + // 6. newNode --> node.right + this.right = newRight; + } + + /** + * 左旋 + */ + public void leftRotate() { + // 1. node --> newNode + Node newRight = new Node(this.value); + // 2. node.left --> newNode.left + newRight.left = this.left; + // 3. node.right.left --> newNode.right + newRight.right = right.left; + // 4. node.right --> node + this.value = right.value; + // 5. node.right.right --> node.right + this.right = right.right; + // 6. newNode --> node.left + this.left = newRight; + } + + + /** + * 添加节点 + * + * @param node + */ + public void add(Node node) { + // 如果 node 值小于当前节点 + if (node.value < this.value) { + // 如果左子节点为空 + if (this.left == null) { + // 赋值给左子节点 + this.left = node; + } else { + // 否则调用左子节点的添加方法 + this.left.add(node); + } + } else {// 如果 node 值大于当前节点 + // 如果右子节点为空 + if (this.right == null) { + // 赋值给右子节点 + this.right = node; + } else { + // 否则调用右子节点的添加方法 + this.right.add(node); + } + } + + // 判断是否为平衡二叉树,如果不是平衡树,需要重新调整 + if (height(left) - height(right) > 1) { + // 如果 left.left 高度 < left.right 高度 + // 要进行双旋转 + if (left.left != null && height(left.left) < height(left.right)) { + // 首先对 left 左旋 + left.leftRotate(); + } + // 调用右旋方法 + rightRotate(); + } else if (height(right) - height(left) > 1) { + // 如果 right.right 高度 < right.left 高度 + // 要进行双旋转 + if (right.right != null && height(right.right) < height(right.left)) { + // 首先对 right 右旋 + right.rightRotate(); + } + // 调用左旋方法 + leftRotate(); + } + + } + + + /** + * 中序遍历 + * + * @param node + */ + public void midShow(Node node) { + if (node == null) { + return; + } + midShow(node.left); + System.out.print(node.value + " "); + midShow(node.right); + } + + /** + * 查找节点 + * + * @param value + * @return + */ + public Node search(int value) { + if (this.value == value) { + return this; + } + if (this.left != null && this.left.value == value) { + return left; + } + if (this.right != null && this.right.value == value) { + return right; + } + return null; + } + + + /** + * 查找双亲节点 + * + * @param value + * @return + */ + public Node searchParent(int value) { + // 如果左子节点非空 + if (this.left != null) { + // 左子节点的值正好等于目标值 + if (this.left.value == value) { + // 当前节点是目标值的双亲节点,返回当前节点 + return this; + } + // 如果目标值小于当前节点的值 + // 按照二叉查找树的性质,左子节点比双亲节点小 + // 在左子树继续查找 + if (value < this.value) { + return this.left.searchParent(value); + } + } + // 如果右子节点非空 + if (this.right != null) { + // 由子节点的值正好等于目标值 + if (this.right.value == value) { + // 当前节点是目标值的双亲节点,返回当前节点 + return this; + } + // 如果目标值大于当前节点的值 + // 按照二叉查找树的性质,右子节点比双亲节点大 + // 在右子树继续查找 + if (value > this.value) { + return this.right.searchParent(value); + } + } + // 都不符合说明目标值不存在树中,也没有双亲节点 + // 返回 null + return null; + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo12/TestBinarySortTree.java b/codes/java_dataStructure_luozhaoyong/src/demo12/TestBinarySortTree.java new file mode 100644 index 0000000..bd15a3f --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo12/TestBinarySortTree.java @@ -0,0 +1,49 @@ +package demo12; + +/** + * 测试平衡二叉树 + * @author admin + */ +public class TestBinarySortTree { + public static void main(String[] args) { + int[] arr = new int[]{8, 9, 6, 7, 5, 4}; + BinarySortTree bst = new BinarySortTree(); + // 添加节点 + for (int i : arr) { + bst.add(new Node(i)); + } + // 打印结果为 3 + System.out.println(bst.root.height()); + // 打印结果为 6 + System.out.println(bst.root.value); + + System.out.println("======================="); + + // 重新创建一棵平衡二叉树,测试左旋 + arr = new int[]{2, 1, 4, 3, 5, 6}; + bst = new BinarySortTree(); + // 添加节点 + for (int i : arr) { + bst.add(new Node(i)); + } + // 打印结果为 3 + System.out.println(bst.root.height()); + // 打印结果为 4 + System.out.println(bst.root.value); + + System.out.println("======================="); + + // 重新创建一棵平衡二叉树,测试双旋转 + arr = new int[]{8, 9, 5, 4, 6, 7}; + bst = new BinarySortTree(); + // 添加节点 + for (int i : arr) { + bst.add(new Node(i)); + } + // 打印结果为 3 + System.out.println(bst.root.height()); + // 打印结果为 6 + System.out.println(bst.root.value); + + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo13/HashTable.java b/codes/java_dataStructure_luozhaoyong/src/demo13/HashTable.java new file mode 100644 index 0000000..05e4634 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo13/HashTable.java @@ -0,0 +1,44 @@ +package demo13; + +import java.util.Arrays; + +/** + * 自定义哈希表 + * + * @author admin + */ +public class HashTable { + /** + * 存储学生数据的数组 + */ + private StuInfo[] data = new StuInfo[100]; + + /** + * 向散列表中添加元素 + * + * @param stuInfo + */ + public void put(StuInfo stuInfo) { + // 调用散列函数获取存储位置 + int index = stuInfo.hashCode(); + // 在指定位置存入对象 + data[index] = stuInfo; + } + + /** + * 从散列表中获取元素 + * + * @param stuInfo + * @return + */ + public StuInfo get(StuInfo stuInfo) { + return data[stuInfo.hashCode()]; + } + + @Override + public String toString() { + return "HashTable{" + + "data=" + Arrays.toString(data) + + '}'; + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo13/StuInfo.java b/codes/java_dataStructure_luozhaoyong/src/demo13/StuInfo.java new file mode 100644 index 0000000..1bda5d0 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo13/StuInfo.java @@ -0,0 +1,59 @@ +package demo13; + +/** + * 学生信息类 + * + * @author admin + */ +public class StuInfo { + int age; + int count; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + /** + * 自定义散列函数 + * + * @return + */ + @Override + public int hashCode() { + // 1. 直接定址法 + // 将年龄直接返回 + // 2. 取余法 + // 将 age 取模后返回余数 + return age%10; + } + + public StuInfo(int age, int count) { + super(); + this.age = age; + this.count = count; + } + + public StuInfo(int age) { + this.age = age; + } + + @Override + public String toString() { + return "StuInfo{" + + "age=" + age + + ", count=" + count + + '}'; + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo13/TestHashTable.java b/codes/java_dataStructure_luozhaoyong/src/demo13/TestHashTable.java new file mode 100644 index 0000000..9a6690a --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo13/TestHashTable.java @@ -0,0 +1,29 @@ +package demo13; + +/** + * 测试散列函数 + * @author admin + */ +public class TestHashTable { + public static void main(String[] args) { + StuInfo s1 = new StuInfo(16, 3); + StuInfo s2 = new StuInfo(17, 11); + StuInfo s3 = new StuInfo(18, 23); + StuInfo s4 = new StuInfo(19, 24); + StuInfo s5 = new StuInfo(20, 9); + + HashTable ht = new HashTable(); + ht.put(s1); + ht.put(s2); + ht.put(s3); + ht.put(s4); + ht.put(s5); + + System.out.println(ht); + + // 获取目标数据 + StuInfo target = new StuInfo(18); + StuInfo info = ht.get(target); + System.out.println(info); + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo14/Graph.java b/codes/java_dataStructure_luozhaoyong/src/demo14/Graph.java new file mode 100644 index 0000000..25b27c4 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo14/Graph.java @@ -0,0 +1,140 @@ +package demo14; + +import demo2.MyStack; + +/** + * 图 + * + * @author admin + */ +public class Graph { + /** + * 顶点数组 + */ + Vertex[] vertex; + /** + * 数组下标,作为哈希表地址 + */ + int currentSize; + /** + * 二维数组定义的邻接矩阵 + */ + int[][] adjMat; + /** + * 创建栈用于存储顶点下标 + */ + MyStack stack = new MyStack(); + /** + * 遍历时记录当前访问下标 + */ + int currentIndex; + + /** + * 构造函数 + * + * @param size + */ + public Graph(int size) { + // 定义顶点数组的容量 + this.vertex = new Vertex[size]; + // 根据顶点数量定义邻接矩阵 + this.adjMat = new int[size][size]; + } + + /** + * 添加节点 + * + * @param v + */ + public void addVertex(Vertex v) { + // 直接向数组中添加元素 + this.vertex[currentSize++] = v; + } + + /** + * 添加边 + * 方法与视频课程中稍有不同 + * 在同一个 for 循环里直接查找符合 v1 和 v2 的两个顶点 + * 加上各种判断是否为空的边界条件 + * + * @param v1 + * @param v2 + */ + public void addEdge(String v1, String v2) { + // 矩阵行坐标 + int index1 = -1; + // 矩阵列坐标 + int index2 = -1; + // 遍历数组,查找与指定值 v1 和 v2 相等的顶点 + for (int i = 0; i < vertex.length; i++) { + // 获取当前位置的顶点对象 + Vertex vertex = this.vertex[i]; + // 顶点非空 + if (vertex != null) { + // 找出符合 v1 和 v2 值的顶点 + // 将符合条件的对象在数组的下标赋值给 index1 和 index2 + if (vertex.getValue().equals(v1)) { + index1 = i; + } + if (vertex.getValue().equals(v2)) { + index2 = i; + } + } + } + // 同时找到了两个 index 值再去邻接矩阵查找元素 + if (index1 != -1 && index2 != -1) { + // 将交叉位置赋值为 1,表示两个顶点之间的连接关系 + adjMat[index1][index2] = 1; + adjMat[index2][index1] = 1; + } + } + + /** + * 深度优先遍历方法 + */ + public void dfs() { + // 0. 将访问下标初始值设为 0 + currentIndex = 0; + // 1. 将第 0 个顶点压入栈中,标记为已访问 + stack.push(currentIndex); + vertex[currentIndex].visited = true; + // 5. 重复步骤 2~4,直到栈为空 + while (!stack.isEmpty()) { + // 2. 从当前下标后一个位置起,遍历顶点数组,按序查找当前顶点与其后顶点之间的连接关系 + for (int i = currentIndex + 1; i < vertex.length; i++) { + // adjMat[currentIndex][i] == 1 表示下标为 currentIndex 的顶点和下标为 i 的顶点相通 + // !vertex[i].visited 表示访问时遇到已访问的顶点则跳过 + if (adjMat[currentIndex][i] == 1 && !vertex[i].visited) { + // 打印顶点之间的连接关系 + System.out.println(vertex[currentIndex].getValue() + " --> " + vertex[i].getValue()); + // 将当前顶点下标入栈 + stack.push(i); + // 访问过的顶点标记为已访问 + vertex[i].visited = true; + // A --> B 连通时,currentIndex 对应 A,i 对应 B + // 继续查找时,让 currentIndex 顺延到当前 i 对应的顶点 B 即可 + // 将 i 的值赋给当前下标 currentIndex + currentIndex = i; + /* + 此处对课程视频中的代码做了改进,用 currentIndex = i 代替课程视频中的 continue out + 按照课程视频中的代码 + 不对 currentIndex 修改,直接 continue out 跳出当前循环 + 再次进入 while 循环时,因为 currentIndex 没有变化,会重复执行 for 循环语句 + 执行到上一轮的 i 时,i 已在上一轮被标识位 visited,此时才跳过 i 继续执行 + 即从 continue out 到下一轮执行到 i 位置的操作都是不必要的重复 + */ + } + } + // 3. 查询不到后续顶点的连接关系时,从栈中弹出栈顶元素 + stack.pop(); + // 步骤 4 弹出了栈顶元素,为保证栈非空,需要单独做判断 + if (!stack.isEmpty()) { + // 4. 以新的栈顶元素为顶点继续查找连接关系 + currentIndex = stack.peek(); + } else { + // 否则跳出循环 + break; + } + } + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo14/TestGraph.java b/codes/java_dataStructure_luozhaoyong/src/demo14/TestGraph.java new file mode 100644 index 0000000..317525c --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo14/TestGraph.java @@ -0,0 +1,51 @@ +package demo14; + +import java.util.Arrays; + +/** + * 测试图 + * + * @author admin + */ +public class TestGraph { + public static void main(String[] args) { + Vertex v1 = new Vertex("A"); + Vertex v2 = new Vertex("B"); + Vertex v3 = new Vertex("C"); + Vertex v4 = new Vertex("D"); + Vertex v5 = new Vertex("E"); + + Graph g = new Graph(5); + g.addVertex(v1); + g.addVertex(v2); + g.addVertex(v3); + g.addVertex(v4); + g.addVertex(v5); + + g.addEdge("A", "C"); + g.addEdge("B", "C"); + g.addEdge("A", "B"); + g.addEdge("B", "D"); + g.addEdge("B", "E"); + + // 遍历打印邻接矩阵,查看添加边的操作是否正确 + // 打印结果: + // [0, 1, 1, 0, 0] + // [1, 0, 1, 1, 1] + // [1, 1, 0, 0, 0] + // [0, 1, 0, 0, 0] + // [0, 1, 0, 0, 0] + for (int[] a : g.adjMat) { + System.out.println(Arrays.toString(a)); + } + + // 执行深度优先遍历 + // 打印结果: + // A --> B + // B --> C + // B --> D + // B --> E + g.dfs(); + + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo14/Vertex.java b/codes/java_dataStructure_luozhaoyong/src/demo14/Vertex.java new file mode 100644 index 0000000..6cd7289 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo14/Vertex.java @@ -0,0 +1,34 @@ +package demo14; + +/** + * 顶点类 + * + * @author admin + */ +public class Vertex { + /** + * 顶点数据内容 + */ + String value; + /** + * 顶点是否已经访问过 + */ + boolean visited; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Vertex(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/DoubleNode.java b/codes/java_dataStructure_luozhaoyong/src/demo2/DoubleNode.java new file mode 100644 index 0000000..c823bb1 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/DoubleNode.java @@ -0,0 +1,78 @@ +package demo2; + +/** + * 定义双向链表的节点 + * @author admin + */ +public class DoubleNode { + /** + * 前置节点 + */ + DoubleNode pre = this; + + /** + * 后继节点 + */ + DoubleNode next = this; + + /** + * 节点数据 + */ + int data; + + /** + * 构造函数 + * @param data + */ + public DoubleNode(int data){ + this.data = data; + } + + /** + * 插入节点方法 + * @param node + */ + public void after(DoubleNode node){ + // 获取当前节点的后继节点 + DoubleNode nextNext = this.next; + // 将当前节点的后继节点指向新节点 + this.next = node; + // 新节点的前置节点指向当前节点 + node.pre = this; + + // 新节点的后继节点指向原后继节点 + node.next = nextNext; + // 原后继节点的前置节点指向新节点 + nextNext.pre = node; + + // 上述过程将新节点插入到当前节点和原后继节点之间 + } + + /** + * 获取后继节点 + * @return + */ + public DoubleNode next(){ + // 返回后继节点 + return this.next; + } + + /** + * 获取前置节点 + * @return + */ + public DoubleNode pre(){ + // 返回前置节点 + return this.pre; + } + + /** + * 获取数据 + * @return + */ + public int getData(){ + // 返回当前节点数据 + return this.data; + } +} + diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/LoopNode.java b/codes/java_dataStructure_luozhaoyong/src/demo2/LoopNode.java new file mode 100644 index 0000000..2c187cd --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/LoopNode.java @@ -0,0 +1,73 @@ +package demo2; + +/** + * 定义节点类 + * + * @author admin + */ +public class LoopNode { + /** + * 节点数据 + */ + int data; + /** + * 后继节点 + * 尾节点指向头节点 + */ + LoopNode next = this; + + /** + * 构造方法 + * + * @param data + */ + public LoopNode(int data) { + this.data = data; + } + + /** + * 获取后继节点 + * + * @return + */ + public LoopNode next() { + // 直接返回后继节点 + return this.next; + } + + /** + * 获取节点数据 + * + * @return + */ + public int getData() { + return this.data; + } + + + /** + * 删除当前节点的下一个节点 + */ + public void removeNext() { + // 如果当前节点的后继节点为空,直接返回 + if (next == null) { + return; + } + // 将当前节点的后继节点指向下下个节点 + this.next = next.next; + } + + /** + * 插入一个新节点 + * + * @param node + */ + public void after(LoopNode node) { + // 获取当前节点的后继节点 + LoopNode nextNext = this.next; + // 当前节点的后继节点指向新加入的节点 + this.next = node; + // 新节点的后继节点指向原先的后继节点 + node.next = nextNext; + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/MyQueue.java b/codes/java_dataStructure_luozhaoyong/src/demo2/MyQueue.java new file mode 100644 index 0000000..0032026 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/MyQueue.java @@ -0,0 +1,77 @@ +package demo2; + +/** + * 数组实现一个队列 + * @author admin + */ +public class MyQueue { + /** + * 存储数据的数组 + */ + int[] elements; + + /** + * 构造方法 + */ + public MyQueue() { + // 初始化数组 + elements = new int[0]; + } + + /** + * 入队 + * @param element + */ + public void add(int element) { + // 新建一个数组,长度是原数组的长度+1 + int[] newArr = new int[elements.length + 1]; + + // 将原数组中的元素赋值逐个给新数组 + for (int i = 0; i < elements.length; i++) { + newArr[i] = elements[i]; + } + + // 将新元素赋值给新数组的最后一个位置 + newArr[newArr.length - 1] = element; + // 新旧数组替换 + elements = newArr; + } + + /** + * 出队 + * @return + */ + public int poll() { + if (elements.length == 0) { + throw new RuntimeException("queue is empty"); + } + // 取出数组的第一个元素 + int element = elements[0]; + + // 创建一个新数组,长度比原数组长度少 1 + int[] newArr = new int[elements.length - 1]; + + // 将原数组除第一个元素以外的所有元素赋值给新数组 + for (int i = 1; i < elements.length; i++) { + // 取原数组元素时,i 从 1开始 + // 新数组下标从 0 开始,所以对应每个下标要在 i 的基础上 -1 + newArr[i - 1] = elements[i]; + } + // 新旧数组替换 + elements = newArr; + + // 返回出队的元素 + return element; + } + + /** + * 判断队列是否为空 + * @return + */ + public boolean isEmpty() { + // 判断队列长度是否为 0 + return elements.length == 0; + } + + +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/MyStack.java b/codes/java_dataStructure_luozhaoyong/src/demo2/MyStack.java new file mode 100644 index 0000000..46c8eb3 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/MyStack.java @@ -0,0 +1,94 @@ +package demo2; + + +/** + * 数组实现栈 + * @author admin + */ +public class MyStack { + + /** + * 使用数组存储数据 + */ + int[] elements; + + /** + * 构造函数 + */ + public MyStack() { + // elements 初始化为空数组 + elements = new int[0]; + } + + /** + * 压入元素 + * @param element + */ + public void push(int element) { + // 新建数组,比原数组长度大 1 + int[] newArr = new int[elements.length + 1]; + + // 遍历原数组 + for (int i = 0; i < elements.length; i++) { + // 将元素逐个赋值给新数组 + newArr[i] = elements[i]; + } + + // 将新元素赋值给新数组最后一个位置 + newArr[newArr.length - 1] = element; + + // 新旧数组替换 + elements = newArr; + } + + /** + * 取出栈顶元素 + * @return + */ + public int pop() { + // 如果栈为空,抛出异常 + if (elements.length == 0) { + throw new RuntimeException("stack is empty"); + } + + // 取出数组中最后一个元素 + int element = elements[elements.length - 1]; + + // 创建一个新数组,比原数组小 1 + int[] newArr = new int[elements.length - 1]; + + // 遍历原数组,但是不包括最后一个元素 + // 所以控制变量 i 的最大值小于 elements.length -1 + for (int i = 0; i < elements.length - 1; i++) { + // 将原数组中的值逐个赋值给新数组 + newArr[i] = elements[i]; + } + // 新旧数组替换 + elements = newArr; + // 返回取出的栈顶元素 + return element; + } + + /** + * 查看栈顶元素 + * @return + */ + public int peek() { + // 如果栈为空,抛出异常 + if (elements.length == 0) { + throw new RuntimeException("stack is empty"); + } + // 返回数组最后一个元素,即栈顶元素 + return elements[elements.length - 1]; + } + + /** + * 判断栈是否为空 + * @return + */ + public boolean isEmpty() { + // 判断数组的长度是否为 0 + return elements.length == 0; + } + +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/Node.java b/codes/java_dataStructure_luozhaoyong/src/demo2/Node.java new file mode 100644 index 0000000..34bd559 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/Node.java @@ -0,0 +1,119 @@ +package demo2; + +/** + * 定义节点类 + * @author admin + */ +public class Node { + /** + * 节点数据 + */ + int data; + /** + * 后继节点 + */ + Node next; + + /** + * 构造方法 + * @param data + */ + public Node(int data) { + this.data = data; + } + + /** + * 追加节点 + * @param node + * @return + */ + public Node append(Node node) { + // 定义一个变量 currentNode 指向当前节点 + Node currentNode = this; + + // 教学视频中的写法 +// while (true){ +// // 获取当前节点的后继节点 +// Node nextNode = currentNode.next; +// // 如果后继节点为空,跳出循环 +// if(nextNode==null){ +// break; +// } +// // 当前节点指向后继节点,循环继续 +// currentNode = nextNode; +// } + // 如果后继节点非空,循环继续 + while (currentNode.next != null) { + // 当前节点 currentNode 指向后继节点 + currentNode = currentNode.next; + } + // 循环结束时,currentNode 已经指向链表的尾节点 + // 将参数 node 赋值给 currentNode 的后继节点 + currentNode.next = node; + // 返回当前节点 + return this; + } + + /** + * 获取后继节点 + * @return + */ + public Node next() { + // 直接返回后继节点 + return this.next; + } + + /** + * 获取节点数据 + * @return + */ + public int getData() { + return this.data; + } + + /** + * 判断当前节点是否是最后一个节点 + * @return + */ + public boolean isLast() { + // 判断当前节点的后继节点是否为空 + return this.next == null; + } + + /** + * 删除当前节点的下一个节点 + */ + public void removeNext() { + // 如果当前节点的后继节点为空,直接返回 + if (next == null) { + return; + } + // 将当前节点的后继节点指向下下个节点 + this.next = next.next; + } + + /** + * 插入一个新节点 + * @param node + */ + public void after(Node node) { + // 获取当前节点的后继节点 + Node nextNext = this.next; + // 当前节点的后继节点指向新加入的节点 + this.next = node; + // 新节点的后继节点指向原先的后继节点 + node.next = nextNext; + } + + /** + * 打印所有节点的值 + */ + public void show() { + Node currentNode = this; + while (currentNode != null) { + System.out.print(currentNode.data + " "); + currentNode = currentNode.next; + } + System.out.println(); + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/TestLoopNode.java b/codes/java_dataStructure_luozhaoyong/src/demo2/TestLoopNode.java new file mode 100644 index 0000000..bd94858 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/TestLoopNode.java @@ -0,0 +1,19 @@ +package demo2; + +/** + * 测试循环链表 + */ +public class TestLoopNode { + public static void main(String[] args) { + // 创建新节点 + LoopNode n1 = new LoopNode(1); + LoopNode n2 = new LoopNode(2); + LoopNode n3 = new LoopNode(3); + LoopNode n4 = new LoopNode(4); + // 插入节点 + n1.after(n2); + // 显示结果 + System.out.println(n1.next().getData()); // 2 + System.out.println(n2.next().getData()); // 1 + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestDoubleNode.java b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestDoubleNode.java new file mode 100644 index 0000000..cdfa0fc --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestDoubleNode.java @@ -0,0 +1,41 @@ +package demo2.test; + +import demo2.DoubleNode; + +/** + * 测试双向链表 + * @author admin + */ +public class TestDoubleNode { + public static void main(String[] args) { + // 创建节点 + DoubleNode n1 = new DoubleNode(1); + DoubleNode n2 = new DoubleNode(2); + DoubleNode n3 = new DoubleNode(3); + // 打印节点的值,结果为 1 + System.out.println(n1.pre().getData()); + // 打印结果为 1 + System.out.println(n1.getData()); + // 打印结果为 1 + System.out.println(n1.next().getData()); + System.out.println(); + + // 节点之间建立连接 + n1.after(n2); + n2.after(n3); + // 打印节点的值,打印结果为 1 + System.out.println(n2.pre().getData()); + // 打印结果为 2 + System.out.println(n2.getData()); + // 打印结果为 3 + System.out.println(n2.next().getData()); + System.out.println(); + + // 双向循环链表最后添加的节点,后继节点指向第一个节点,打印结果为 1 + System.out.println(n3.next().getData()); + // 打印结果为 3 + System.out.println(n1.pre().getData()); + + + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestLoopNode.java b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestLoopNode.java new file mode 100644 index 0000000..a3b105a --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestLoopNode.java @@ -0,0 +1,31 @@ +package demo2.test; + +import demo2.LoopNode; + +/** + * 测试循环链表 + * + * @author admin + */ +public class TestLoopNode { + public static void main(String[] args) { + LoopNode n1 = new LoopNode(1); + LoopNode n2 = new LoopNode(2); + LoopNode n3 = new LoopNode(3); + LoopNode n4 = new LoopNode(4); + + // 增加节点 + n1.after(n2); + n2.after(n3); + n3.after(n4); + + // 打印结果是 2 + System.out.println(n1.next().getData()); + // 打印结果是 3 + System.out.println(n2.next().getData()); + // 打印结果是 4 + System.out.println(n3.next().getData()); + // 打印结果是 1,循环链表首尾相连 + System.out.println(n4.next().getData()); + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestMyQueue.java b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestMyQueue.java new file mode 100644 index 0000000..703447e --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestMyQueue.java @@ -0,0 +1,31 @@ +package demo2.test; + +import demo2.MyQueue; + +/** + * 测试队列 + * @author admin + */ +public class TestMyQueue { + public static void main(String[] args) { + // 创建一个队列 + MyQueue mq = new MyQueue(); + // 添加元素 + mq.add(9); + mq.add(8); + mq.add(7); + // 出队,打印结果为 9 + System.out.println(mq.poll()); + mq.add(6); + // 出队前有新元素入队,不影响出队的顺序,打印结果为 8 + System.out.println(mq.poll()); + // 判断是否为空,打印结果为 false + System.out.println(mq.isEmpty()); + // 继续出队,打印结果为 7 + System.out.println(mq.poll()); + // 大姨结果为 8 + System.out.println(mq.poll()); + // 再判断是否为空,打印结果为 true + System.out.println(mq.isEmpty()); + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestMyStack.java b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestMyStack.java new file mode 100644 index 0000000..0732807 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestMyStack.java @@ -0,0 +1,45 @@ +package demo2.test; + +import demo2.MyStack; + +/** + * 测试栈 + * + * @author admin + */ +public class TestMyStack { + public static void main(String[] args) { + MyStack ms = new MyStack(); + // 测试栈为空时抛出异常 + try { + ms.pop(); + } catch (RuntimeException e) { + e.printStackTrace(); + } + + // 压入数据 + ms.push(9); + ms.push(8); + ms.push(7); + + // 查看栈顶元素,打印结果为 7 + System.out.println(ms.peek()); + + // 取出栈顶元素,打印结果为 7 + System.out.println(ms.pop()); + + // 再次查看栈顶元素,打印结果为 8 + System.out.println(ms.peek()); + + // 判断栈是否为空,打印结果为 false + System.out.println(ms.isEmpty()); + + // 取出栈顶元素,打印结果为 8 + System.out.println(ms.pop()); + // 打印结果为 9 + System.out.println(ms.pop()); + + // 判断栈是否为空,打印结果为 true + System.out.println(ms.isEmpty()); + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestNode.java b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestNode.java new file mode 100644 index 0000000..9a1baf8 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo2/test/TestNode.java @@ -0,0 +1,47 @@ +package demo2.test; + +import demo2.Node; + +/** + * 测试单链表 + * + * @author admin + */ +public class TestNode { + public static void main(String[] args) { + // 创建节点 + Node n1 = new Node(1); + Node n2 = new Node(2); + Node n3 = new Node(3); + // 追加节点 + n1.append(n2).append(n3).append(new Node(4)); + // 获取后继节点,打印结果为 3 + System.out.println(n1.next().next().getData()); + // 判断节点是否为最后一个节点,打印结果为 false + System.out.println(n1.isLast()); + // 打印结果为 true + System.out.println(n1.next().next().next().isLast()); + + // 显示已有节点,打印结果 1 2 3 4 + n1.show(); + // 删除 n3 + n1.next().removeNext(); + // 显示删除后剩余的节点,打印结果 1 2 4 + n1.show(); + + // 创建一个新节点 + Node node = new Node(3); + // 将新节点插入 n2 之后 + n1.next().after(node); + // 重新显示所有节点,打印结果 1 2 3 4 + n1.show(); + + // 再来一次 + // 创建一个新节点 + node = new Node(5); + // 将新节点插入 n2 之后 + n1.next().after(node); + // 重新显示所有节点,打印结果 1 2 5 3 4 + n1.show(); + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo3/TestFibonacci.java b/codes/java_dataStructure_luozhaoyong/src/demo3/TestFibonacci.java new file mode 100644 index 0000000..8412e61 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo3/TestFibonacci.java @@ -0,0 +1,33 @@ +package demo3; + +/** + * 测试斐波那契数列 + * @author admin + */ +public class TestFibonacci { + public static void main(String[] args) { + // 斐波那契数列 1 1 2 3 5 8 13 + int i = fibonacci(3); + // 打印结果为 2 + System.out.println(i); + + i = fibonacci(6); + // 打印结果为 8 + System.out.println(i); + } + + /** + * 斐波那契数列求值函数 + * @param i + * @return + */ + public static int fibonacci(int i) { + // 递归函数停止条件,当 i 等于 1 或者 2 时返回数字 1 + if (i == 1 || i == 2) { + return 1; + } + // 其他情况递归调用当前函数 + // 即第 i 项等于前两项之和 + return fibonacci(i - 1) + fibonacci(i - 2); + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo3/TestHanoi.java b/codes/java_dataStructure_luozhaoyong/src/demo3/TestHanoi.java new file mode 100644 index 0000000..5b07590 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo3/TestHanoi.java @@ -0,0 +1,53 @@ +package demo3; + +/** + * 测试汉诺塔 + * @author admin + */ +public class TestHanoi { + public static void main(String[] args) { + hanoi(1, 'A', 'B', 'C'); + System.out.println(); + + hanoi(2, 'A', 'B', 'C'); + System.out.println(); + + hanoi(3, 'A', 'B', 'C'); + System.out.println(); + + hanoi(4, 'A', 'B', 'C'); + } + + /** + * 共有 n 个盘子 + * 将上面的 n - 1 个盘子视为 1 个整体 + * 最底下的 1 个盘子视为 1 个整体 + * 3 根柱子中的空闲柱子作为中转 + * 当 n>=3 时,每次递归都将问题转化为 2 个盘子的情况 + * + * @param n 盘子总数 + * @param from 第一根柱子 + * @param in 中间的柱子 + * @param to 最后一根柱子 + */ + public static void hanoi(int n, char from, char in, char to) { + // 只有一个盘子的情况 + if (n == 1) { + // 直接将当前盘子移动到目标位置 + System.out.println("第 1 个盘子从 " + from + " 移动到 " + to); + + // 其他情况都转换成处理 2 个盘子的汉诺塔问题 + } else { + // 将上面的 n-1 个盘子视为 1 个整体,从原位置 from 移动到中间位置 in + // to 此时为空,作为中转的柱子 + hanoi(n - 1, from, to, in); + + // 再将最底下的 1 个盘子,从原位置 from 移动到最终的目标位置 to + System.out.println("第 " + n + " 个盘子从 " + from + " 移动到 " + to); + + // 最后将放在中间位置 in 的盘子,也移动到目标位置 to + // from 此时为空,作为中转的柱子 + hanoi(n - 1, in, from, to); + } + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo3/TestRecursive.java b/codes/java_dataStructure_luozhaoyong/src/demo3/TestRecursive.java new file mode 100644 index 0000000..3977665 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo3/TestRecursive.java @@ -0,0 +1,23 @@ +package demo3; + +/** + * 测试递归 + * @author admin + */ +public class TestRecursive { + public static void main(String[] args) { + // 调用递归函数 + print(3); + } + + /** + * 递归打印 + * @param i + */ + public static void print(int i) { + if (i > 0) { + System.out.println(i); + print(i - 1); + } + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/BubbleSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/BubbleSort.java new file mode 100644 index 0000000..20110c9 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo4/BubbleSort.java @@ -0,0 +1,60 @@ +package demo4; + +import java.util.Arrays; + +/** + * 冒泡排序 + *
+ * 多次遍历数组 + * 每次逐个比较相邻两个元素 + * 如果没有按照指定顺序排列,就互换元素 + * 直到遍历结束或者全部有序为止 + * + * @author admin + */ +public class BubbleSort { + public static void main(String[] args) { + int[] arr = new int[]{5, 7, 2, 9, 4, 1, 0, 5, 7}; + bubbleSort(arr); + System.out.println(Arrays.toString(arr)); + } + + /** + * 冒泡排序 + *
+ * 时间复杂度:O(n^2) + * 外循环执行了 n 次 + * 内循环每次都排除上一轮已排好序的末尾元素,因此每轮递减 1 + * (n-1) + (n-2) + ... 1 = (n-1+1)/2 = n/2 + * 外循环 * 内循环 = n*(n/2) = n^2/2 + * O(n^2/2) = O(n^2) + *
+ * 空间复杂度:O(1),没有使用额外空间 + */ + public static void bubbleSort(int[] arr) { + // 如果数组长度小于等于 1,不用排序 + if (arr.length <= 1) { + return; + } + // 临时变量,用于两数交换时做临时存储 + int temp; + for (int i = 0; i < arr.length - 1; i++) { + + // 每轮排序,最大的值都会排到末尾 + // i = 1 时,arr[arr.length-1-1] 已经在上一轮排好序了 + // i = 2 时,arr[arr.length-1-2] 已经在上一轮排好序了 + // 因此内循环控制变量 j 的值,最大应小于 arr.length - 1 - i + // 可以避免重复检查数组末尾已经排好序的部分 + for (int j = 0; j < arr.length - 1 - i; j++) { + if (arr[j] > arr[j + 1]) { + // 临时变量存储 arr[j] 的值 + temp = arr[j]; + // 将 arr[j+1] 的值赋给 arr[j] + arr[j] = arr[j + 1]; + // 将原 arr[j] 的值赋给 arr[j] + arr[j + 1] = temp; + } + } + } + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/HeapSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/HeapSort.java new file mode 100644 index 0000000..efc0194 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo4/HeapSort.java @@ -0,0 +1,95 @@ +package demo4; + +import java.util.Arrays; + +/** + * 堆排序 + *
+ * 假设有大小为 n 的顺序排列二叉树 + * 1. 首先将顺序排列二叉树调整为大顶堆 + * 2. 交换堆顶元素和最后一个叶子节点,即数组的第 0 个元素和第 n 个元素交换 + * 3. 数组第 n 个元素已经排好序,数组递减 1,对递减后的数组重复步骤 1~2 + * + * @author admin + */ +public class HeapSort { + + public static void main(String[] args) { + int[] arr = new int[]{9, 6, 8, 7, 0, 1, 10, 4, 2}; + heapSort(arr); + System.out.println(Arrays.toString(arr)); + } + + /** + * 堆排序方法 + * + * @param arr + */ + public static void heapSort(int[] arr) { + // 1. 获取最后一个非叶子节点下标 + // 最后一个叶子节点的下标为 arr.length - 1 + // 根据公式,最后一个叶子节点的父节点下标为 (arr.length - 1) / 2 + // 最后一个叶子节点的父节点,就是最后一个非叶子节点 + int start = (arr.length - 1) / 2; + // 2. 从最后一个非叶子节点开始,将整个顺序存储二叉树调整为大顶堆 + for (int i = start; i >= 0; i--) { + // 调用方法将当前位置 i 的子树调整为大顶堆 + maxHeap(arr, arr.length, i); + } + + // 3. 遍历数组,每轮都将大顶堆的堆顶移动到当前轮的最后 + for (int i = arr.length - 1; i > 0; i--) { + // 将堆顶元素 arr[0] 交换到数组当前的末尾位置 i + int temp = arr[0]; + arr[0] = arr[i]; + arr[i] = temp; + // 交换后堆顶的结构被破坏 + // 重新调用方法将堆顶调整为大顶堆 + maxHeap(arr, i, 0); + } + } + + /** + * 将顺序排列二叉树调整为大顶堆的方法 + * + * @param arr 数组 + * @param size 数组大小 + * @param index 要操作的节点在数组中 arr 中的下标 + */ + public static void maxHeap(int[] arr, int size, int index) { + // 1. 获取当前节点的左右子节点下标 + int leftNode = index * 2 + 1; + int rightNode = index * 2 + 2; + // 定义一个变量 max,用于存储节点中最大节点的下标 + // 初始值为当前元素下标 index + int max = index; + + // 2. 比较当前节点和左右子节点并找出最大值下标 + // 比较 max 节点和左子节点,左子节点下标 leftNode 要小于数组长度 + if (leftNode < size && arr[max] < arr[leftNode]) { + // 如果 leftNode 对应的值更大,将 leftNode 赋值给 max + max = leftNode; + } + + // 比较 max 节点和右子节点,右子节点下标 rightNode 要小于数组长度 + if (rightNode < size && arr[max] < arr[rightNode]) { + // 如果 rightNode 对应的值更大,将 rightNode 赋值给 max + max = rightNode; + } + + // 3. 如果最大值下标 max 与 当前元素下标不相等 + // 说明当前节点不是最大值,需要将最大值交换到当前节点的位置 + if (max != index) { + // 交换 max 位置和 index 位置的元素 + int temp = arr[max]; + arr[max] = arr[index]; + arr[index] = temp; + + // 4. 交换元素后,如果 max 位置的元素是非叶子节点 + // 需要重新调整它的结构,重新调用 maxHeap 方法 + maxHeap(arr, size, max); + } + + } + +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/InsertSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/InsertSort.java new file mode 100644 index 0000000..b59c1b1 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo4/InsertSort.java @@ -0,0 +1,67 @@ +package demo4; + +import java.util.Arrays; + +/** + * 插入排序 + *
+ * 从第一个元素开始,把数组分成有序和无序两部分 + * 每轮都从无序部分取出一个元素 + * 按照指定顺序插入有序部分 + * 重复上述步骤,有序部分不断向右扩大,直到所有元素排好序 + * + * @author admin + */ +public class InsertSort { + public static void main(String[] args) { + int[] arr = new int[]{5, 3, 2, 8, 5, 9, 1, 0}; + insertSort(arr); + System.out.println(Arrays.toString(arr)); + } + + /** + * 插入排序方法 + *
+ * 外循环执行了 n 次 + * 内循环每次都为插入元素,将有序部分的元素移动若干次 + * 最差情况依次执行了 1 次移动、2 次移动、3 次移动,n-1 次移动 + * 但是并非每次都要移动有序部分的所有元素 + * 均摊情况可以视为大致移动了一半的元素 + * 因此内均摊情况依次进行了 1/2 次移动、2/2 次移动、3/2 次移动、 (n-1)/2 次移动 + * 总共执行了 (1/2 + 2/2 + 3/2 + ... (n-1)/2) = (1/2 + (n-1)/2))/2 = n/4 次移动 + * 所以总的时间复杂度是 + * 外循环执行次数 * 内循环时间复杂度 = n * n/4 = n^2/4 + * O(n^2/4) = O(n^2) + * + * @param arr 待排序的数组 + */ + public static void insertSort(int[] arr) { + if (arr.length <= 1) { + return; + } + + // 临时变量,用于存储当前元素的值 + int temp; + // 从下标 1,即第 2 个元素开始遍历 + for (int i = 1; i < arr.length; i++) { + // 将当前元素 arr[i] 的值赋给临时变量 temp + temp = arr[i]; + // 内循环控制变量 j 从 i 的前一个元素开始 + // 满足条件 j >=0 保证数组不越界 + // 同时满足 temp 比内循环当前元素 arr[j] 小 + int j; + for (j = i - 1; j >= 0 && temp < arr[j]; j--) { + // 将当前元素的值赋给后一个元素 + // 即所有比 temp 大的元素都不断后移 + // 直至找到比 temp 小的元素为止 + arr[j + 1] = arr[j]; + } + // 循环结束时,arr[j] < temp + // 此时 arr[j+1] 已经腾出了空间 + // 将 temp 值插入 arr[j + 1] 的位置 + // 满足条件 arr[j] < arr[j+1] = temp < arr[j+2] + arr[j + 1] = temp; + } + + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/MergeSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/MergeSort.java new file mode 100644 index 0000000..394ff98 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo4/MergeSort.java @@ -0,0 +1,115 @@ +package demo4; + +import java.util.Arrays; + +/** + * 归并排序 + *
+ * 将数组分为两部分 + * 对每部分都递归使用归并排序方法 + * 两部分排好序后 + * 再将数组的两部分合并到一起 + * + * @author admin + */ +public class MergeSort { + public static void main(String[] args) { + int[] arr = new int[]{1, 3, 5, 2, 4, 6, 8, 10}; + mergeSort(arr, 0, arr.length - 1); + System.out.println(Arrays.toString(arr)); + } + + /** + * 归并排序方法 + * 将原数组折半划分为两部分 + * 依次对两部分递归调用递归算法 + * 直到数组不可再分 + * 对排好序的两部分调用归并方法合并为一个数组 + *
+ * 时间复杂度: + * 每轮都将数组折半,直到不可再分,总共是 logN 轮 + * 每一轮的合并方法最多执行 n 次循环 + * 总共的时间复杂度是 O(NlogN) + * + * @param arr 待排序数组 + * @param low 要排序部分的起始位置 + * @param high 要排序部分的结束位置 + */ + public static void mergeSort(int[] arr, int low, int high) { + // 如果起始位置不小于结束位置,结束排序 + if (low >= high) { + return; + } + // 获取中间位置 + int middle = low + (high - low) / 2; + // 为左半部分数组排序 + mergeSort(arr, low, middle); + // 为右半部分数组排序 + mergeSort(arr, middle + 1, high); + // 将排好序的两部分数组合并 + merge(arr, low, middle, high); + } + + /** + * 归并数组的合并方法 + *
+ * 原数组已经被分为两部分,每部分都各自有序 + * 创建一个与原数组等长的临时数组 + * 依次从两部分中取出元素进行对比,按照顺序放入临时数组 + * 所有元素都放入新数组后,整个数组已经排好序 + * 将临时数组重新赋值给原有数组 + * + * @param arr + * @param low + * @param middle + * @param high + */ + public static void merge(int[] arr, int low, int middle, int high) { + // 创建一个新数组,用于存储合并后的元素 + int[] temp = new int[high - low + 1]; + // 临时变量 i 和 j 分别指向两部分数组的起始位置 + // 第一部分数组从 low 开始 + int i = low; + // 第二部分数组从 middle + 1开始 + int j = middle + 1; + + // 定义一个下标用于遍历新数组 + int index = 0; + // 遍历原数组的两部分 + while (i <= middle && j <= high) { + // 归并排序的条件之一就是要合并的两部分数组是各自排好序的 + // 即数组两部分满足 arr[i] <= arr[i+1] 和 arr[j] <= arr[j+1] + // 当 arr[i] <= arr[j] 时,将较小的 arr[i] 放入新数组后 + // 继续向后遍历,数组两部分都不会出现比 arr[i] 更小的数字 + // 同理,如果 arr[j] 较小,继续遍历也不会出现比 arr[j] 更小的数字 + // 所以,这种方式排列出的新数组是有序的 + // 通过比较,将 arr[i] 和 arr[j] 中较小的数字放入新数组 + if (arr[i] <= arr[j]) { + // arr[i] 放入新数组 index 位置后 + // index 和 i 都要递增 + temp[index++] = arr[i++]; + // 上述写法是简便写法,等价于下面的写法 + // newArr[index] = arr[i]; + // index++; + // i++; + } else { + // 同理,将 arr[j] 放入新数组后 + // index 和 j 都递增 + temp[index++] = arr[j++]; + } + } + // 上一个循环结束时,可能会出现 i 或 j 没有遍历到各自结尾的情况 + // 将没有被遍历到的部分依次放入新数组 + while (i <= middle) { + temp[index++] = arr[i++]; + } + while (j <= high) { + temp[index++] = arr[j++]; + } + + // 将合并好的新数组元素,逐个赋值给原数组对应的位置 + for (int k = 0; k < temp.length; k++) { + arr[low + k] = temp[k]; + } + } +} diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/QuickSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/QuickSort.java new file mode 100644 index 0000000..5f8fd10 --- /dev/null +++ b/codes/java_dataStructure_luozhaoyong/src/demo4/QuickSort.java @@ -0,0 +1,90 @@ +package demo4; + +import java.util.Arrays; + +/** + * 快速排序 + *
+ * 1) 从数组中找出一个基准数 + * 2) 数组定义左右两个指针分别向中间移动 + * 3) 数组左侧的值比基准值大,则移到数组右侧 + * 4) 数组右侧的值比基准值小,则移到数组左侧 + * 5) 当左右两个指针重合时,当前轮排序结束 + * 6) 指针重合的位置将数组分为两部分,分别对两部分递归调用快速排序 + * 7) 重复上述步骤,直到排序完成 + * + * @author admin + */ +public class QuickSort { + public static void main(String[] args) { + // 创建数组 + int[] arr = new int[]{3, 4, 6, 7, 2, 7, 2, 8, 0, 9, 1}; + // 调用快速排序方法 + quickSort(arr, 0, arr.length - 1); + // 打印结果 + System.out.println(Arrays.toString(arr)); + } + + /** + * 时间复杂度:O(NlogN) + * 每一轮都将数组从头到尾遍历和交换,所以每轮的时间复杂度为 O(N) + * 每轮结束时,都将数组分为左右两半,再分别递归 + * 即第一轮 n/2 + * 第二轮 n/2/2 + * 直到不能再分 + * 总共进行了 logN 次减半再分别递归的操作 + * 所以时间复杂度为 O(Nlog(N)) + *
+ * 快速排序
+ *
+ * @param arr 要排序的数组
+ * @param start 起始位置
+ * @param end 结束位置
+ */
+ public static void quickSort(int[] arr, int start, int end) {
+ // 如果起始位置大于或等于结束位置,结束当前方法
+ if (start >= end) {
+ return;
+ }
+
+ // 将数组中第 0 个位置的数字作为基准值
+ int stard = arr[start];
+ // 定义一个指针 low,从起始位置向结束位置移动
+ int low = start;
+ // 定义一个指针 high,从结束位置向起始位置移动
+ int high = end;
+
+ // 当 low 指针小于 high 指针时
+ while (low < high) {
+ // 从结束位置遍历
+ // 如果右侧的值大于等于基准值,符合较大的值在基准值右侧的条件
+ // 则将指针 high 递减,即向左移动
+ while (low < high && arr[high] >= stard) {
+ high--;
+ }
+ // 循环结束时,说明出现了 arr[high]
+ * 思路:
+ * 第一轮按照所有元素的个位数字为所有元素排序
+ * 第二轮按照所有元素的十位数字为所有元素排序
+ * 以此类推
+ * 当按照数组中元素的最大位数排序之后,最终得到 1 个有序的数组
+ *
+ * 例如数组 [5, 1, 72, 36, 101]
+ * 为便于理解,想象元素空缺的位数上都是 0
+ * 把数组写成如下形式
+ * 排序前原始数组 [005, 001, 072, 036, 101]
+ *
+ * 第一轮排序得到 [001, 101, 072, 005, 036]
+ * 第一轮排序得到 [001, 101, 005, 036, 072]
+ * 第一轮排序得到 [001, 005, 036, 072, 101]
+ * 每次按照排序后,位数相同的数字,相对顺序不会改变
+ * 如第一次按照个位排序后,两个个位数字 1 和 5
+ * 1 在接下来的几轮排序后,总是位于 5 的前面
+ * 所有排序结束后,就得到了按照数字整体大小排列的数组
+ *
+ *
+ * 具体操作:
+ * 1. 为自然数 0 ~ 9 中的每个数字创建 1 个桶,总共 10 个
+ *
+ * 2. 第一轮获取每个元素的个位数字,把元素放入与个位数字对应的桶中
+ * 所有元素都入桶后,依次从桶中取出元素
+ * 先去标号为 0 的桶中的第 1 个数字,再取第 2 个数字
+ * 标号为 0 的桶取完之后,再从标号为 1 的桶取数字,以此类推
+ * 按照上述顺序取出的数字,依次存入原数组第 0 个位置,第 1 个位置...
+ * 装满原数组后,原数组就变成了一个按照个位数字排好序的数组
+ *
+ * 3. 第二轮获取每个元素的十位数字
+ * 按照第二个步骤的方法操作,得到一个按十位数字排好序的数组
+ *
+ * 4. 重复以上步骤,直到按照最大的位数排好序
+ * 整个数组就是有序的数组
+ *
+ * @author admin
+ */
+public class RadixQueueSort {
+ public static void main(String[] args) {
+ int[] arr = new int[]{23, 6, 189, 45, 9, 287, 56, 1, 798, 34, 65, 652, 5};
+ radixSort(arr);
+ System.out.println(Arrays.toString(arr));
+ }
+
+ /**
+ * 基数排序方法
+ *
+ * 时间复杂度:
+ * 假设最大数的位数为 k,总共执行 k 轮比较
+ * 每轮比较都遍历一次数组,时间复杂度为 n
+ * 总的时间复杂度是 O(kn)
+ *
+ * @param arr 待排序的数组
+ */
+ public static void radixSort(int[] arr) {
+ // 长度小于等于 1 的时候直接返回
+ if (arr.length <= 1) {
+ return;
+ }
+ // 1. 计算数组中最大数的位数
+ // 定义一个临时遍历 max 用于获取数组中最大的数
+ int max = Integer.MIN_VALUE;
+ // 遍历数组,找到最大的数字
+ for (int i = 0; i < arr.length; i++) {
+ if (arr[i] > max) {
+ max = arr[i];
+ }
+ }
+ // 获取最大数字的位数
+ int maxLength = (max + "").length();
+
+ // 2. 定义存放元素的桶
+ // 定义一个队列数组,数组长度为 10,表示 0~9 数字对应的 10 个桶
+ // 每个桶都是一个先进先出的队列
+ MyQueue[] temp = new MyQueue[10];
+ // 遍历队列数组
+ for (int i = 0; i < temp.length; i++) {
+ // 数组中每个元素赋值为一个新的队列对象
+ temp[i] = new MyQueue();
+ }
+
+ // 3. 遍历数组,按照每个元素各个位上的数字为数组进行多轮排序
+ // 定义进位基数 10
+ int scale = 10;
+
+ // 数组中最大数字的位数是 maxLength,外循环总共循环 maxLength 轮
+ // 另外定义一个除数 n,用来获取数字上每一位的数字
+ // n 的初始值是 1,即取个位上的数
+ // 每一轮结束都递乘 10,即第二轮 n = 10,获取十位上的数字,第三轮 n = 100,以此类推
+ for (int i = 1, n = 1; i <= maxLength; i++, n *= scale) {
+ // 内循环遍历数组
+ for (int j = 0; j < arr.length; j++) {
+ // 获取当前下标 j 在原数组中对应的元素
+ int num = arr[j];
+ // 计算元素在当前位上的余数
+ // 第一轮,i=1, n = 1,((num / 1) % 10) 得到个位上的数字
+ // 第二轮,i=2, n = 10,((num / 10) % 10) 得到十位上的数字
+ // 依次类推
+ int remainder = (num / n) % 10;
+ // 通过余数 remainder 获取对应数字的桶
+ MyQueue bucket = temp[remainder];
+ // 将当前元素存入桶中
+ bucket.add(num);
+ }
+
+ // 记录原数组的下标变化,从桶中取出元素放回原数组时,下标递增
+ int index = 0;
+ // 遍历队列数组
+ for (int k = 0; k < temp.length; k++) {
+ // 通过 k 获取对应的桶
+ MyQueue bucket = temp[k];
+ // 只要桶不为空,就继续遍历
+ while (!bucket.isEmpty()) {
+ // 桶中的元素出列,放入原数组,同时原数组下标 index 递增
+ arr[index++] = bucket.poll();
+ }
+ }
+ System.out.println(Arrays.toString(arr));
+
+ }
+ }
+
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/RadixSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/RadixSort.java
new file mode 100644
index 0000000..a09eaaa
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo4/RadixSort.java
@@ -0,0 +1,138 @@
+package demo4;
+
+import java.util.Arrays;
+
+/**
+ * 基数排序
+ *
+ * 思路:
+ * 第一轮按所有元素的个位数字排序
+ * 第二轮按所有元素的十位数字排序
+ * 以此类推
+ * 当按照数组中元素的最大位数排序之后,最终得到 1 个有序的数组
+ *
+ * 例如数组 [5, 1, 72, 36, 101]
+ * 为便于理解,想象元素空缺的位数上都是 0
+ * 把数组写成如下形式
+ * 排序前原始数组 [005, 001, 072, 036, 101]
+ *
+ * 第一轮按个位排序得到 [001, 101, 072, 005, 036]
+ * 第二轮按十位排序得到 [001, 101, 005, 036, 072]
+ * 第三轮按百位排序得到 [001, 005, 036, 072, 101]
+ * 每轮排序后,位数相同的数字,相对顺序不会改变
+ * 如第一次按照个位排序后,两个个位数字 1 和 5
+ * 1 在接下来的几轮排序过程中,总是位于 5 的前面
+ * 所有排序结束后,就得到了按照数字整体大小排列的数组
+ *
+ *
+ * 具体操作:
+ * 1. 为自然数 0 ~ 9 中的每个数字创建 1 个桶,总共 10 个
+ *
+ * 2. 第一轮获取每个元素的个位数字,把元素放入与个位数字对应的桶中
+ * 所有元素都入桶后,依次从桶中取出元素
+ * 先取标号为 0 的桶中的第 1 个数字,再取第 2 个数字 ...
+ * 标号为 0 的桶取完之后,再从标号为 1 的桶取数字,以此类推
+ * 按照上述顺序取出的数字,依次存入原数组第 0 个位置,第 1 个位置 ...
+ * 装满原数组后,原数组就变成了一个按照个位数字排好序的数组
+ *
+ * 3. 第二轮获取每个元素的十位数字
+ * 按照第二个步骤的方法操作,得到一个按十位数字排好序的数组
+ *
+ * 4. 重复以上步骤,直到按照最大的位数排好序
+ * 整个数组就是有序的数组
+ *
+ * @author admin
+ */
+public class RadixSort {
+ public static void main(String[] args) {
+ int[] arr = new int[]{23, 6, 189, 45, 9, 287, 56, 1, 798, 34, 65, 652, 5};
+ radixSort(arr);
+ System.out.println(Arrays.toString(arr));
+ }
+
+ /**
+ * 基数排序方法
+ *
+ * 时间复杂度:
+ * 假设最大数的位数为 k,总共执行 k 轮比较
+ * 每轮比较都遍历一次数组,时间复杂度为 n
+ * 总的时间复杂度是 O(kn)
+ *
+ * @param arr
+ */
+ public static void radixSort(int[] arr) {
+ // 长度小于等于 1 的时候直接返回
+ if (arr.length <= 1) {
+ return;
+ }
+ // 1. 计算数组中最大数的位数
+ // 定义一个临时变量 max 用于获取数组中最大的数
+ int max = Integer.MIN_VALUE;
+ // 遍历数组,找到最大的数字
+ for (int i = 0; i < arr.length; i++) {
+ if (arr[i] > max) {
+ max = arr[i];
+ }
+ }
+ // 获取最大数字的位数
+ int maxLength = (max + "").length();
+
+ // 2. 定义一个 10 行 arr.length 列的二维数组
+ // 行数为 10,表示 0~9 数字对应的 10 个桶
+ // 列数为 arr.length,考虑到所有元素都在同一个桶中的极端情况
+ // 每个桶的容量都需要与数组的长度相等
+ int[][] temp = new int[10][arr.length];
+
+ // 定义一个用于计数的数组
+ // 数组中每个元素的数值,代表对应的桶中有多少个元素
+ int[] count = new int[10];
+
+ // 3. 遍历数组,按照每个元素各个位上的数字为数组进行多轮排序
+ // 定义进位基数 10
+ int scale = 10;
+ // 数组中最大数字的位数是 maxLength,外循环总共循环 maxLength 轮
+ // 另外定义一个除数 n,用来获取数字上每一位的数字
+ // n 的初始值是 1,即取个位上的数
+ // 每一轮结束都递乘 10,即第二轮 n = 10,获取十位上的数字,第三轮 n = 100,以此类推
+ for (int i = 0, n = 1; i < maxLength; i++, n *= scale) {
+
+ // 内循环遍历数组
+ for (int j = 0; j < arr.length; j++) {
+ // 获取当前下标 j 在原数组中对应的元素
+ int num = arr[j];
+ // 计算元素在当前位上的余数
+ // 第一轮,i=1, n = 1,((num / 1) % 10) 得到个位上的数字
+ // 第二轮,i=2, n = 10,((num / 10) % 10) 得到十位上的数字
+ // 以此类推
+ int remainder = (num / n) % 10;
+
+ // 通过余数 remainder 获取对应数字的桶 temp[remainder]
+ // 向桶中添加当前元素,同时桶对应的计数器 count[remainder] 递增
+ temp[remainder][count[remainder]++] = num;
+ }
+
+ // 记录原数组的下标变化,从桶中取出元素放回原数组时,下标递增
+ int index = 0;
+ // 遍历计数器数组
+ for (int k = 0; k < count.length; k++) {
+ // 获取 k 值对应的桶中有多少个元素
+ int volume = count[k];
+ // 只要计数器不为 0,说明桶中还有元素
+ if (volume > 0) {
+ // 获取 k 值对应的桶
+ int[] bucket = temp[k];
+ // 桶内有 volume 个元素,则 l 正好对应下标 0 ~ volume-1
+ for (int l = 0; l < volume; l++) {
+ // 通过下标 l 获取桶内的元素 bucket[l]
+ // 将桶内元素 bucket[l] 赋值给原数组相应的位置
+ arr[index++] = bucket[l];
+ // index++ 指针指向下一个位置
+ }
+ // 循环结束后,将当前桶的计数器清零
+ count[k] = 0;
+ }
+ }
+ }
+ }
+
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/SelectionSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/SelectionSort.java
new file mode 100644
index 0000000..7cce7db
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo4/SelectionSort.java
@@ -0,0 +1,60 @@
+package demo4;
+
+import java.util.Arrays;
+
+/**
+ * 选择排序
+ *
+ * 将数组看作有序和无序两部分
+ * 每次都从无序部分找出最小的元素,与无序部分的第一个元素交换位置
+ * 直到数组完全排序为止
+ *
+ * @author admin
+ */
+public class SelectionSort {
+ public static void main(String[] args) {
+ int[] arr = new int[]{3, 4, 5, 7, 1, 2, 0, 3, 6, 8};
+ selectionSort(arr);
+ System.out.println(Arrays.toString(arr));
+ }
+
+ /**
+ * 选择排序方法
+ * 时间复杂度:
+ * 内循环每次都会从无序部分找出最小的元素
+ * 依次比较了 n-1 次,n-2 次,n-3 次 ... 1 次
+ * 总共比较的次数是 (n-1) + (n-2) + ...+ 1 = (n-1 + 1) /2 = n/2 次
+ * 外循环执行了 n 次,总共的时间复杂度是 O(n*n/2) = O(n^2/2) = O(n^2)
+ *
+ * @param arr
+ */
+ public static void selectionSort(int[] arr) {
+ // 当数组元素小于等于 1 时,天然有序,无需进行排序
+ if (arr.length <= 1) {
+ return;
+ }
+ // 遍历数组
+ for (int i = 0; i < arr.length; i++) {
+ int minIndex = i;
+ for (int j = i + 1; j < arr.length; j++) {
+ // 如果内循环当前元素 arr[j] 比已知最小值还小
+ // 则将最小值下标 minIndex 替换为 j
+ if (arr[j] < arr[minIndex]) {
+ minIndex = j;
+ }
+ }
+ // 内循环结束时
+ // 未排序部分第一个元素是 arr[i]
+ // 未排序部分最小元素是 arr[minIndex]
+ // 如果 i 与 minIndex 不相等
+ // 则需要交换两者的值
+ // 让未排序部分的最小元素排到未排序部分的第一个元素位置
+ if (i != minIndex) {
+ // 交换两者的位置
+ int temp = arr[i];
+ arr[i] = arr[minIndex];
+ arr[minIndex] = temp;
+ }
+ }
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo4/ShellSort.java b/codes/java_dataStructure_luozhaoyong/src/demo4/ShellSort.java
new file mode 100644
index 0000000..3111795
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo4/ShellSort.java
@@ -0,0 +1,56 @@
+package demo4;
+
+import java.util.Arrays;
+
+/**
+ * 希尔排序
+ *
+ * 取某个数字作为步长,按步长对数组进行插入排序
+ * 排序完成后,步长按规律递减
+ * 用新步长进行下一轮插入排序
+ * 重复上述步骤,直到步长变成 1,进行最后一轮普通的插入排序为止
+ *
+ * @author admin
+ */
+public class ShellSort {
+ public static void main(String[] args) {
+ int[] arr = new int[]{3, 5, 2, 7, 8, 1, 2, 0, 4, 7, 4, 3, 8};
+ shellSort(arr);
+ System.out.println(Arrays.toString(arr));
+ }
+
+ /**
+ * 希尔排序方法
+ * 数组完全逆序时,接近插入排序的时间复杂度 O(n^2)
+ * 最优时间复杂度,约为 O(n^1.3)
+ *
+ * @param arr
+ */
+ public static void shellSort(int[] arr) {
+ // 用于记录当前排序次数,与主逻辑无关,仅用于打印结果
+ int k = 1;
+
+ // 除数设定为 2,每次步长都是上一次的 1/2
+ int divisor = 2;
+ // 遍历所有步长的情况
+ for (int d = arr.length / divisor; d > 0; d /= divisor) {
+ // 外循环控制变量 i 起始位置为 d
+ // d 是规定的步长,当 d ==1 时,就变成了插入排序
+ for (int i = d; i < arr.length; i++) {
+ // 内循环控制变量 j
+ for (int j = i - d; j >= 0; j -= d) {
+ // 如果 arr[j] 比更靠后的元素 arr[j+d] 大
+ // 则交换两者位置,保持前面数字更小的顺序
+ if (arr[j] > arr[j + d]) {
+ // 交换 arr[j] 和 arr[j+d] 的位置
+ int temp = arr[j];
+ arr[j] = arr[j + d];
+ arr[j + d] = temp;
+ }
+ }
+ }
+ System.out.println("第 " + k + " 次排序结果 " + Arrays.toString(arr));
+ k++;
+ }
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo5/BinaryTree.java b/codes/java_dataStructure_luozhaoyong/src/demo5/BinaryTree.java
new file mode 100644
index 0000000..39fc877
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo5/BinaryTree.java
@@ -0,0 +1,81 @@
+package demo5;
+
+/**
+ * 二叉树
+ * @author admin
+ */
+public class BinaryTree {
+ /**
+ * 根结点
+ */
+ TreeNode root;
+
+
+ /**
+ * 设置根结点
+ *
+ * @param node 节点参数
+ */
+ public void setRoot(TreeNode node) {
+ root = node;
+ }
+
+ /**
+ * 前序遍历
+ */
+ public void frontShow() {
+ if (root == null) {
+ System.out.println("树为空");
+ return;
+ }
+ // 调用根结点的前序遍历方法
+ root.frontShow();
+ // 打印一个空行,与主逻辑无关
+ System.out.println();
+ }
+
+ /**
+ * 中序遍历
+ */
+ public void midShow() {
+ if (root == null) {
+ return;
+ }
+ root.midShow();
+ System.out.println();
+ }
+
+ /**
+ * 后序遍历
+ */
+ public void afterShow() {
+ if (root == null) {
+ return;
+ }
+ root.afterShow();
+ System.out.println();
+ }
+
+ /**
+ * 前序查找
+ *
+ * @param i
+ * @return
+ */
+ public TreeNode frontSearch(int i) {
+ return root.frontSearch(i);
+ }
+
+ /**
+ * 删除方法
+ *
+ * @param i
+ */
+ public void delete(int i) {
+ if (root.value == i) {
+ root = null;
+ return;
+ }
+ root.delete(i);
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo5/TestBinaryTree.java b/codes/java_dataStructure_luozhaoyong/src/demo5/TestBinaryTree.java
new file mode 100644
index 0000000..e008d7c
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo5/TestBinaryTree.java
@@ -0,0 +1,58 @@
+package demo5;
+
+/**
+ * 测试二叉树
+ * @author admin
+ */
+public class TestBinaryTree {
+ public static void main(String[] args) {
+ /* 第 30 课,创建二叉树*/
+ // 创建一棵二叉树
+ BinaryTree binTree = new BinaryTree();
+
+ // 创建一个节点作为根结点
+ TreeNode root = new TreeNode(1);
+ // 设置根结点
+ binTree.setRoot(root);
+
+ // 创建一个左节点
+ TreeNode leftNode = new TreeNode(2);
+ // 设置左节点
+ root.setLeftNode(leftNode);
+
+ // 创建一个右节点
+ TreeNode rightNode = new TreeNode(3);
+ // 设置右节点
+ root.setRightNode(rightNode);
+
+ /* 第 31 课,遍历二叉树*/
+
+ // 为第二层的左节点创建左右两个子节点
+ leftNode.setLeftNode(new TreeNode(4));
+ leftNode.setRightNode(new TreeNode(5));
+
+ // 为第二层的右节点创建左右两个子节点
+ rightNode.setLeftNode(new TreeNode(6));
+ rightNode.setRightNode(new TreeNode(7));
+
+ // 调用前序遍历方法
+ binTree.frontShow();
+
+ // 调用中序遍历方法
+ binTree.midShow();
+
+ // 调用后序遍历方法
+ binTree.afterShow();
+
+ // 调用前序查找方法,查找节点值为 2 的节点
+ TreeNode result = binTree.frontSearch(2);
+ // 检查当前结果是否为根结点的左子节点
+ System.out.println(result == leftNode);
+
+ // 测试删除节点的方法
+ binTree.delete(5);
+ // 前序遍历显示节点是否被删除
+ // 打印结果是 1 2 4 3 6 7
+ binTree.frontShow();
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo5/TreeNode.java b/codes/java_dataStructure_luozhaoyong/src/demo5/TreeNode.java
new file mode 100644
index 0000000..2fa8943
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo5/TreeNode.java
@@ -0,0 +1,162 @@
+package demo5;
+
+/**
+ * 二叉树节点
+ * @author admin
+ */
+public class TreeNode {
+ /**
+ * 节点的权值
+ */
+ int value;
+ /**
+ * 左节点
+ */
+ TreeNode leftNode;
+ /**
+ * 右节点
+ */
+ TreeNode rightNode;
+
+ /**
+ * 构造方法
+ *
+ * @param value 权值参数
+ */
+ public TreeNode(int value) {
+ this.value = value;
+ }
+
+ public void setLeftNode(TreeNode node) {
+ leftNode = node;
+ }
+
+ public void setRightNode(TreeNode node) {
+ rightNode = node;
+ }
+
+ /**
+ * 前序遍历
+ *
+ * 当前节点-->左子节点-->右子节点
+ */
+ public void frontShow() {
+ // 获取当前节点的值
+ System.out.print(value + " ");
+ // 获取左子节点的值
+ if (leftNode != null) {
+ leftNode.frontShow();
+ }
+ // 获取右子节点的值
+ if (rightNode != null) {
+ rightNode.frontShow();
+ }
+ }
+
+ /**
+ * 中序遍历
+ *
+ * 左子节点-->当前节点-->右子节点
+ */
+ public void midShow() {
+ // 获取左子节点的值
+ if (leftNode != null) {
+ leftNode.midShow();
+ }
+
+ // 获取当前节点的值
+ System.out.print(value + " ");
+
+ // 获取右子节点的值
+ if (rightNode != null) {
+ rightNode.midShow();
+ }
+ }
+
+ /**
+ * 后序遍历
+ *
+ * 左子节点-->右子节点-->当前节点
+ */
+ public void afterShow() {
+ // 获取左子节点的值
+ if (leftNode != null) {
+ leftNode.afterShow();
+ }
+
+ // 获取右子节点的值
+ if (rightNode != null) {
+ rightNode.afterShow();
+ }
+
+ // 获取当前节点的值
+ System.out.print(value + " ");
+ }
+
+ /**
+ * 前序查找
+ *
+ * @return
+ */
+ public TreeNode frontSearch(int i) {
+ // 定义一个变量作为返回值
+ TreeNode target = null;
+ // 查看当前值是否与目标值相等
+ if (value == i) {
+ return this;
+ }
+ // 如果左子节点不为空
+ if (leftNode != null) {
+ // 在左子节点递归调用当前查找方法
+ target = leftNode.frontSearch(i);
+ }
+ // 如果左子节点查找结果不为空
+ if (target != null) {
+ // 返回结果
+ return target;
+ }
+ // 如果右子节点不为空
+ if (rightNode != null) {
+ // 在右子节点递归调用当前查找方法
+ target = rightNode.frontSearch(i);
+ }
+ // 返回目标结果
+ return target;
+ }
+
+ /**
+ * 递归删除子树
+ *
+ * @param i
+ */
+ public void delete(int i) {
+ // 将当前节点作为父节点赋值给变量 parent
+ TreeNode parent = this;
+ // 左子节点的值等于指定值,则删除左子节点
+ if (parent.leftNode != null && parent.leftNode.value == i) {
+ // 将左子节点赋值为空,即删除了左子节点
+ parent.leftNode = null;
+ return;
+ }
+ // 右子节点的值等于指定值,则删除左子节点
+ if (parent.rightNode != null && parent.rightNode.value == i) {
+ // 将右子节点赋值为空,即删除了左子节点
+ parent.rightNode = null;
+ return;
+ }
+ // 将左子节点赋值给父节点变量
+ parent = leftNode;
+ // 如果节点不为空
+ if (parent != null) {
+ // 递归调用删除方法
+ parent.delete(i);
+ }
+ // 将右子节点赋值给父节点变量
+ parent = rightNode;
+ // 如果节点不为空
+ if (parent != null) {
+ // 递归调用删除方法
+ parent.delete(i);
+ }
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo6/ArrayBinaryTree.java b/codes/java_dataStructure_luozhaoyong/src/demo6/ArrayBinaryTree.java
new file mode 100644
index 0000000..7e30868
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo6/ArrayBinaryTree.java
@@ -0,0 +1,58 @@
+package demo6;
+
+/**
+ * 顺序存储二叉树
+ *
+ * @author admin
+ */
+public class ArrayBinaryTree {
+ /**
+ * 数据以数组的形式来存储
+ */
+ int[] data;
+
+ /**
+ * 构造方法
+ *
+ * @param data 指定数组参数
+ */
+ public ArrayBinaryTree(int[] data) {
+ this.data = data;
+ }
+
+ /**
+ * 从根结点开始前序遍历
+ */
+ public void frontShow() {
+ // 传入根结点下标 0
+ frontShow(0);
+ }
+
+ /**
+ * 前序遍历
+ *
+ * @param index 起点的下标
+ */
+ public void frontShow(int index) {
+ // 检查边际条件
+ if (data == null || data.length == 0) {
+ return;
+ }
+ // 获取当前节点的值
+ System.out.print(data[index] + " ");
+ // 获取左子节点下标
+ int leftIndex = index * 2 + 1;
+ // 处理左子节点
+ if (leftIndex < data.length) {
+ // 左子节点递归调用前序遍历方法
+ frontShow(leftIndex);
+ }
+ // 获取右子节点下标
+ int rightIndex = index * 2 + 2;
+ // 处理右子节点
+ if (rightIndex < data.length) {
+ // 右子节点递归调用前序遍历方法
+ frontShow(rightIndex);
+ }
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo6/TestArrayBinaryTree.java b/codes/java_dataStructure_luozhaoyong/src/demo6/TestArrayBinaryTree.java
new file mode 100644
index 0000000..8d86292
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo6/TestArrayBinaryTree.java
@@ -0,0 +1,18 @@
+package demo6;
+
+/**
+ * 测试顺序存储二叉树
+ * @author admin
+ */
+public class TestArrayBinaryTree {
+ public static void main(String[] args) {
+ // 创建数组
+ int[] data = new int[]{1, 2, 3, 4, 5, 6, 7};
+ // 创建顺序存储二叉树对象
+ ArrayBinaryTree binTree = new ArrayBinaryTree(data);
+
+ // 调用前序遍历方法
+ // 打印结果是 1 2 4 5 3 6 7
+ binTree.frontShow();
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo7/TestThreadedBinaryTree.java b/codes/java_dataStructure_luozhaoyong/src/demo7/TestThreadedBinaryTree.java
new file mode 100644
index 0000000..96390cf
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo7/TestThreadedBinaryTree.java
@@ -0,0 +1,57 @@
+package demo7;
+
+
+/**
+ * 测试线索二叉树
+ * @author admin
+ */
+public class TestThreadedBinaryTree {
+ public static void main(String[] args) {
+ /* 第 30 课,创建二叉树*/
+ // 创建一棵二叉树
+ ThreadedBinaryTree binTree = new ThreadedBinaryTree();
+
+ // 创建一个节点作为根结点
+ ThreadedNode root = new ThreadedNode(1);
+ // 设置根结点
+ binTree.setRoot(root);
+
+ // 创建一个左节点
+ ThreadedNode leftNode = new ThreadedNode(2);
+ // 设置左节点
+ root.setLeftNode(leftNode);
+
+ /* 第 31 课,遍历二叉树*/
+ // 创建一个右节点
+ ThreadedNode rightNode = new ThreadedNode(3);
+ // 设置右节点
+ root.setRightNode(rightNode);
+
+ // 为第二层的左节点创建左右两个子节点
+ leftNode.setLeftNode(new ThreadedNode(4));
+ ThreadedNode fiveNode = new ThreadedNode(5);
+ leftNode.setRightNode(fiveNode);
+
+ // 为第二层的右节点创建左右两个子节点
+ rightNode.setLeftNode(new ThreadedNode(6));
+ rightNode.setRightNode(new ThreadedNode(7));
+
+ // 调用中序遍历方法
+ // 执行结果:4 2 5 1 6 3 7
+ binTree.midShow();
+
+ // 中序线索化二叉树
+ binTree.threadNodes();
+
+ // 找到节点 5 的后继节点
+ ThreadedNode afterFive = fiveNode.rightNode;
+ // 打印后继节点的值
+ // 执行结果为 1
+ System.out.println(afterFive.value);
+
+ // 线索化二叉树之后,遍历所有节点
+ // 执行结果:4 2 5 1 6 3 7
+ binTree.threadIterate();
+
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo7/ThreadedBinaryTree.java b/codes/java_dataStructure_luozhaoyong/src/demo7/ThreadedBinaryTree.java
new file mode 100644
index 0000000..8cb26ed
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo7/ThreadedBinaryTree.java
@@ -0,0 +1,169 @@
+package demo7;
+
+/**
+ * 线索二叉树
+ * @author admin
+ */
+public class ThreadedBinaryTree {
+ /**
+ * 根结点
+ */
+ ThreadedNode root;
+
+ /**
+ * 临时存储前驱节点
+ */
+ ThreadedNode pre;
+
+ /**
+ * 中序遍历线索化二叉树
+ */
+ public void threadIterate() {
+ // 定义临时变量 node 记录当前节点
+ ThreadedNode node = root;
+ // node 不为空时
+ while (node != null) {
+ // 1. 中序遍历,向左查找第一个被线索化的节点
+ // 跳过所有没有线索化的节点,即所有 leftType == 0 的节点
+ // 直至找到第一个线索化的节点,即 leftType == 1 的节点
+ while (node.leftType == 0) {
+ // node 指针前移
+ node = node.leftNode;
+ }
+
+ // 2. 通过线索化不断打印后继节点的值
+ // while 循环结束后, node 指向的节点就是当前第一个线索化的节点
+ // 打印节点的值
+ System.out.print(node.value + " ");
+
+ // 循环查找后继节点
+ while (node.rightType == 1) {
+ // 指针后移
+ node = node.rightNode;
+ // 打印后继节点的值
+ System.out.print(node.value + " ");
+ }
+ // 上个 while 循环结束后
+ // 当前有效范围内的所有线索化的节点都已经遍历过
+ // 3. 指针后移到右子节点,在下一个有效范围内查找线索化的节点
+ node = node.rightNode;
+ }
+ }
+
+ /**
+ * 设置根结点
+ *
+ * @param node 节点参数
+ */
+ public void setRoot(ThreadedNode node) {
+ root = node;
+ }
+
+ /**
+ * 对根结点应用线索化二叉树方法
+ */
+ public void threadNodes() {
+ threadNodes(root);
+ }
+
+ /**
+ * 中序遍历
+ * 线索化二叉树方法
+ *
+ * @param node
+ */
+ public void threadNodes(ThreadedNode node) {
+ // 如果节点为空
+ if (node == null) {
+ // 返回不做处理
+ return;
+ }
+
+ // 对左节点递归调用当前方法
+ threadNodes(node.leftNode);
+
+ // 对当前节点进行处理
+ // 如果左子树为空
+ if (node.leftNode == null) {
+ // 将左指针指向前驱节点
+ node.leftNode = pre;
+ // 改变标识,1 表示 leftNode 指向前驱节点
+ node.leftType = 1;
+ }
+
+ // 中序遍历时,pre 的后继节点就是当前节点
+ // 如果前驱节点的右子树为空
+ if (pre != null && pre.rightNode == null) {
+ // 将前驱节点的右指针指向当前节点
+ pre.rightNode = node;
+ // 改变标识,1 表示 rightNode 指向后继节点
+ pre.rightType = 1;
+ }
+
+ // 将当前节点的值赋给前驱节点变量 pre
+ pre = node;
+
+ // 对右节点递归调用当前方法
+ threadNodes(node.rightNode);
+ }
+
+
+ /**
+ * 前序遍历
+ */
+ public void frontShow() {
+ if (root == null) {
+ System.out.println("树为空");
+ return;
+ }
+ // 调用根结点的前序遍历方法
+ root.frontShow();
+ // 打印一个空行,与主逻辑无关
+ System.out.println();
+ }
+
+ /**
+ * 中序遍历
+ */
+ public void midShow() {
+ if (root == null) {
+ return;
+ }
+ root.midShow();
+ System.out.println();
+ }
+
+ /**
+ * 后序遍历
+ */
+ public void afterShow() {
+ if (root == null) {
+ return;
+ }
+ root.afterShow();
+ System.out.println();
+ }
+
+ /**
+ * 前序查找
+ *
+ * @param i
+ * @return
+ */
+ public ThreadedNode frontSearch(int i) {
+ return root.frontSearch(i);
+ }
+
+ /**
+ * 删除方法
+ *
+ * @param i
+ */
+ public void delete(int i) {
+ if (root.value == i) {
+ root = null;
+ return;
+ }
+ root.delete(i);
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo7/ThreadedNode.java b/codes/java_dataStructure_luozhaoyong/src/demo7/ThreadedNode.java
new file mode 100644
index 0000000..11bcb5d
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo7/ThreadedNode.java
@@ -0,0 +1,175 @@
+package demo7;
+
+/**
+ * 定义线索二叉树的节点
+ *
+ * @author admin
+ */
+public class ThreadedNode {
+ /**
+ * 节点的权值
+ */
+ int value;
+ /**
+ * 左节点
+ */
+ ThreadedNode leftNode;
+ /**
+ * 右节点
+ */
+ ThreadedNode rightNode;
+
+ /**
+ * 标识左指针类型
+ */
+ int leftType;
+
+ /**
+ * 标识右指针类型
+ */
+ int rightType;
+
+
+
+ /**
+ * 构造方法
+ *
+ * @param value 权值参数
+ */
+ public ThreadedNode(int value) {
+ this.value = value;
+ }
+
+ public void setLeftNode(ThreadedNode node) {
+ leftNode = node;
+ }
+
+ public void setRightNode(ThreadedNode node) {
+ rightNode = node;
+ }
+
+ /**
+ * 前序遍历
+ *
+ * 当前节点-->左子节点-->右子节点
+ */
+ public void frontShow() {
+ // 获取当前节点的值
+ System.out.print(value + " ");
+ // 获取左子节点的值
+ if (leftNode != null) {
+ leftNode.frontShow();
+ }
+ // 获取右子节点的值
+ if (rightNode != null) {
+ rightNode.frontShow();
+ }
+ }
+
+ /**
+ * 中序遍历
+ *
+ * 左子节点-->当前节点-->右子节点
+ */
+ public void midShow() {
+ // 获取左子节点的值
+ if (leftNode != null) {
+ leftNode.midShow();
+ }
+
+ // 获取当前节点的值
+ System.out.print(value + " ");
+
+ // 获取右子节点的值
+ if (rightNode != null) {
+ rightNode.midShow();
+ }
+ }
+
+ /**
+ * 后序遍历
+ *
+ * 左子节点-->右子节点-->当前节点
+ */
+ public void afterShow() {
+ // 获取左子节点的值
+ if (leftNode != null) {
+ leftNode.afterShow();
+ }
+
+ // 获取右子节点的值
+ if (rightNode != null) {
+ rightNode.afterShow();
+ }
+
+ // 获取当前节点的值
+ System.out.print(value + " ");
+ }
+
+ /**
+ * 前序查找
+ *
+ * @return
+ */
+ public ThreadedNode frontSearch(int i) {
+ // 定义一个变量作为返回值
+ ThreadedNode target = null;
+ // 查看当前值是否与目标值相等
+ if (value == i) {
+ return this;
+ }
+ // 如果左子节点不为空
+ if (leftNode != null) {
+ // 在左子节点递归调用当前查找方法
+ target = leftNode.frontSearch(i);
+ }
+ // 如果左子节点查找结果不为空
+ if (target != null) {
+ // 返回结果
+ return target;
+ }
+ // 如果右子节点不为空
+ if (rightNode != null) {
+ // 在右子节点递归调用当前查找方法
+ target = rightNode.frontSearch(i);
+ }
+ // 返回目标结果
+ return target;
+ }
+
+ /**
+ * 递归删除子树
+ *
+ * @param i
+ */
+ public void delete(int i) {
+ // 将当前节点作为父节点赋值给变量 parent
+ ThreadedNode parent = this;
+ // 左子节点的值等于指定值,则删除左子节点
+ if (parent.leftNode != null && parent.leftNode.value == i) {
+ // 将左子节点赋值为空,即删除了左子节点
+ parent.leftNode = null;
+ return;
+ }
+ // 右子节点的值等于指定值,则删除左子节点
+ if (parent.rightNode != null && parent.rightNode.value == i) {
+ // 将右子节点赋值为空,即删除了左子节点
+ parent.rightNode = null;
+ return;
+ }
+ // 将左子节点赋值给父节点变量
+ parent = leftNode;
+ // 如果节点不为空
+ if (parent != null) {
+ // 递归调用删除方法
+ parent.delete(i);
+ }
+ // 将右子节点赋值给父节点变量
+ parent = rightNode;
+ // 如果节点不为空
+ if (parent != null) {
+ // 递归调用删除方法
+ parent.delete(i);
+ }
+ }
+}
diff --git a/codes/java_dataStructure_luozhaoyong/src/demo9/Node.java b/codes/java_dataStructure_luozhaoyong/src/demo9/Node.java
new file mode 100644
index 0000000..c4050e9
--- /dev/null
+++ b/codes/java_dataStructure_luozhaoyong/src/demo9/Node.java
@@ -0,0 +1,48 @@
+package demo9;
+
+/**
+ * 定义赫夫曼树的节点
+ *
+ * @author admin
+ */
+public class Node implements Comparable
+ * 时间复杂度 O(n)
+ * 判断是否有环时,循环了n+k次,k是快指针比慢指针多跑的长度
+ * 查找环的入口时循环了s次,s是从头节点到环入口的距离
+ *
+ * 空间复杂度 O(1) 只使用了两个临时变量,空间复杂度为常数O(1)
+ *
+ * @param head
+ * @return
+ */
public ListNode detectCycle(ListNode head) {
- //快慢指针都从头结点出发
+ //快慢指针都从头节点出发
ListNode slow = head;
ListNode fast = head;
boolean hasCycle = false; //判断是否有环的标识
@@ -22,7 +34,7 @@
}
//如果有环,第二次循环找出环的入口
if (hasCycle) {
- //设从头结点到环入口的长度为len
+ //设从头节点到环入口的长度为len
//从环入口到快慢指针相遇点的距离为h
//环的长度为r
//fast和slow走过的相同路段为len+h
@@ -35,39 +47,39 @@
// len = m*r - h
// 将公式右边变化以后更好理解
// len = m*r - h = (m-1)*r + (r-h)
- // 让两个指针分别从头结点和相遇点出发,以相同的速度前进
+ // 让两个指针分别从头节点和相遇点出发,以相同的速度前进
// 一个指针走完len距离时,到达环形入口
// 另一个指针围着环绕了(m-1)圈,并且从h位置出发,走了(r-h)步
// 第二个指针最后到达的位置为 h+(r-h) = r 正好回到环形起点,即环形的入口
// 最终两个指针会在环形入口处相遇
- slow = head; //让慢指针从头结点重新出发
- while (slow != fast) { //当两个结点未相遇时循环继续
+ slow = head; //让慢指针从头节点重新出发
+ while (slow != fast) { //当两个节点未相遇时循环继续
//慢指针和快指针各走一步
slow = slow.next;
fast = fast.next;
}
- return slow;//循环结束后返回的结点就是环形入口
+ return slow;//循环结束后返回的节点就是环形入口
}
return null;
}
-
-
+
```
**复杂度分析**
-时间复杂度:O(n),
+时间复杂度: O(n),
判断是否有环时,循环了n+k次,k是快指针比慢指针多跑的长度
-查找环的入口时循环了s次,s是从头结点到环入口的距离
+查找环的入口时循环了s次,s是从头节点到环入口的距离
-空间复杂度:O(1),只使用了两个临时变量,空间复杂度为常数O(1)
+空间复杂度: O(1),
+只使用了两个临时变量,空间复杂度为常数O(1)
---
**参考资料**
* 网友高票Java解法:
-[https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-O(1)-space-solution-with-detailed-explanation.](https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-OƑ)-space-solution-with-detailed-explanation.)
+[https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-O(1)-space-solution-with-detailed-explanation.](https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-O(1)-space-solution-with-detailed-explanation.)
-* 《数据结构面试 之 单链表是否有环及环入口点 附有最详细明了的图解》:
-[https://www.jianshu.com/p/ef71e04241e4](https://www.jianshu.com/p/ef71e04241e4)
\ No newline at end of file
+* 《数据结构面试 之 单链表是否有环及环入口点 附有最详细明了的图解》:
+[https://www.jianshu.com/p/ef71e04241e4](https://www.jianshu.com/p/ef71e04241e4)
diff --git a/solutions/leetcode/142-linkedListCycleII/official.md b/solutions/leetcode/142-linkedListCycleII/official.md
new file mode 100644
index 0000000..439a91c
--- /dev/null
+++ b/solutions/leetcode/142-linkedListCycleII/official.md
@@ -0,0 +1,3 @@
+**142. 环形链表 II**
+---
+[https://leetcode-cn.com/problems/linked-list-cycle-ii/](https://leetcode-cn.com/problems/linked-list-cycle-ii/)
diff --git a/solutions/leetcode/144-BinaryTreePreorderTraversal/README.md b/solutions/leetcode/144-BinaryTreePreorderTraversal/README.md
new file mode 100644
index 0000000..91dc5eb
--- /dev/null
+++ b/solutions/leetcode/144-BinaryTreePreorderTraversal/README.md
@@ -0,0 +1,18 @@
+**144. 二叉树的前序遍历**
+---
+[https://leetcode-cn.com/problems/binary-tree-preorder-traversal/](https://leetcode-cn.com/problems/binary-tree-preorder-traversal/)
+
+给定一个二叉树,返回它的 前序 遍历。
+
+**示例:**
+
+```
+输入: [1,null,2,3]
+ 1
+ \
+ 2
+ /
+ 3
+
+输出: [1,2,3]
+```
diff --git a/solutions/leetcode/144-BinaryTreePreorderTraversal/bigablecat.md b/solutions/leetcode/144-BinaryTreePreorderTraversal/bigablecat.md
new file mode 100644
index 0000000..0a450e8
--- /dev/null
+++ b/solutions/leetcode/144-BinaryTreePreorderTraversal/bigablecat.md
@@ -0,0 +1,52 @@
+**144. 二叉树的前序遍历**
+---
+[https://leetcode-cn.com/problems/binary-tree-preorder-traversal/](https://leetcode-cn.com/problems/binary-tree-preorder-traversal/)
+
+* 网友高票Java解法:
+
+```java
+
+ /**
+ * 前序遍历(DLR),是二叉树遍历的一种,首先访问根结点然后遍历左子树,最后遍历右子树
+ *
+ * 网友高票Java解法
+ *
+ * @param node
+ * @return
+ */
+ public List
@@ -103,9 +103,3 @@
4) 在git上提交你的文件,管理员审核通过后大家就能看到你的答案并和你讨论了
---
-
-**参考资料**
-
-1) [leetCode中文题库](https://leetcode-cn.com/problemset/all/)
-
-2) [覃超《算法面试通关40讲》课件](https://github.com/geektime-geekbang/algorithm-1)
diff --git a/leetcode/001-twoSum/official.md b/leetcode/001-twoSum/official.md
deleted file mode 100644
index 729d988..0000000
--- a/leetcode/001-twoSum/official.md
+++ /dev/null
@@ -1,4 +0,0 @@
-**1. 两数之和**
----
-[https://leetcode-cn.com/problems/two-sum/](https://leetcode-cn.com/problems/two-sum/)
-
diff --git a/leetcode/053-maximumSubarray/official.md b/leetcode/053-maximumSubarray/official.md
deleted file mode 100644
index e50ab30..0000000
--- a/leetcode/053-maximumSubarray/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**53. 最大子序和**
----
-[https://leetcode-cn.com/problems/maximum-subarray/](https://leetcode-cn.com/problems/linked-list-cycle-ii/)
diff --git a/leetcode/064-minimumPathSum/official.md b/leetcode/064-minimumPathSum/official.md
deleted file mode 100644
index ce1339d..0000000
--- a/leetcode/064-minimumPathSum/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**64. 最小路径和**
----
-[https://leetcode-cn.com/problems/minimum-path-sum/](https://leetcode-cn.com/problems/minimum-path-sum/)
diff --git a/leetcode/069-SqrtX/official.md b/leetcode/069-SqrtX/official.md
deleted file mode 100644
index b9d2b1f..0000000
--- a/leetcode/069-SqrtX/official.md
+++ /dev/null
@@ -1,4 +0,0 @@
-**69. x 的平方根**
----
-
-[https://leetcode-cn.com/problems/sqrtx/](https://leetcode-cn.com/problems/sqrtx/)
diff --git a/leetcode/070-ClimbingStairs/official.md b/leetcode/070-ClimbingStairs/official.md
deleted file mode 100644
index db86b03..0000000
--- a/leetcode/070-ClimbingStairs/official.md
+++ /dev/null
@@ -1,4 +0,0 @@
-**70. 爬楼梯**
----
-
-[https://leetcode-cn.com/problems/climbing-stairs/](https://leetcode-cn.com/problems/climbing-stairs/)
diff --git a/leetcode/152-MaximumProductSubarray/official.md b/leetcode/152-MaximumProductSubarray/official.md
deleted file mode 100644
index d6f0978..0000000
--- a/leetcode/152-MaximumProductSubarray/official.md
+++ /dev/null
@@ -1,4 +0,0 @@
-**152. 乘积最大子序列**
----
-
-[https://leetcode-cn.com/problems/maximum-product-subarray/](https://leetcode-cn.com/problems/maximum-product-subarray/)
diff --git a/leetcode/174-DungeonGame/official.md b/leetcode/174-DungeonGame/official.md
deleted file mode 100644
index 194b4a0..0000000
--- a/leetcode/174-DungeonGame/official.md
+++ /dev/null
@@ -1,4 +0,0 @@
-**174. 地下城游戏**
----
-
-[https://leetcode-cn.com/problems/dungeon-game/](https://leetcode-cn.com/problems/dungeon-game/)
diff --git a/leetcode/198-houseRobber/official.md b/leetcode/198-houseRobber/official.md
deleted file mode 100644
index 90116ff..0000000
--- a/leetcode/198-houseRobber/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**198. 打家劫舍**
----
-[https://leetcode-cn.com/problems/house-robber/](https://leetcode-cn.com/problems/house-robber/)
diff --git a/leetcode/208-implementTriePrefixTree/official.md b/leetcode/208-implementTriePrefixTree/official.md
deleted file mode 100644
index e8c050d..0000000
--- a/leetcode/208-implementTriePrefixTree/official.md
+++ /dev/null
@@ -1,4 +0,0 @@
-**208. 实现 Trie (前缀树)**
----
-[https://leetcode-cn.com/problems/implement-trie-prefix-tree/](https://leetcode-cn.com/problems/implement-trie-prefix-tree/)
-
diff --git a/leetcode/232-implementQueueUsingStacks/official.md b/leetcode/232-implementQueueUsingStacks/official.md
deleted file mode 100644
index 98ac7a7..0000000
--- a/leetcode/232-implementQueueUsingStacks/official.md
+++ /dev/null
@@ -1,4 +0,0 @@
-**232. 用栈实现队列**
----
-[https://leetcode-cn.com/problems/implement-queue-using-stacks/](https://leetcode-cn.com/problems/implement-queue-using-stacks/)
-
diff --git a/leetcode/279-PerfectSquares/official.md b/leetcode/279-PerfectSquares/official.md
deleted file mode 100644
index f0a46e8..0000000
--- a/leetcode/279-PerfectSquares/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**279. 完全平方数**
----
-[https://leetcode-cn.com/problems/perfect-squares/](https://leetcode-cn.com/problems/perfect-squares/)
diff --git a/leetcode/300-LongestIncreasingSubsequence/official.md b/leetcode/300-LongestIncreasingSubsequence/official.md
deleted file mode 100644
index 81ee403..0000000
--- a/leetcode/300-LongestIncreasingSubsequence/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**300. 最长上升子序列**
----
-[https://leetcode-cn.com/problems/longest-increasing-subsequence/](https://leetcode-cn.com/problems/longest-increasing-subsequence/)
diff --git a/leetcode/303-rangeSumQueryImmutable/official.md b/leetcode/303-rangeSumQueryImmutable/official.md
deleted file mode 100644
index 3a7024f..0000000
--- a/leetcode/303-rangeSumQueryImmutable/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**303. 区域和检索 - 数组不可变**
----
-[https://leetcode-cn.com/problems/range-sum-query-immutable/](https://leetcode-cn.com/problems/range-sum-query-immutable/)
diff --git a/leetcode/343-IntegerBreak/official.md b/leetcode/343-IntegerBreak/official.md
deleted file mode 100644
index 16e682f..0000000
--- a/leetcode/343-IntegerBreak/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**343. 整数拆分**
----
-[https://leetcode-cn.com/problems/integer-break/](https://leetcode-cn.com/problems/integer-break/)
diff --git a/leetcode/416-PartitionEqualSubsetSum/official.md b/leetcode/416-PartitionEqualSubsetSum/official.md
deleted file mode 100644
index 2f25f64..0000000
--- a/leetcode/416-PartitionEqualSubsetSum/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**416. 分割等和子集**
----
-[https://leetcode-cn.com/problems/partition-equal-subset-sum/](https://leetcode-cn.com/problems/partition-equal-subset-sum/)
diff --git a/leetcode/920-NumberOfMusicPlaylists/official.md b/leetcode/920-NumberOfMusicPlaylists/official.md
deleted file mode 100644
index 0afaa26..0000000
--- a/leetcode/920-NumberOfMusicPlaylists/official.md
+++ /dev/null
@@ -1,3 +0,0 @@
-**920. Number of Music Playlists**
----
-[https://leetcode-cn.com/problems/number-of-music-playlists/](https://leetcode-cn.com/problems/number-of-music-playlists/)
diff --git a/solutions/README.md b/solutions/README.md
new file mode 100644
index 0000000..ac5cec1
--- /dev/null
+++ b/solutions/README.md
@@ -0,0 +1,2156 @@
+
+### 算法每日一练
+
+* 这个专栏是Hollis知识星球的朋友们练习算法的地方,同时也欢迎广大网友参与
+* 所有题目来源是[leetCode](https://leetcode-cn.com/problemset/all/)官方公开题库
+
+### 初学者友好的算法题目解答
+
+* 算法解答部分的代码注释细致到每一行
+* 希望能为初学者提供最大的便利去理解每道题目和解法
+* 欢迎网友为本项目做贡献,提交你的解题方法和详细解释
+
+---
+
+### 专题列表
+* 2018年11月27日~2019年01月16日
+>[《算法面试通关40讲》专题](https://time.geekbang.org/course/intro/130)
+>[《算法面试通关40讲》官方课件](https://github.com/geektime-geekbang/algorithm-1)
+
+* 2018年11月16日
+>LeetCode动态规划专题
+
+---
+
+专题(Begin):《算法面试40讲》
+---
+
+2018年11月27日
+
+[206. 反转链表](https://github.com/hollischuang/algorithm/tree/master/leetcode/206-reverseLinkedList)
+
+[https://leetcode-cn.com/problems/reverse-linked-list/](https://leetcode-cn.com/problems/reverse-linked-list/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/reverse-linked-list/](https://leetcode.com/articles/reverse-linked-list/)
+
+知识点:数组、链表
+
+难度:简单
+
+---
+
+2018年11月28日
+
+[24. 两两交换链表中的节点](https://github.com/hollischuang/algorithm/tree/master/leetcode/024-swapNodesInPairs)
+
+[https://leetcode-cn.com/problems/swap-nodes-in-pairs/](https://leetcode-cn.com/problems/swap-nodes-in-pairs/)
+
+无官方题解,网友最高票Java解法:
+
+[https://leetcode.com/problems/swap-nodes-in-pairs/discuss/11030/My-accepted-java-code.-used-recursion.](https://leetcode.com/problems/swap-nodes-in-pairs/discuss/11030/My-accepted-java-code.-used-recursion.)
+
+知识点:数组、链表
+
+难度:中等
+
+---
+
+2018年11月29日
+
+[141. 环形链表](https://github.com/hollischuang/algorithm/tree/master/leetcode/141-linkedListCycle)
+
+[https://leetcode-cn.com/problems/linked-list-cycle/](https://leetcode-cn.com/problems/linked-list-cycle/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/linked-list-cycle/](https://leetcode-cn.com/articles/linked-list-cycle/)
+
+知识点:数组、链表
+
+难度:简单
+
+---
+
+2018年11月30日
+
+[142. 环形链表 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/142-linkedListCycleII)
+
+[https://leetcode-cn.com/problems/linked-list-cycle-ii/](https://leetcode-cn.com/problems/linked-list-cycle-ii/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-O(1)-space-solution-with-detailed-explanation.](https://leetcode.com/problems/linked-list-cycle-ii/discuss/44774/Java-O(1)-space-solution-with-detailed-explanation.)
+
+知识点:数组、链表
+
+难度:中等
+
+---
+
+2018年12月01日
+
+[25. k个一组翻转链表](https://github.com/hollischuang/algorithm/tree/master/leetcode/025-reverseNodesInKGroup)
+
+[https://leetcode-cn.com/problems/reverse-nodes-in-k-group/](https://leetcode-cn.com/problems/reverse-nodes-in-k-group/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11423/Short-but-recursive-Java-code-with-comments](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11423/Short-but-recursive-Java-code-with-comments)
+
+知识点:数组、链表
+
+难度:困难
+
+---
+
+2018年12月02日
+
+[20. 有效的括号](https://github.com/hollischuang/algorithm/tree/master/leetcode/020-validParentheses)
+
+[https://leetcode-cn.com/problems/valid-parentheses/](https://leetcode-cn.com/problems/valid-parentheses/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/valid-parentheses/](https://leetcode-cn.com/articles/valid-parentheses/)
+
+知识点:堆栈、队列
+
+难度:简单
+
+---
+
+2018年12月03日
+
+[232. 用栈实现队列](https://github.com/hollischuang/algorithm/tree/master/leetcode/232-implementQueueUsingStacks)
+
+[https://leetcode-cn.com/problems/implement-queue-using-stacks/](https://leetcode-cn.com/problems/implement-queue-using-stacks/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/implement-queue-using-stacks/](https://leetcode.com/articles/implement-queue-using-stacks/)
+
+知识点:堆栈、队列
+
+难度:简单
+
+---
+
+2018年12月04日
+
+[225. 用队列实现栈](https://github.com/hollischuang/algorithm/tree/master/leetcode/225-implementStackUsingQueues)
+
+[https://leetcode-cn.com/problems/implement-stack-using-queues/](https://leetcode-cn.com/problems/implement-stack-using-queues/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/implement-stack-using-queues/](https://leetcode.com/articles/implement-stack-using-queues/)
+
+知识点:堆栈、队列
+
+难度:简单
+
+---
+
+2018年12月05日
+
+[844. 比较含退格的字符串](https://github.com/hollischuang/algorithm/tree/master/leetcode/844-BackspaceStringCompare)
+
+[https://leetcode-cn.com/problems/backspace-string-compare/](https://leetcode-cn.com/problems/backspace-string-compare/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/backspace-string-compare/](https://leetcode.com/articles/backspace-string-compare/)
+
+知识点:堆栈、队列
+
+难度:简单
+
+---
+
+2018年12月06日
+
+[703. 数据流中的第K大元素](https://github.com/hollischuang/algorithm/tree/master/leetcode/703-KthLargestElementInAStream)
+
+[https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/kth-largest-element-in-a-stream/discuss/149050/Java-Priority-Queue](https://leetcode.com/problems/kth-largest-element-in-a-stream/discuss/149050/Java-Priority-Queue)
+
+知识点:优先队列
+
+难度:简单
+
+---
+
+2018年12月07日
+
+[692. 前K个高频单词](https://github.com/hollischuang/algorithm/tree/master/leetcode/692-TopKFrequentWords)
+
+[https://leetcode-cn.com/problems/top-k-frequent-words/](https://leetcode-cn.com/problems/top-k-frequent-words/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/top-k-frequent-words/](https://leetcode.com/articles/top-k-frequent-words/)
+
+知识点:优先队列
+
+难度:中等
+
+---
+
+2018年12月08日
+
+[239. 滑动窗口最大值](https://github.com/hollischuang/algorithm/tree/master/leetcode/239-slidingWindowMaximum)
+
+[https://leetcode-cn.com/problems/sliding-window-maximum/](https://leetcode-cn.com/problems/sliding-window-maximum/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/sliding-window-maximum/discuss/65884/Java-O(n)-solution-using-deque-with-explanation](https://leetcode.com/problems/sliding-window-maximum/discuss/65884/Java-O(n)-solution-using-deque-with-explanation)
+
+知识点:优先队列
+
+难度:困难
+
+---
+
+2018年12月09日
+
+[242. 有效的字母异位词](https://github.com/hollischuang/algorithm/tree/master/leetcode/242-ValidAnagram)
+
+[https://leetcode-cn.com/problems/valid-anagram/](https://leetcode-cn.com/problems/valid-anagram/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/valid-anagram/](https://leetcode.com/articles/valid-anagram/)
+
+知识点:哈希表和集合
+
+难度:简单
+
+---
+
+2018年12月10日
+
+[1. 两数之和](https://github.com/hollischuang/algorithm/tree/master/leetcode/001-twoSum)
+
+[https://leetcode-cn.com/problems/two-sum/](https://leetcode-cn.com/problems/two-sum/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/two-sum/](https://leetcode-cn.com/articles/two-sum/)
+
+知识点:哈希表和集合
+
+难度:简单
+
+---
+
+2018年12月11日
+
+[15. 三数之和](https://github.com/hollischuang/algorithm/tree/master/leetcode/015-threeSum)
+
+[https://leetcode-cn.com/problems/3sum/](https://leetcode-cn.com/problems/3sum/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/3sum/discuss/7380/Concise-O(N2)-Java-solution](https://leetcode.com/problems/3sum/discuss/7380/Concise-O(N2)-Java-solution)
+
+知识点:哈希表和集合
+
+难度:中等
+
+---
+
+2018年12月12日
+
+[98. 验证二叉搜索树](https://github.com/hollischuang/algorithm/tree/master/leetcode/098-validateBinarySearchTree)
+
+[https://leetcode-cn.com/problems/validate-binary-search-tree/](https://leetcode-cn.com/problems/validate-binary-search-tree/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/validate-binary-search-tree/discuss/32112/Learn-one-iterative-inorder-traversal-apply-it-to-multiple-tree-questions-(Java-Solution)](https://leetcode.com/problems/validate-binary-search-tree/discuss/32112/Learn-one-iterative-inorder-traversal-apply-it-to-multiple-tree-questions-(Java-Solution))
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/validate-binary-search-tree/discuss/32109/My-simple-Java-solution-in-3-lines](https://leetcode.com/problems/validate-binary-search-tree/discuss/32109/My-simple-Java-solution-in-3-lines)
+
+知识点:树、二叉树、二叉搜索树
+
+难度:中等
+
+---
+
+2018年12月13日
+
+[236. 二叉树的最近公共祖先](https://github.com/hollischuang/algorithm/tree/master/leetcode/236-lowestCommonAncestorOfABinaryTree)
+
+[https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/lowest-common-ancestor-of-a-binary-tree/](https://leetcode.com/articles/lowest-common-ancestor-of-a-binary-tree/)
+
+知识点:树、二叉树、二叉搜索树
+
+难度:中等
+
+---
+
+2018年12月14日
+
+[50. Pow(x, n)](https://github.com/hollischuang/algorithm/tree/master/leetcode/050-powxN)
+
+[https://leetcode-cn.com/problems/powx-n/](https://leetcode-cn.com/problems/powx-n/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/powx-n/discuss/19546/Short-and-easy-to-understand-solution](https://leetcode.com/problems/powx-n/discuss/19546/Short-and-easy-to-understand-solution)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/powx-n/discuss/19544/5-different-choices-when-talk-with-interviewers](https://leetcode.com/problems/powx-n/discuss/19544/5-different-choices-when-talk-with-interviewers)
+
+知识点:递归、分治
+
+难度:中等
+
+---
+
+2018年12月15日
+
+[169. 求众数](https://github.com/hollischuang/algorithm/tree/master/leetcode/169-majorityElement)
+
+[https://leetcode-cn.com/problems/majority-element/](https://leetcode-cn.com/problems/majority-element/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/majority-element/](https://leetcode.com/articles/majority-element/)
+
+知识点:递归、分治
+
+难度:简单
+
+---
+
+2018年12月16日
+
+[53. 最大子序和](https://github.com/hollischuang/algorithm/tree/master/leetcode/053-maximumSubarray)
+
+[https://leetcode-cn.com/problems/maximum-subarray/](https://leetcode-cn.com/problems/maximum-subarray/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/maximum-subarray/discuss/20193/DP-solution-and-some-thoughts](https://leetcode.com/problems/maximum-subarray/discuss/20193/DP-solution-and-some-thoughts)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/maximum-subarray/discuss/20211/Accepted-O(n)-solution-in-java](https://leetcode.com/problems/maximum-subarray/discuss/20211/Accepted-O(n)-solution-in-java)
+
+知识点:递归、分治、动态规划
+
+难度:简单
+
+---
+
+2018年12月17日
+
+[860. 柠檬水找零](https://github.com/hollischuang/algorithm/tree/master/leetcode/860-lemonadeChange)
+
+[https://leetcode-cn.com/problems/lemonade-change/](https://leetcode-cn.com/problems/lemonade-change/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/lemonade-change/](https://leetcode-cn.com/articles/lemonade-change/)
+
+知识点:贪心算法
+
+难度:简单
+
+---
+
+2018年12月18日
+
+[122. 买卖股票的最佳时机 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/122-bestTimeToBuyAndSellStockII)
+
+[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/best-time-to-buy-and-sell-stock-ii/](https://leetcode-cn.com/articles/best-time-to-buy-and-sell-stock-ii/)
+
+知识点:贪心算法
+
+难度:简单
+
+---
+
+2018年12月19日
+
+[455. 分发饼干](https://github.com/hollischuang/algorithm/tree/master/leetcode/455-AssignCookies)
+
+[https://leetcode-cn.com/problems/assign-cookies/](https://leetcode-cn.com/problems/assign-cookies/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/assign-cookies/discuss/93987/Simple-Greedy-Java-Solution](https://leetcode.com/problems/assign-cookies/discuss/93987/Simple-Greedy-Java-Solution)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/assign-cookies/discuss/93997/Array-sort-%2B-Two-pointer-greedy-solution-O(nlogn)](https://leetcode.com/problems/assign-cookies/discuss/93997/Array-sort-%2B-Two-pointer-greedy-solution-O(nlogn))
+
+知识点:贪心算法
+
+难度:简单
+
+---
+
+2018年12月20日
+
+[874. 模拟行走机器人](https://github.com/hollischuang/algorithm/tree/master/leetcode/874-walkingRobotSimulation)
+
+[https://leetcode-cn.com/problems/walking-robot-simulation/](https://leetcode-cn.com/problems/walking-robot-simulation/)
+
+英文官方题解:
+
+[https://leetcode.com/problems/walking-robot-simulation/solution/](https://leetcode.com/problems/walking-robot-simulation/solution/)
+
+知识点:贪心算法
+
+难度:简单
+
+---
+
+2018年12月21日
+
+[102. 二叉树的层次遍历](https://github.com/hollischuang/algorithm/tree/master/leetcode/102-BinaryTreeLevelOrderTraversal)
+
+[https://leetcode-cn.com/problems/binary-tree-level-order-traversal/](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/binary-tree-level-order-traversal/discuss/33450/Java-solution-with-a-queue-used](https://leetcode.com/problems/binary-tree-level-order-traversal/discuss/33450/Java-solution-with-a-queue-used)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/binary-tree-level-order-traversal/discuss/33445/Java-Solution-using-DFS](https://leetcode.com/problems/binary-tree-level-order-traversal/discuss/33445/Java-Solution-using-DFS)
+
+知识点:广度优先搜索
+
+难度:中等
+
+---
+
+2018年12月22日
+
+[104. 二叉树的最大深度](https://github.com/hollischuang/algorithm/tree/master/leetcode/104-MaximumDepthOfBinaryTree)
+
+[https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/maximum-depth-of-binary-tree/](https://leetcode-cn.com/articles/maximum-depth-of-binary-tree/)
+
+知识点:深度优先搜索
+
+难度:简单
+
+---
+
+2018年12月23日
+
+[51. N-皇后](https://github.com/hollischuang/algorithm/tree/master/leetcode/051-NQueens)
+
+[https://leetcode-cn.com/problems/n-queens/](https://leetcode-cn.com/problems/n-queens/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/n-queens/discuss/19805/My-easy-understanding-Java-Solution](https://leetcode.com/problems/n-queens/discuss/19805/My-easy-understanding-Java-Solution)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/n-queens/discuss/19808/Accepted-4ms-c%2B%2B-solution-use-backtracking-and-bitmask-easy-understand.](https://leetcode.com/problems/n-queens/discuss/19808/Accepted-4ms-c%2B%2B-solution-use-backtracking-and-bitmask-easy-understand.)
+
+知识点:剪枝
+
+难度:困难
+
+---
+
+2018年12月24日
+
+[36. 有效的数独](https://github.com/hollischuang/algorithm/tree/master/leetcode/036-ValidSudoku)
+
+[https://leetcode-cn.com/problems/valid-sudoku/](https://leetcode-cn.com/problems/valid-sudoku/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/valid-sudoku/discuss/15472/Short%2BSimple-Java-using-Strings](https://leetcode.com/problems/valid-sudoku/discuss/15472/Short%2BSimple-Java-using-Strings)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/valid-sudoku/discuss/15450/Shared-my-concise-Java-code](https://leetcode.com/problems/valid-sudoku/discuss/15450/Shared-my-concise-Java-code)
+
+知识点:剪枝
+
+难度:中等
+
+---
+
+2018年12月25日
+
+[37. 解数独](https://github.com/hollischuang/algorithm/tree/master/leetcode/037-SudokuSolver)
+
+[https://leetcode-cn.com/problems/sudoku-solver/](https://leetcode-cn.com/problems/sudoku-solver/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/sudoku-solver/discuss/15752/Straight-Forward-Java-Solution-Using-Backtracking](https://leetcode.com/problems/sudoku-solver/discuss/15752/Straight-Forward-Java-Solution-Using-Backtracking)
+
+知识点:剪枝
+
+难度:困难
+
+---
+
+2018年12月26日
+
+[69. x 的平方根](https://github.com/hollischuang/algorithm/tree/master/leetcode/069-SqrtX)
+
+[https://leetcode-cn.com/problems/sqrtx/](https://leetcode-cn.com/problems/sqrtx/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/sqrtx/discuss/25047/A-Binary-Search-Solution](https://leetcode.com/problems/sqrtx/discuss/25047/A-Binary-Search-Solution)
+
+知识点:二分查找
+
+难度:简单
+
+---
+
+2018年12月27日
+
+[367. 有效的完全平方数](https://github.com/hollischuang/algorithm/tree/master/leetcode/367-ValidPerfectSquare)
+
+[https://leetcode-cn.com/problems/valid-perfect-square/](https://leetcode-cn.com/problems/valid-perfect-square/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/valid-perfect-square/discuss/83874/A-square-number-is-1%2B3%2B5%2B7%2B...-JAVA-code](https://leetcode.com/problems/valid-perfect-square/discuss/83874/A-square-number-is-1%2B3%2B5%2B7%2B...-JAVA-code)
+
+知识点:二分查找
+
+难度:简单
+
+---
+
+2018年12月28日
+
+[208. 实现 Trie (前缀树)](https://github.com/hollischuang/algorithm/tree/master/leetcode/208-implementTriePrefixTree)
+
+[https://leetcode-cn.com/problems/implement-trie-prefix-tree/](https://leetcode-cn.com/problems/implement-trie-prefix-tree/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/implement-trie-prefix-tree/](https://leetcode.com/articles/implement-trie-prefix-tree/)
+
+知识点:字典树
+
+难度:中等
+
+---
+
+2018年12月29日
+
+[212. 单词搜索 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/212-wordSearchII)
+
+[https://leetcode-cn.com/problems/word-search-ii/](https://leetcode-cn.com/problems/word-search-ii/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/word-search-ii/discuss/59780/Java-15ms-Easiest-Solution-(100.00)](https://leetcode.com/problems/word-search-ii/discuss/59780/Java-15ms-Easiest-Solution-(100.00))
+
+知识点:字典树
+
+难度:困难
+
+---
+
+2018年12月30日
+
+[191. 位1的个数](https://github.com/hollischuang/algorithm/tree/master/leetcode/191-NumberOf1Bits)
+
+[https://leetcode-cn.com/problems/number-of-1-bits/](https://leetcode-cn.com/problems/number-of-1-bits/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/number-1-bits/](https://leetcode.com/articles/number-1-bits/)
+
+知识点:位运算
+
+难度:简单
+
+---
+
+2018年12月31日
+
+[338. 比特位计数](https://github.com/hollischuang/algorithm/tree/master/leetcode/338-CountingBits)
+
+[https://leetcode-cn.com/problems/counting-bits/](https://leetcode-cn.com/problems/counting-bits/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/counting-bits/discuss/79539/Three-Line-Java-Solution](https://leetcode.com/problems/counting-bits/discuss/79539/Three-Line-Java-Solution)
+
+知识点:位运算
+
+难度:中等
+
+---
+
+2019年01月01日
+
+[231. 2的幂](https://github.com/hollischuang/algorithm/tree/master/leetcode/231-PowerOfTwo)
+
+[https://leetcode-cn.com/problems/power-of-two/](https://leetcode-cn.com/problems/power-of-two/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/power-of-two/discuss/63972/One-line-java-solution-using-bitCount](https://leetcode.com/problems/power-of-two/discuss/63972/One-line-java-solution-using-bitCount)
+
+知识点:位运算
+
+难度:简单
+
+---
+
+2019年01月02日
+
+[52. N皇后 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/052-N-QueensII)
+
+[https://leetcode-cn.com/problems/n-queens-ii/](https://leetcode-cn.com/problems/n-queens-ii/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/n-queens-ii/discuss/20058/Accepted-Java-Solution](https://leetcode.com/problems/n-queens-ii/discuss/20058/Accepted-Java-Solution)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/n-queens-ii/discuss/20048/Easiest-Java-Solution-(1ms-98.22)](https://leetcode.com/problems/n-queens-ii/discuss/20048/Easiest-Java-Solution-(1ms-98.22))
+
+知识点:位运算
+
+难度:困难
+
+---
+
+2019年01月03日
+
+[70. 爬楼梯](https://github.com/hollischuang/algorithm/tree/master/leetcode/070-ClimbingStairs)
+
+[https://leetcode-cn.com/problems/climbing-stairs/](https://leetcode-cn.com/problems/climbing-stairs/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/climbing-stairs/](https://leetcode.com/articles/climbing-stairs/)
+
+知识点:动态规划
+
+难度:简单
+
+---
+
+2019年01月04日
+
+[120. 三角形最小路径和](https://github.com/hollischuang/algorithm/tree/master/leetcode/120-Triangle)
+
+[https://leetcode-cn.com/problems/triangle/](https://leetcode-cn.com/problems/triangle/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/triangle/discuss/38730/DP-Solution-for-Triangle](https://leetcode.com/problems/triangle/discuss/38730/DP-Solution-for-Triangle)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/triangle/discuss/38724/7-lines-neat-Java-Solution](https://leetcode.com/problems/triangle/discuss/38724/7-lines-neat-Java-Solution)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月05日
+
+[152. 乘积最大子序列](https://github.com/hollischuang/algorithm/tree/master/leetcode/152-MaximumProductSubarray)
+
+[https://leetcode-cn.com/problems/maximum-product-subarray/](https://leetcode-cn.com/problems/maximum-product-subarray/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/maximum-product-subarray/discuss/48230/Possibly-simplest-solution-with-O(n)-time-complexity](https://leetcode.com/problems/maximum-product-subarray/discuss/48230/Possibly-simplest-solution-with-O(n)-time-complexity)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/maximum-product-subarray/discuss/48252/Sharing-my-solution%3A-O(1)-space-O(n)-running-time](https://leetcode.com/problems/maximum-product-subarray/discuss/48252/Sharing-my-solution%3A-O(1)-space-O(n)-running-time)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月06日
+
+[123. 买卖股票的最佳时机 III](https://github.com/hollischuang/algorithm/tree/master/leetcode/123-BestTimeToBuyAndSellStockIII)
+
+[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/discuss/39611/Is-it-Best-Solution-with-O(n)-O(1).](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/discuss/39611/Is-it-Best-Solution-with-O(n)-O(1).)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/discuss/135704/Detail-explanation-of-DP-solution](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/discuss/135704/Detail-explanation-of-DP-solution)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年01月07日
+
+[121. 买卖股票的最佳时机](https://github.com/hollischuang/algorithm/tree/master/leetcode/121-bestTimeToBuyAndSellStock)
+
+[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/best-time-to-buy-and-sell-stock/](https://leetcode-cn.com/articles/best-time-to-buy-and-sell-stock/)
+
+知识点:动态规划
+
+难度:简单
+
+---
+
+2019年01月08日
+
+[188. 买卖股票的最佳时机 IV](https://github.com/hollischuang/algorithm/tree/master/leetcode/188-bestTimeToBuyAndSellStockIV)
+
+[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/discuss/54113/A-Concise-DP-Solution-in-Java](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/discuss/54113/A-Concise-DP-Solution-in-Java)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年01月09日
+
+[309. 最佳买卖股票时机含冷冻期](https://github.com/hollischuang/algorithm/tree/master/leetcode/309-BestTimeToBuyAndSellStockWithCooldown)
+
+[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/discuss/75927/Share-my-thinking-process](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/discuss/75927/Share-my-thinking-process)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月10日
+
+[714. 买卖股票的最佳时机含手续费](https://github.com/hollischuang/algorithm/tree/master/leetcode/714-BestTimeToBuyAndSellStockWithTransactionFee)
+
+[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/best-time-to-buy-and-sell-stock-with-transaction-fee/](https://leetcode.com/articles/best-time-to-buy-and-sell-stock-with-transaction-fee/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月11日
+
+[300. 最长上升子序列](https://github.com/hollischuang/algorithm/tree/master/leetcode/300-LongestIncreasingSubsequence)
+
+[https://leetcode-cn.com/problems/longest-increasing-subsequence/](https://leetcode-cn.com/problems/longest-increasing-subsequence/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/longest-increasing-subsequence/](https://leetcode.com/articles/longest-increasing-subsequence/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月12日
+
+[322. 零钱兑换](https://github.com/hollischuang/algorithm/tree/master/leetcode/322-CoinChange)
+
+[https://leetcode-cn.com/problems/coin-change/](https://leetcode-cn.com/problems/coin-change/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/coin-change/](https://leetcode.com/articles/coin-change/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月13日
+
+[72. 编辑距离](https://github.com/hollischuang/algorithm/tree/master/leetcode/072-EditDistance)
+
+[https://leetcode-cn.com/problems/edit-distance/](https://leetcode-cn.com/problems/edit-distance/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/edit-distance/](https://leetcode.com/articles/edit-distance/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年01月14日
+
+[200. 岛屿的个数](https://github.com/hollischuang/algorithm/tree/master/leetcode/200-numberOfIslands)
+
+[https://leetcode-cn.com/problems/number-of-islands/](https://leetcode-cn.com/problems/number-of-islands/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/number-of-islands/discuss/56359/Very-concise-Java-AC-solution](https://leetcode.com/problems/number-of-islands/discuss/56359/Very-concise-Java-AC-solution)
+
+知识点:并查集
+
+难度:中等
+
+---
+
+2019年01月15日
+
+[547. 朋友圈](https://github.com/hollischuang/algorithm/tree/master/leetcode/547-friendCircles)
+
+[https://leetcode-cn.com/problems/friend-circles/](https://leetcode-cn.com/problems/friend-circles/)
+
+无官方题解,网友高票Java解法1(DFS):
+
+[https://leetcode.com/problems/friend-circles/discuss/101338/Neat-DFS-java-solution](https://leetcode.com/problems/friend-circles/discuss/101338/Neat-DFS-java-solution)
+
+无官方题解,网友高票Java解法2(Union Find):
+
+[https://leetcode.com/problems/friend-circles/discuss/101336/Java-solution-Union-Find](https://leetcode.com/problems/friend-circles/discuss/101336/Java-solution-Union-Find)
+
+知识点:并查集
+
+难度:中等
+
+---
+
+2019年01月16日
+
+[146. LRU缓存机制](https://github.com/hollischuang/algorithm/tree/master/leetcode/146-lruCache)
+
+[https://leetcode-cn.com/problems/lru-cache/](https://leetcode-cn.com/problems/lru-cache/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/lru-cache/discuss/45911/Java-Hashtable-%2B-Double-linked-list-(with-a-touch-of-pseudo-nodes)](https://leetcode.com/problems/lru-cache/discuss/45911/Java-Hashtable-%2B-Double-linked-list-(with-a-touch-of-pseudo-nodes))
+
+知识点:LRU
+
+难度:困难
+
+---
+
+专题(End):《算法面试40讲》
+---
+
+
+
+专题(Begin):动态规划
+---
+
+2019年01月17日
+
+[303. 区域和检索 - 数组不可变](https://github.com/hollischuang/algorithm/tree/master/leetcode/303-rangeSumQueryImmutable)
+
+[https://leetcode-cn.com/problems/range-sum-query-immutable/](https://leetcode-cn.com/problems/range-sum-query-immutable/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/range-sum-query-immutable/](https://leetcode.com/articles/range-sum-query-immutable/)
+
+知识点:动态规划
+
+难度:简单
+
+---
+
+2019年01月18日
+
+[746. 使用最小花费爬楼梯](https://github.com/hollischuang/algorithm/tree/master/leetcode/746-minCostClimbingStairs)
+
+[https://leetcode-cn.com/problems/min-cost-climbing-stairs/](https://leetcode-cn.com/problems/min-cost-climbing-stairs/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/min-cost-climbing-stairs/](https://leetcode.com/articles/min-cost-climbing-stairs/)
+
+知识点:动态规划
+
+难度:简单
+
+---
+
+2019年01月19日
+
+[198. 打家劫舍](https://github.com/hollischuang/algorithm/tree/master/leetcode/198-houseRobber)
+
+[https://leetcode-cn.com/problems/house-robber/](https://leetcode-cn.com/problems/house-robber/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/house-robber/discuss/156523/From-good-to-great.-How-to-approach-most-of-DP-problems.](https://leetcode.com/problems/house-robber/discuss/156523/From-good-to-great.-How-to-approach-most-of-DP-problems.)
+
+知识点:动态规划
+
+难度:简单
+
+---
+
+2019年01月20日
+
+[877. 石子游戏](https://github.com/hollischuang/algorithm/tree/master/leetcode/877-stoneGame)
+
+[https://leetcode-cn.com/problems/stone-game/](https://leetcode-cn.com/problems/stone-game/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/stone-game/](https://leetcode-cn.com/articles/stone-game/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月21日
+
+[64. 最小路径和](https://github.com/hollischuang/algorithm/tree/master/leetcode/064-minimumPathSum)
+
+[https://leetcode-cn.com/problems/minimum-path-sum/](https://leetcode-cn.com/problems/minimum-path-sum/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/minimum-path-sum/discuss/23471/My-java-solution-using-DP-and-no-extra-space](https://leetcode.com/problems/minimum-path-sum/discuss/23471/My-java-solution-using-DP-and-no-extra-space)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月22日
+
+[96. 不同的二叉搜索树](https://github.com/hollischuang/algorithm/tree/master/leetcode/096-uniqueBinarySearchTrees)
+
+[https://leetcode-cn.com/problems/unique-binary-search-trees/](https://leetcode-cn.com/problems/unique-binary-search-trees/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/unique-binary-search-trees/](https://leetcode.com/articles/unique-binary-search-trees/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月23日
+
+[413. 等差数列划分](https://github.com/hollischuang/algorithm/tree/master/leetcode/413-arithmeticSlices)
+
+[https://leetcode-cn.com/problems/arithmetic-slices/](https://leetcode-cn.com/problems/arithmetic-slices/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/arithmetic-slices/](https://leetcode.com/articles/arithmetic-slices/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月24日
+
+[712. 两个字符串的最小ASCII删除和](https://github.com/hollischuang/algorithm/tree/master/leetcode/712-MinimumASCIIDeleteSumforTwoStrings)
+
+[https://leetcode-cn.com/problems/minimum-ascii-delete-sum-for-two-strings/](https://leetcode-cn.com/problems/minimum-ascii-delete-sum-for-two-strings/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/minimum-ascii-delete-sum-for-two-strings/](https://leetcode.com/articles/minimum-ascii-delete-sum-for-two-strings/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月25日
+
+[62. 不同路径](https://github.com/hollischuang/algorithm/tree/master/leetcode/062-UniquePaths)
+
+[https://leetcode-cn.com/problems/unique-paths/](https://leetcode-cn.com/problems/unique-paths/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/unique-paths/discuss/22958/Math-solution-O(1)-space](https://leetcode.com/problems/unique-paths/discuss/22958/Math-solution-O(1)-space)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/unique-paths/discuss/22953/Java-DP-solution-with-complexity-O(n*m)](https://leetcode.com/problems/unique-paths/discuss/22953/Java-DP-solution-with-complexity-O(n*m))
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月26日
+
+[638. 大礼包](https://github.com/hollischuang/algorithm/tree/master/leetcode/638-ShoppingOffers)
+
+[https://leetcode-cn.com/problems/shopping-offers/](https://leetcode-cn.com/problems/shopping-offers/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/shopping-offers/](https://leetcode.com/articles/shopping-offers/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月27日
+
+[647. 回文子串](https://github.com/hollischuang/algorithm/tree/master/leetcode/647-PalindromicSubstrings)
+
+[https://leetcode-cn.com/problems/palindromic-substrings/](https://leetcode-cn.com/problems/palindromic-substrings/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/palindromic-substrings/](https://leetcode.com/articles/palindromic-substrings/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月28日
+
+[931. 下降路径最小和](https://github.com/hollischuang/algorithm/tree/master/leetcode/931-MinimumFallingPathSum)
+
+[https://leetcode-cn.com/problems/minimum-falling-path-sum/](https://leetcode-cn.com/problems/minimum-falling-path-sum/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/minimum-path-falling-sum/](https://leetcode.com/articles/minimum-path-falling-sum/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月29日
+
+[343. 整数拆分](https://github.com/hollischuang/algorithm/tree/master/leetcode/343-IntegerBreak)
+
+[https://leetcode-cn.com/problems/integer-break/](https://leetcode-cn.com/problems/integer-break/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/integer-break/discuss/80689/A-simple-explanation-of-the-math-part-and-a-O(n)-solution](https://leetcode.com/problems/integer-break/discuss/80689/A-simple-explanation-of-the-math-part-and-a-O(n)-solution)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月30日
+
+[95. 不同的二叉搜索树 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/095-UniqueBinarySearchTreesII)
+
+[https://leetcode-cn.com/problems/unique-binary-search-trees-ii/](https://leetcode-cn.com/problems/unique-binary-search-trees-ii/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/unique-binary-search-trees-ii/](https://leetcode.com/articles/unique-binary-search-trees-ii/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年01月31日
+
+[740. 删除与获得点数](https://github.com/hollischuang/algorithm/tree/master/leetcode/740-DeleteAndEarn)
+
+[https://leetcode-cn.com/problems/delete-and-earn/](https://leetcode-cn.com/problems/delete-and-earn/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/delete-and-earn/](https://leetcode.com/articles/delete-and-earn/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月01日
+
+[646. 最长数对链](https://github.com/hollischuang/algorithm/tree/master/leetcode/646-MaximumLengthOfPairChain)
+
+[https://leetcode-cn.com/problems/maximum-length-of-pair-chain/](https://leetcode-cn.com/problems/maximum-length-of-pair-chain/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/maximum-length-of-pair-chain/](https://leetcode.com/articles/maximum-length-of-pair-chain/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月02日
+
+[764. 最大加号标志](https://github.com/hollischuang/algorithm/tree/master/leetcode/764-LargestPlusSign)
+
+[https://leetcode-cn.com/problems/largest-plus-sign/](https://leetcode-cn.com/problems/largest-plus-sign/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/largest-plus-sign/](https://leetcode.com/articles/largest-plus-sign/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月03日
+
+[279. 完全平方数](https://github.com/hollischuang/algorithm/tree/master/leetcode/279-PerfectSquares)
+
+[https://leetcode-cn.com/problems/perfect-squares/](https://leetcode-cn.com/problems/perfect-squares/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/perfect-squares/discuss/71495/An-easy-understanding-DP-solution-in-Java](https://leetcode.com/problems/perfect-squares/discuss/71495/An-easy-understanding-DP-solution-in-Java)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月04日
+
+[392. 判断子序列](https://github.com/hollischuang/algorithm/tree/master/leetcode/392-IsSubsequence)
+
+[https://leetcode-cn.com/problems/is-subsequence/](https://leetcode-cn.com/problems/is-subsequence/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/is-subsequence/discuss/87302/Binary-search-solution-for-follow-up-with-detailed-comments](https://leetcode.com/problems/is-subsequence/discuss/87302/Binary-search-solution-for-follow-up-with-detailed-comments)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月05日
+
+[377. 组合总和 Ⅳ](https://github.com/hollischuang/algorithm/tree/master/leetcode/377-CombinationSumIV)
+
+[https://leetcode-cn.com/problems/combination-sum-iv/](https://leetcode-cn.com/problems/combination-sum-iv/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/combination-sum-iv/discuss/85036/1ms-Java-DP-Solution-with-Detailed-Explanation](https://leetcode.com/problems/combination-sum-iv/discuss/85036/1ms-Java-DP-Solution-with-Detailed-Explanation)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月06日
+
+[486. 预测赢家](https://github.com/hollischuang/algorithm/tree/master/leetcode/486-PredictTheWinner)
+
+[https://leetcode-cn.com/problems/predict-the-winner/](https://leetcode-cn.com/problems/predict-the-winner/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/predict-the-winner/](https://leetcode.com/articles/predict-the-winner/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月07日
+
+[357. 计算各个位数不同的数字个数](https://github.com/hollischuang/algorithm/tree/master/leetcode/357-CountNumbersWithUniqueDigits)
+
+[https://leetcode-cn.com/problems/count-numbers-with-unique-digits/](https://leetcode-cn.com/problems/count-numbers-with-unique-digits/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/count-numbers-with-unique-digits/discuss/83041/JAVA-DP-O(1)-solution.](https://leetcode.com/problems/count-numbers-with-unique-digits/discuss/83041/JAVA-DP-O(1)-solution.)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月08日
+
+[494. 目标和](https://github.com/hollischuang/algorithm/tree/master/leetcode/494-TargetSum)
+
+[https://leetcode-cn.com/problems/target-sum/](https://leetcode-cn.com/problems/target-sum/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/target-sum/](https://leetcode.com/articles/target-sum/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月09日
+
+[516. 最长回文子序列](https://github.com/hollischuang/algorithm/tree/master/leetcode/516-LongestPalindromicSubsequence)
+
+[https://leetcode-cn.com/problems/longest-palindromic-subsequence/](https://leetcode-cn.com/problems/longest-palindromic-subsequence/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/longest-palindromic-subsequence/discuss/99101/Straight-forward-Java-DP-solution](https://leetcode.com/problems/longest-palindromic-subsequence/discuss/99101/Straight-forward-Java-DP-solution)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月10日
+
+[688. “马”在棋盘上的概率](https://github.com/hollischuang/algorithm/tree/master/leetcode/688-KnightProbabilityInChessboard)
+
+[https://leetcode-cn.com/problems/knight-probability-in-chessboard/](https://leetcode-cn.com/problems/knight-probability-in-chessboard/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/knight-probability-in-chessboard/](https://leetcode.com/articles/knight-probability-in-chessboard/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月11日
+
+[718. 最长重复子数组](https://github.com/hollischuang/algorithm/tree/master/leetcode/718-MaximumLengthOfRepeatedSubarray)
+
+[https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/](https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/maximum-length-of-repeated-subarray/](https://leetcode.com/articles/maximum-length-of-repeated-subarray/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月12日
+
+[650. 只有两个键的键盘](https://github.com/hollischuang/algorithm/tree/master/leetcode/650-2KeysKeyboard)
+
+[https://leetcode-cn.com/problems/2-keys-keyboard/](https://leetcode-cn.com/problems/2-keys-keyboard/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/2-keys-keyboard/](https://leetcode.com/articles/2-keys-keyboard/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月13日
+
+[873. 最长的斐波那契子序列的长度](https://github.com/hollischuang/algorithm/tree/master/leetcode/873-LengthOfLongestFibonacciSubsequence)
+
+[https://leetcode-cn.com/problems/length-of-longest-fibonacci-subsequence/](https://leetcode-cn.com/problems/length-of-longest-fibonacci-subsequence/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/length-of-longest-fibonacci-subsequence/](https://leetcode-cn.com/articles/length-of-longest-fibonacci-subsequence/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月14日
+
+[139. 单词拆分](https://github.com/hollischuang/algorithm/tree/master/leetcode/139-WordBreak)
+
+[https://leetcode-cn.com/problems/word-break/](https://leetcode-cn.com/problems/word-break/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/word-break/discuss/43790/Java-implementation-using-DP-in-two-ways](https://leetcode.com/problems/word-break/discuss/43790/Java-implementation-using-DP-in-two-ways)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月15日
+
+[264. 丑数 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/264-UglyNumberII)
+
+[https://leetcode-cn.com/problems/ugly-number-ii/](https://leetcode-cn.com/problems/ugly-number-ii/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/ugly-number-ii/discuss/69362/O(n)-Java-solution](https://leetcode.com/problems/ugly-number-ii/discuss/69362/O(n)-Java-solution)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月16日
+
+[416. 分割等和子集](https://github.com/hollischuang/algorithm/tree/master/leetcode/416-PartitionEqualSubsetSum)
+
+[https://leetcode-cn.com/problems/partition-equal-subset-sum/](https://leetcode-cn.com/problems/partition-equal-subset-sum/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/partition-equal-subset-sum/discuss/90592/01-knapsack-detailed-explanation](https://leetcode.com/problems/partition-equal-subset-sum/discuss/90592/01-knapsack-detailed-explanation)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/partition-equal-subset-sum/discuss/90627/Java-Solution-similar-to-backpack-problem-Easy-to-understand](https://leetcode.com/problems/partition-equal-subset-sum/discuss/90627/Java-Solution-similar-to-backpack-problem-Easy-to-understand)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月17日
+
+[304. 二维区域和检索 - 矩阵不可变](https://github.com/hollischuang/algorithm/tree/master/leetcode/304-RangeSumQuery2DImmutable)
+
+[https://leetcode-cn.com/problems/range-sum-query-2d-immutable/](https://leetcode-cn.com/problems/range-sum-query-2d-immutable/)
+
+英文无官方题解:
+
+[https://leetcode.com/articles/range-sum-query-2d-immutable/](https://leetcode.com/articles/range-sum-query-2d-immutable/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月18日
+
+[221. 最大正方形](https://github.com/hollischuang/algorithm/tree/master/leetcode/221-MaximalSquare)
+
+[https://leetcode-cn.com/problems/maximal-square/](https://leetcode-cn.com/problems/maximal-square/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/maximal-square/](https://leetcode.com/articles/maximal-square/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月19日
+
+[698. 划分为k个相等的子集](https://github.com/hollischuang/algorithm/tree/master/leetcode/698-PartitionToKEqualSumSubsets)
+
+[https://leetcode-cn.com/problems/partition-to-k-equal-sum-subsets/](https://leetcode-cn.com/problems/partition-to-k-equal-sum-subsets/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/partition-to-k-equal-sum-subsets/](https://leetcode.com/articles/partition-to-k-equal-sum-subsets/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月20日
+
+[474. 一和零](https://github.com/hollischuang/algorithm/tree/master/leetcode/474-OnesAndZeroes)
+
+[https://leetcode-cn.com/problems/ones-and-zeroes/](https://leetcode-cn.com/problems/ones-and-zeroes/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/ones-and-zeroes/discuss/95807/0-1-knapsack-detailed-explanation.](https://leetcode.com/problems/ones-and-zeroes/discuss/95807/0-1-knapsack-detailed-explanation.)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/ones-and-zeroes/discuss/95811/Java-Iterative-DP-Solution-O(mn)-Space](https://leetcode.com/problems/ones-and-zeroes/discuss/95811/Java-Iterative-DP-Solution-O(mn)-Space)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月21日
+
+[838. 推多米诺](https://github.com/hollischuang/algorithm/tree/master/leetcode/838-PushDominoes)
+
+[https://leetcode-cn.com/problems/push-dominoes/](https://leetcode-cn.com/problems/push-dominoes/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/articles/push-dominoes/](https://leetcode.com/articles/push-dominoes/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月22日
+
+[790. 多米诺和托米诺平铺](https://github.com/hollischuang/algorithm/tree/master/leetcode/790-DominoAndTrominoTiling)
+
+[https://leetcode-cn.com/problems/domino-and-tromino-tiling/](https://leetcode-cn.com/problems/domino-and-tromino-tiling/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/domino-and-tromino-tiling/discuss/116581/Detail-and-explanation-of-O(n)-solution-why-dpn2*dn-1%2Bdpn-3](https://leetcode.com/problems/domino-and-tromino-tiling/discuss/116581/Detail-and-explanation-of-O(n)-solution-why-dpn2*dn-1%2Bdpn-3)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月23日
+
+[813. 最大平均值和的分组](https://github.com/hollischuang/algorithm/tree/master/leetcode/813-LargestSumOfAverages)
+
+[https://leetcode-cn.com/problems/largest-sum-of-averages/](https://leetcode-cn.com/problems/largest-sum-of-averages/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/largest-sum-of-averages/](https://leetcode.com/articles/largest-sum-of-averages/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月24日
+
+[376. 摆动序列变](https://github.com/hollischuang/algorithm/tree/master/leetcode/367-ValidPerfectSquare)
+
+[https://leetcode-cn.com/problems/wiggle-subsequence/](https://leetcode-cn.com/problems/wiggle-subsequence/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/wiggle-subsequence/](https://leetcode.com/articles/wiggle-subsequence/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月25日
+
+[801. 使序列递增的最小交换次数](https://github.com/hollischuang/algorithm/tree/master/leetcode/801-MinimumSwapsToMakeSequencesIncreasing)
+
+[https://leetcode-cn.com/problems/minimum-swaps-to-make-sequences-increasing/](https://leetcode-cn.com/problems/minimum-swaps-to-make-sequences-increasing/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/minimum-swaps-to-make-sequences-increasing/](https://leetcode.com/articles/minimum-swaps-to-make-sequences-increasing/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月26日
+
+[808. 分汤](https://github.com/hollischuang/algorithm/tree/master/leetcode/808-SoupServings)
+
+[https://leetcode-cn.com/problems/soup-servings/](https://leetcode-cn.com/problems/soup-servings/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/soup-servings/](https://leetcode.com/articles/soup-servings/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月27日
+
+[63. 不同路径 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/063-UniquePathsII)
+
+[https://leetcode-cn.com/problems/unique-paths-ii/](https://leetcode-cn.com/problems/unique-paths-ii/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/unique-paths-ii/](https://leetcode.com/articles/unique-paths-ii/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年02月28日
+
+[213. 打家劫舍 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/213-HouseRobberII)
+
+[https://leetcode-cn.com/problems/house-robber-ii/](https://leetcode-cn.com/problems/house-robber-ii/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/house-robber-ii/discuss/59934/Simple-AC-solution-in-Java-in-O(n)-with-explanation](https://leetcode.com/problems/house-robber-ii/discuss/59934/Simple-AC-solution-in-Java-in-O(n)-with-explanation)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月01日
+
+[368. 最大整除子集](https://github.com/hollischuang/algorithm/tree/master/leetcode/368-LargestDivisibleSubset)
+
+[https://leetcode-cn.com/problems/largest-divisible-subset/](https://leetcode-cn.com/problems/largest-divisible-subset/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/largest-divisible-subset/discuss/84006/Classic-DP-solution-similar-to-LIS-O(n2)](https://leetcode.com/problems/largest-divisible-subset/discuss/84006/Classic-DP-solution-similar-to-LIS-O(n2))
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月02日
+
+[467. 环绕字符串中唯一的子字符串](https://github.com/hollischuang/algorithm/tree/master/leetcode/467-UniqueSubstringsInWraparoundString)
+
+[https://leetcode-cn.com/problems/unique-substrings-in-wraparound-string/](https://leetcode-cn.com/problems/unique-substrings-in-wraparound-string/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/unique-substrings-in-wraparound-string/discuss/95439/Concise-Java-solution-using-DP](https://leetcode.com/problems/unique-substrings-in-wraparound-string/discuss/95439/Concise-Java-solution-using-DP)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月03日
+
+[464. 我能赢吗](https://github.com/hollischuang/algorithm/tree/master/leetcode/464-CanIWin)
+
+[https://leetcode-cn.com/problems/can-i-win/](https://leetcode-cn.com/problems/can-i-win/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/can-i-win/discuss/95277/Java-solution-using-HashMap-with-detailed-explanation](https://leetcode.com/problems/can-i-win/discuss/95277/Java-solution-using-HashMap-with-detailed-explanation)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/can-i-win/discuss/95293/Java-easy-strightforward-solution-with-explanation](https://leetcode.com/problems/can-i-win/discuss/95293/Java-easy-strightforward-solution-with-explanation)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月04日
+
+[935. 骑士拨号器](https://github.com/hollischuang/algorithm/tree/master/leetcode/935-KnightDialer)
+
+[https://leetcode-cn.com/problems/knight-dialer/](https://leetcode-cn.com/problems/knight-dialer/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/knight-dialer/](https://leetcode.com/articles/knight-dialer/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月05日
+
+[787. K 站中转内最便宜的航班](https://github.com/hollischuang/algorithm/tree/master/leetcode/787-CheapestFlightsWithinKStops)
+
+[https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/](https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/115541/JavaPython-Priority-Queue-Solution](https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/115541/JavaPython-Priority-Queue-Solution)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/128776/5-ms-AC-Java-Solution-based-on-Dijkstra's-Algorithm](https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/128776/5-ms-AC-Java-Solution-based-on-Dijkstra's-Algorithm)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月06日
+
+[576. 出界的路径数](https://github.com/hollischuang/algorithm/tree/master/leetcode/576-OutOfBoundaryPaths)
+
+[https://leetcode-cn.com/problems/out-of-boundary-paths/](https://leetcode-cn.com/problems/out-of-boundary-paths/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/out-of-boundary-paths/](https://leetcode.com/articles/out-of-boundary-paths/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月07日
+
+[374. 猜数字大小](https://github.com/hollischuang/algorithm/tree/master/leetcode/374-GuessNumberHigherOrLower)
+
+[https://leetcode-cn.com/problems/guess-number-higher-or-lower/](https://leetcode-cn.com/problems/guess-number-higher-or-lower/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/guess-number-higher-or-lower/](https://leetcode.com/articles/guess-number-higher-or-lower/)
+
+知识点:二分查找
+
+难度:简单
+
+---
+
+2019年03月08日
+
+[375. 猜数字大小 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/375-GuessNumberHigherOrLowerII)
+
+[https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/](https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/guess-number-higher-or-lower-ii/discuss/84764/Simple-DP-solution-with-explanation~~](https://leetcode.com/problems/guess-number-higher-or-lower-ii/discuss/84764/Simple-DP-solution-with-explanation~~)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月09日
+
+[967. 连续差相同的数字](https://github.com/hollischuang/algorithm/tree/master/leetcode/967-NumbersWithSameConsecutiveDifferences)
+
+[https://leetcode-cn.com/problems/numbers-with-same-consecutive-differences/](https://leetcode-cn.com/problems/numbers-with-same-consecutive-differences/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/numbers-with-same-consecutive-differences/](https://leetcode.com/articles/numbers-with-same-consecutive-differences/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月10日
+
+[673. 最长递增子序列的个数](https://github.com/hollischuang/algorithm/tree/master/leetcode/673-NumberOfLongestIncreasingSubsequence)
+
+[https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/](https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/number-of-longest-increasing-subsequence/](https://leetcode.com/articles/number-of-longest-increasing-subsequence/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月11日
+
+[131. 分割回文串](https://github.com/hollischuang/algorithm/tree/master/leetcode/131-PalindromePartitioning)
+
+[https://leetcode-cn.com/problems/palindrome-partitioning/](https://leetcode-cn.com/problems/palindrome-partitioning/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/palindrome-partitioning/discuss/41963/Java%3A-Backtracking-solution.](https://leetcode.com/problems/palindrome-partitioning/discuss/41963/Java%3A-Backtracking-solution.)
+
+知识点:回溯算法
+
+难度:中等
+
+---
+
+2019年03月12日
+
+[132. 分割回文串II](https://github.com/hollischuang/algorithm/tree/master/leetcode/132-PalindromePartitioningII)
+
+[https://leetcode-cn.com/problems/palindrome-partitioning-ii/](https://leetcode-cn.com/problems/palindrome-partitioning-ii/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/palindrome-partitioning-ii/discuss/42198/My-solution-does-not-need-a-table-for-palindrome-is-it-right-It-uses-only-O(n)-space.](https://leetcode.com/problems/palindrome-partitioning-ii/discuss/42198/My-solution-does-not-need-a-table-for-palindrome-is-it-right-It-uses-only-O(n)-space.)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月13日
+
+[5. 最长回文子串](https://github.com/hollischuang/algorithm/tree/master/leetcode/005-LongestPalindromicSubstring)
+
+[https://leetcode-cn.com/problems/longest-palindromic-substring/](https://leetcode-cn.com/problems/longest-palindromic-substring/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/longest-palindromic-substring/](https://leetcode.com/articles/longest-palindromic-substring/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月14日
+
+[523. 连续的子数组和](https://github.com/hollischuang/algorithm/tree/master/leetcode/523-ContinuousSubarraySum)
+
+[https://leetcode-cn.com/problems/continuous-subarray-sum/](https://leetcode-cn.com/problems/continuous-subarray-sum/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/continuous-subarray-sum/discuss/99499/Java-O(n)-time-O(k)-space](https://leetcode.com/problems/continuous-subarray-sum/discuss/99499/Java-O(n)-time-O(k)-space)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月15日
+
+[837. 新21点](https://github.com/hollischuang/algorithm/tree/master/leetcode/837-New21Game)
+
+[https://leetcode-cn.com/problems/new-21-game/](https://leetcode-cn.com/problems/new-21-game/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/new-21-game/](https://leetcode.com/articles/new-21-game/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月16日
+
+[898. 子数组按位或操作](https://github.com/hollischuang/algorithm/tree/master/leetcode/898-BitwiseORsOfSubarrays)
+
+[https://leetcode-cn.com/problems/bitwise-ors-of-subarrays/](https://leetcode-cn.com/problems/bitwise-ors-of-subarrays/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/bitwise-ors-of-subarrays/](https://leetcode.com/articles/bitwise-ors-of-subarrays/)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月17日
+
+[91. 解码方法](https://github.com/hollischuang/algorithm/tree/master/leetcode/091-DecodeWays)
+
+[https://leetcode-cn.com/problems/decode-ways/](https://leetcode-cn.com/problems/decode-ways/)
+
+无官方题解,网友高票Java解法1:
+
+[https://leetcode.com/problems/decode-ways/discuss/30357/DP-Solution-(Java)-for-reference](https://leetcode.com/problems/decode-ways/discuss/30357/DP-Solution-(Java)-for-reference)
+
+无官方题解,网友高票Java解法2:
+
+[https://leetcode.com/problems/decode-ways/discuss/30358/Java-clean-DP-solution-with-explanation](https://leetcode.com/problems/decode-ways/discuss/30358/Java-clean-DP-solution-with-explanation)
+
+知识点:动态规划
+
+难度:中等
+
+---
+
+2019年03月18日
+
+[312. 戳气球](https://github.com/hollischuang/algorithm/tree/master/leetcode/312-BurstBalloons)
+
+[https://leetcode-cn.com/problems/burst-balloons/](https://leetcode-cn.com/problems/burst-balloons/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/burst-balloons/discuss/76228/Share-some-analysis-and-explanations](https://leetcode.com/problems/burst-balloons/discuss/76228/Share-some-analysis-and-explanations)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月19日
+
+[72. 编辑距离](https://github.com/hollischuang/algorithm/tree/master/leetcode/072-EditDistance)
+
+[https://leetcode-cn.com/problems/edit-distance/](https://leetcode-cn.com/problems/edit-distance/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/edit-distance/discuss/25849/Java-DP-solution-O(nm)](https://leetcode.com/problems/edit-distance/discuss/25849/Java-DP-solution-O(nm))
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月20日
+
+[975. 奇偶跳](https://github.com/hollischuang/algorithm/tree/master/leetcode/975-OddEvenJump)
+
+[https://leetcode-cn.com/problems/odd-even-jump/](https://leetcode-cn.com/problems/odd-even-jump/)
+
+官方题解:
+
+[https://leetcode-cn.com/articles/odd-even-jump/](https://leetcode-cn.com/articles/odd-even-jump/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月21日
+
+[115. 不同的子序列](https://github.com/hollischuang/algorithm/tree/master/leetcode/115-DistinctSubsequences)
+
+[https://leetcode-cn.com/problems/distinct-subsequences/](https://leetcode-cn.com/problems/distinct-subsequences/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/distinct-subsequences/discuss/37327/Easy-to-understand-DP-in-Java](https://leetcode.com/problems/distinct-subsequences/discuss/37327/Easy-to-understand-DP-in-Java)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月22日
+
+[940. 不同的子序列 II](https://github.com/hollischuang/algorithm/tree/master/leetcode/940-DistinctSubsequencesII)
+
+[https://leetcode-cn.com/problems/distinct-subsequences-ii/](https://leetcode-cn.com/problems/distinct-subsequences-ii/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/distinct-subsequences-ii/](https://leetcode.com/articles/distinct-subsequences-ii/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月23日
+
+[691. 贴纸拼词](https://github.com/hollischuang/algorithm/tree/master/leetcode/691-StickersToSpellWord)
+
+[https://leetcode-cn.com/problems/stickers-to-spell-word/](https://leetcode-cn.com/problems/stickers-to-spell-word/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/stickers-to-spell-word/](https://leetcode.com/articles/stickers-to-spell-word/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月24日
+
+[982. 按位与为零的三元组](https://github.com/hollischuang/algorithm/tree/master/leetcode/982-TriplesWithBitwiseANDEqualToZero)
+
+[https://leetcode-cn.com/problems/triples-with-bitwise-and-equal-to-zero/](https://leetcode-cn.com/problems/triples-with-bitwise-and-equal-to-zero/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/triples-with-bitwise-and-equal-to-zero/discuss/226721/Java-DP-O(3-*-216-*-n)-time-O(216)-space](https://leetcode.com/problems/triples-with-bitwise-and-equal-to-zero/discuss/226721/Java-DP-O(3-*-216-*-n)-time-O(216)-space)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月25日
+
+[546. 移除盒子](https://github.com/hollischuang/algorithm/tree/master/leetcode/546-RemoveBoxes)
+
+[https://leetcode-cn.com/problems/remove-boxes/](https://leetcode-cn.com/problems/remove-boxes/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/remove-boxes/discuss/101310/Java-top-down-and-bottom-up-DP-solutions](https://leetcode.com/problems/remove-boxes/discuss/101310/Java-top-down-and-bottom-up-DP-solutions)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月26日
+
+[85. 最大矩形](https://github.com/hollischuang/algorithm/tree/master/leetcode/085-MaximalRectangle)
+
+[https://leetcode-cn.com/problems/maximal-rectangle/](https://leetcode-cn.com/problems/maximal-rectangle/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/maximal-rectangle/discuss/29054/Share-my-DP-solution](https://leetcode.com/problems/maximal-rectangle/discuss/29054/Share-my-DP-solution)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月27日
+
+[903. DI 序列的有效排列](https://github.com/hollischuang/algorithm/tree/master/leetcode/903-ValidPermutationsForDISequence)
+
+[https://leetcode-cn.com/problems/valid-permutations-for-di-sequence/](https://leetcode-cn.com/problems/valid-permutations-for-di-sequence/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/valid-permutations-for-di-sequence/](https://leetcode.com/articles/valid-permutations-for-di-sequence/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月28日
+
+[629. K个逆序对数组](https://github.com/hollischuang/algorithm/tree/master/leetcode/629-KInversePairsArray)
+
+[https://leetcode-cn.com/problems/k-inverse-pairs-array/](https://leetcode-cn.com/problems/k-inverse-pairs-array/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/k-inverse-pairs-array/](https://leetcode.com/articles/k-inverse-pairs-array/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月29日
+
+[956. 最高的广告牌](https://github.com/hollischuang/algorithm/tree/master/leetcode/629-KInversePairsArray)
+
+[https://leetcode-cn.com/problems/tallest-billboard/](https://leetcode-cn.com/problems/tallest-billboard/)
+
+英文官方题解:
+
+[https://leetcode.com/problems/tallest-billboard/solution/](https://leetcode.com/problems/tallest-billboard/solution/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年03月30日
+
+[664. 奇怪的打印机](https://github.com/hollischuang/algorithm/tree/master/leetcode/629-KInversePairsArray)
+
+[https://leetcode-cn.com/problems/strange-printer/](https://leetcode-cn.com/problems/strange-printer/)
+
+英文官方题解:
+
+[https://leetcode.com/problems/strange-printer/solution/](https://leetcode.com/problems/strange-printer/solution/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年04月01日
+
+[943. 最短超级串](https://github.com/hollischuang/algorithm/tree/master/leetcode/943-FindTheShortestSuperstring)
+
+[https://leetcode-cn.com/problems/find-the-shortest-superstring/](https://leetcode-cn.com/problems/find-the-shortest-superstring/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/find-the-shortest-superstring/](https://leetcode.com/articles/find-the-shortest-superstring/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+2019年04月02日
+
+[32. 最长有效括号](https://github.com/hollischuang/algorithm/tree/master/leetcode/032-LongestValidParentheses)
+
+[https://leetcode-cn.com/problems/longest-valid-parentheses/](https://leetcode-cn.com/problems/longest-valid-parentheses/)
+
+英文官方题解:
+
+[https://leetcode.com/articles/longest-valid-parentheses/](https://leetcode.com/articles/longest-valid-parentheses/)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+
+2019年04月03日
+
+[403. 青蛙过河](https://github.com/hollischuang/algorithm/tree/master/leetcode/403-FrogJump)
+
+[https://leetcode-cn.com/problems/frog-jump/](https://leetcode-cn.com/problems/frog-jump/)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/frog-jump/discuss/88824/Very-easy-to-understand-JAVA-solution-with-explanations](https://leetcode.com/problems/frog-jump/discuss/88824/Very-easy-to-understand-JAVA-solution-with-explanations)
+
+知识点:动态规划
+
+难度:困难
+
+---
+
+
+2019年04月04日
+
+[321. 拼接最大数](https://github.com/hollischuang/algorithm/tree/master/leetcode/321-CreateMaximumNumber)
+
+[https://leetcode.com/problems/create-maximum-number/discuss/77285/Share-my-greedy-solution](https://leetcode.com/problems/create-maximum-number/discuss/77285/Share-my-greedy-solution)
+
+无官方题解,网友高票Java解法:
+
+[https://leetcode.com/problems/frog-jump/discuss/88824/Very-easy-to-understand-JAVA-solution-with-explanations](https://leetcode.com/problems/frog-jump/discuss/88824/Very-easy-to-understand-JAVA-solution-with-explanations)
+
+知识点:动态规划
+
+难度:困难
+
+---
diff --git a/solutions/images/017_Telephone-keypad2.png b/solutions/images/017_Telephone-keypad2.png
new file mode 100644
index 0000000..3876402
Binary files /dev/null and b/solutions/images/017_Telephone-keypad2.png differ
diff --git a/solutions/images/160_example_1.png b/solutions/images/160_example_1.png
new file mode 100644
index 0000000..dc20482
Binary files /dev/null and b/solutions/images/160_example_1.png differ
diff --git a/solutions/images/160_example_2.png b/solutions/images/160_example_2.png
new file mode 100644
index 0000000..8a57d6c
Binary files /dev/null and b/solutions/images/160_example_2.png differ
diff --git a/solutions/images/160_example_3.png b/solutions/images/160_example_3.png
new file mode 100644
index 0000000..6f8e524
Binary files /dev/null and b/solutions/images/160_example_3.png differ
diff --git a/solutions/images/160_statement.png b/solutions/images/160_statement.png
new file mode 100644
index 0000000..ede5121
Binary files /dev/null and b/solutions/images/160_statement.png differ
diff --git a/solutions/leetcode/001-twoSum/README.md b/solutions/leetcode/001-twoSum/README.md
new file mode 100644
index 0000000..7ecda74
--- /dev/null
+++ b/solutions/leetcode/001-twoSum/README.md
@@ -0,0 +1,16 @@
+**1. 两数之和**
+---
+[https://leetcode-cn.com/problems/two-sum/](https://leetcode-cn.com/problems/two-sum/)
+
+给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
+
+你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
+
+**示例:**
+
+```
+给定 nums = [2, 7, 11, 15], target = 9
+
+因为 nums[0] + nums[1] = 2 + 7 = 9
+所以返回 [0, 1]
+```
diff --git a/leetcode/001-twoSum/hatrick.md b/solutions/leetcode/001-twoSum/hatrick.md
similarity index 100%
rename from leetcode/001-twoSum/hatrick.md
rename to solutions/leetcode/001-twoSum/hatrick.md
diff --git a/leetcode/001-twoSum/woody.md b/solutions/leetcode/001-twoSum/woody.md
similarity index 100%
rename from leetcode/001-twoSum/woody.md
rename to solutions/leetcode/001-twoSum/woody.md
diff --git a/solutions/leetcode/002-addTwoNumber/README.md b/solutions/leetcode/002-addTwoNumber/README.md
new file mode 100644
index 0000000..8dc4992
--- /dev/null
+++ b/solutions/leetcode/002-addTwoNumber/README.md
@@ -0,0 +1,17 @@
+**2. 两数相加**
+---
+[https://leetcode-cn.com/problems/add-two-numbers/](https://leetcode-cn.com/problems/add-two-numbers/)
+
+给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
+
+如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
+
+您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
+
+**示例:**
+
+```
+输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
+输出:7 -> 0 -> 8
+原因:342 + 465 = 807
+```
diff --git a/leetcode/002-addTwoNumber/monkey.md b/solutions/leetcode/002-addTwoNumber/monkey.md
similarity index 100%
rename from leetcode/002-addTwoNumber/monkey.md
rename to solutions/leetcode/002-addTwoNumber/monkey.md
diff --git a/solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/README.md b/solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/README.md
new file mode 100644
index 0000000..f05424e
--- /dev/null
+++ b/solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/README.md
@@ -0,0 +1,30 @@
+**3. 无重复字符的最长子串**
+---
+[https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/)
+
+给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
+
+**示例 1:**
+
+```
+输入: "abcabcbb"
+输出: 3
+解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
+```
+
+**示例 2:**
+
+```
+输入: "bbbbb"
+输出: 1
+解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
+```
+
+**示例 3:**
+
+```
+输入: "pwwkew"
+输出: 3
+解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
+ 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
+```
diff --git a/leetcode/003-longestSubstringWithoutRepeatingCharacters/monkey.md b/solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/monkey.md
similarity index 100%
rename from leetcode/003-longestSubstringWithoutRepeatingCharacters/monkey.md
rename to solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/monkey.md
diff --git a/solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/zengdiqing1994.md b/solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/zengdiqing1994.md
new file mode 100644
index 0000000..2bdab90
--- /dev/null
+++ b/solutions/leetcode/003-longestSubstringWithoutRepeatingCharacters/zengdiqing1994.md
@@ -0,0 +1,42 @@
+3.给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
+
+示例 1:
+
+输入: "abcabcbb"
+输出: 3
+解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
+示例 2:
+
+输入: "bbbbb"
+输出: 1
+解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
+示例 3:
+
+输入: "pwwkew"
+输出: 3
+解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
+ 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
+
+思路:
+
+```py
+ def lengthOfLongestSubstring(self, s):
+ lookup = collections.defaultdict(int)
+ l, r, counter, res = 0, 0, 0, 0 # counter 为当前子串中 unique 字符的数量
+ while r < len(s):
+ lookup[s[r]] += 1
+ if lookup[s[r]] == 1: # 遇到了当前子串中未出现过的字符
+ counter += 1
+ r += 1
+ # counter < r - l 说明有重复字符出现,否则 counter 应该等于 r - l
+ while l < r and counter < r - l:
+ lookup[s[l]] -= 1
+ if lookup[s[l]] == 0: # 当前子串中的一种字符完全消失了
+ counter -= 1
+ l += 1
+ res = max(res, r - l) # 当前子串满足条件了,更新最大长度
+ return res
+```
+时间复杂度:O(n^2)
+
+空间复杂度:O(n)
diff --git a/leetcode/005-LongestPalindromicSubstring/hatrick.md b/solutions/leetcode/005-LongestPalindromicSubstring/hatrick.md
similarity index 100%
rename from leetcode/005-LongestPalindromicSubstring/hatrick.md
rename to solutions/leetcode/005-LongestPalindromicSubstring/hatrick.md
diff --git a/leetcode/005-LongestPalindromicSubstring/official.md b/solutions/leetcode/005-LongestPalindromicSubstring/official.md
similarity index 100%
rename from leetcode/005-LongestPalindromicSubstring/official.md
rename to solutions/leetcode/005-LongestPalindromicSubstring/official.md
diff --git a/solutions/leetcode/006-ZigZagConversion/README.md b/solutions/leetcode/006-ZigZagConversion/README.md
new file mode 100644
index 0000000..3252cff
--- /dev/null
+++ b/solutions/leetcode/006-ZigZagConversion/README.md
@@ -0,0 +1,41 @@
+**6. Z 字形变换**
+---
+[https://leetcode-cn.com/problems/zigzag-conversion/](https://leetcode-cn.com/problems/zigzag-conversion/)
+
+将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
+
+比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
+
+```
+L C I R
+E T O E S I I G
+E D H N
+```
+
+之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。
+
+请你实现这个将字符串进行指定行数变换的函数:
+
+```
+string convert(string s, int numRows);
+```
+
+**示例 1:**
+
+```
+输入: s = "LEETCODEISHIRING", numRows = 3
+输出: "LCIRETOESIIGEDHN"
+```
+
+**示例 2:**
+
+```
+输入: s = "LEETCODEISHIRING", numRows = 4
+输出: "LDREOEIIECIHNTSG"
+解释:
+
+L D R
+E O E I I
+E C I H N
+T S G
+```
diff --git a/solutions/leetcode/006-ZigZagConversion/zengdiqing.md b/solutions/leetcode/006-ZigZagConversion/zengdiqing.md
new file mode 100644
index 0000000..1882f4c
--- /dev/null
+++ b/solutions/leetcode/006-ZigZagConversion/zengdiqing.md
@@ -0,0 +1,51 @@
+6.将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
+
+比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
+
+L C I R
+E T O E S I I G
+E D H N
+之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。
+
+请你实现这个将字符串进行指定行数变换的函数:
+
+string convert(string s, int numRows);
+示例 1:
+
+输入: s = "LEETCODEISHIRING", numRows = 3
+输出: "LCIRETOESIIGEDHN"
+示例 2:
+
+输入: s = "LEETCODEISHIRING", numRows = 4
+输出: "LDREOEIIECIHNTSG"
+解释:
+
+L D R
+E O E I I
+E C I H N
+T S G
+
+思路:idx从0开始,自增直到numRows-1,此后又一直自减到0,重复执行。
+
+从第一行开始往下,走到第四行又往上走,这里用 step = 1 代表往下走, step = -1 代表往上走
+
+因为只会有一次遍历,同时把每一行的元素都存下来,所以时间复杂度和空间复杂度都是 O(N)
+
+```py
+class Solution:
+ def convert(self, s: str, numRows: int) -> str:
+ if numRows==1 or numRows>=len(s):
+ return s #判断情况
+ res = [''] * numRows #初始化res结果
+ idx, step = 0, 1
+ for c in s:
+ res[idx] += c #把字符加入res中
+ if idx == 0:
+ step = 1 #step向下加一
+ elif idx == numRows-1: #一直到最后一行为止
+ step = -1 #向上操作
+ idx += step #idx代表第几行
+ return ''.join(res)
+```
+时间复杂度: O(n)
+空间复杂度: O(1)
diff --git a/leetcode/015-threeSum/hatrick.md b/solutions/leetcode/015-threeSum/hatrick.md
similarity index 100%
rename from leetcode/015-threeSum/hatrick.md
rename to solutions/leetcode/015-threeSum/hatrick.md
diff --git a/leetcode/015-threeSum/official.md b/solutions/leetcode/015-threeSum/official.md
similarity index 100%
rename from leetcode/015-threeSum/official.md
rename to solutions/leetcode/015-threeSum/official.md
diff --git a/solutions/leetcode/017-LetterCombinationsOfAPhoneNumber/README.md b/solutions/leetcode/017-LetterCombinationsOfAPhoneNumber/README.md
new file mode 100644
index 0000000..bcb6e78
--- /dev/null
+++ b/solutions/leetcode/017-LetterCombinationsOfAPhoneNumber/README.md
@@ -0,0 +1,18 @@
+**17. 电话号码的字母组合**
+---
+[https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)
+
+给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
+
+给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
+
+
+**示例:**
+
+```
+输入:"23"
+输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
+```
+
+**说明:**
+尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
diff --git a/leetcode/020-validParentheses/official.md b/solutions/leetcode/020-validParentheses/official.md
similarity index 100%
rename from leetcode/020-validParentheses/official.md
rename to solutions/leetcode/020-validParentheses/official.md
diff --git a/solutions/leetcode/023-MergeKSortedLists/README.md b/solutions/leetcode/023-MergeKSortedLists/README.md
new file mode 100644
index 0000000..7ebf242
--- /dev/null
+++ b/solutions/leetcode/023-MergeKSortedLists/README.md
@@ -0,0 +1,17 @@
+**23. 合并K个排序链表**
+---
+[https://leetcode-cn.com/problems/merge-k-sorted-lists/](https://leetcode-cn.com/problems/merge-k-sorted-lists/)
+
+合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
+
+**示例:**
+
+```
+输入:
+[
+ 1->4->5,
+ 1->3->4,
+ 2->6
+]
+输出: 1->1->2->3->4->4->5->6
+```
diff --git a/leetcode/024-swapNodesInPairs/official.md b/solutions/leetcode/024-swapNodesInPairs/official.md
similarity index 100%
rename from leetcode/024-swapNodesInPairs/official.md
rename to solutions/leetcode/024-swapNodesInPairs/official.md
diff --git a/leetcode/025-reverseNodesInKGroup/bigablecat.md b/solutions/leetcode/025-reverseNodesInKGroup/bigablecat.md
similarity index 100%
rename from leetcode/025-reverseNodesInKGroup/bigablecat.md
rename to solutions/leetcode/025-reverseNodesInKGroup/bigablecat.md
diff --git a/leetcode/025-reverseNodesInKGroup/official.md b/solutions/leetcode/025-reverseNodesInKGroup/official.md
similarity index 100%
rename from leetcode/025-reverseNodesInKGroup/official.md
rename to solutions/leetcode/025-reverseNodesInKGroup/official.md
diff --git a/solutions/leetcode/032-LongestValidParentheses/official.md b/solutions/leetcode/032-LongestValidParentheses/official.md
new file mode 100644
index 0000000..181dca1
--- /dev/null
+++ b/solutions/leetcode/032-LongestValidParentheses/official.md
@@ -0,0 +1,3 @@
+**32. 最长有效括号**
+---
+[https://leetcode-cn.com/problems/longest-valid-parentheses/](https://leetcode-cn.com/problems/longest-valid-parentheses/)
diff --git a/solutions/leetcode/033-SearchInRotatedSortedArray/README.md b/solutions/leetcode/033-SearchInRotatedSortedArray/README.md
new file mode 100644
index 0000000..9c693c7
--- /dev/null
+++ b/solutions/leetcode/033-SearchInRotatedSortedArray/README.md
@@ -0,0 +1,27 @@
+**33. 搜索旋转排序数组**
+---
+[https://leetcode-cn.com/problems/search-in-rotated-sorted-array/](https://leetcode-cn.com/problems/search-in-rotated-sorted-array/)
+
+假设按照升序排序的数组在预先未知的某个点上进行了旋转。
+
+( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
+
+搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
+
+你可以假设数组中不存在重复的元素。
+
+你的算法时间复杂度必须是 O(log n) 级别。
+
+**示例 1:**
+
+```
+输入: nums = [4,5,6,7,0,1,2], target = 0
+输出: 4
+```
+
+**示例 2:**
+
+```
+输入: nums = [4,5,6,7,0,1,2], target = 3
+输出: -1
+```
diff --git a/solutions/leetcode/033-SearchInRotatedSortedArray/zengdiqing1994.md b/solutions/leetcode/033-SearchInRotatedSortedArray/zengdiqing1994.md
new file mode 100644
index 0000000..2933550
--- /dev/null
+++ b/solutions/leetcode/033-SearchInRotatedSortedArray/zengdiqing1994.md
@@ -0,0 +1,64 @@
+33.假设按照升序排序的数组在预先未知的某个点上进行了旋转。
+
+( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
+
+搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
+
+你可以假设数组中不存在重复的元素。
+
+你的算法时间复杂度必须是 O(log n) 级别。
+
+示例 1:
+
+输入: nums = [4,5,6,7,0,1,2], target = 0
+输出: 4
+示例 2:
+
+输入: nums = [4,5,6,7,0,1,2], target = 3
+输出: -1
+
+思路:二分法
+
+这道题让在旋转数组中搜索一个给定值,若存在返回坐标,若不存在返回-1。我们还是考虑二分搜索法,但是这道题的难点在于我们不知道原数组在哪旋转了,我们还是
+用题目中给的例子来分析,对于数组[0 1 2 4 5 6 7] 共有下列七种旋转方法:
+
+0 1 2 **4 5 6 7**
+
+7 0 1 2 4 5 6
+
+6 7 0 1 2 4 5
+
+5 6 7 0 1 2 4
+
+4 5 6 7 0 1 2
+
+2 4 5 6 7 0 1
+
+1 2 4 5 6 7 0
+
+二分搜索法的关键在于获得了中间数后,判断下面要搜索左半段还是右半段,我们观察上面粗体的数字都是升序的,由此我们可以观察出规律,如果中间的数小于最右边
+的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的,我们只要在有序的半段里用首尾两个数组来判断目标值是否在这一区域内,这样就可以确定保留
+哪半边了.
+
+```py
+def search(nums,target):
+ l, r = 0, len(nums) - 1
+ while l < r:
+ mid = l + ((r-l)>>2)
+ if nums[mid] == target:
+ return mid
+ if nums[mid] < nums[r]:
+ if nums[mid] < target <= nums[r]:
+ l = mid + 1
+ else:
+ r = mid - 1
+ else:
+ if nums[l] <= target < nums[mid]
+ r = mid - 1
+ else:
+ l = mid + 1
+ return -1
+```
+
+时间复杂度:O(lgn)
+空间复杂度:O(1)
diff --git a/leetcode/036-ValidSudoku/SpecialYang.md b/solutions/leetcode/036-ValidSudoku/SpecialYang.md
similarity index 100%
rename from leetcode/036-ValidSudoku/SpecialYang.md
rename to solutions/leetcode/036-ValidSudoku/SpecialYang.md
diff --git a/leetcode/036-ValidSudoku/official.md b/solutions/leetcode/036-ValidSudoku/official.md
similarity index 100%
rename from leetcode/036-ValidSudoku/official.md
rename to solutions/leetcode/036-ValidSudoku/official.md
diff --git a/leetcode/037-SudokuSolver/SpecialYang.md b/solutions/leetcode/037-SudokuSolver/SpecialYang.md
similarity index 100%
rename from leetcode/037-SudokuSolver/SpecialYang.md
rename to solutions/leetcode/037-SudokuSolver/SpecialYang.md
diff --git a/leetcode/037-SudokuSolver/official.md b/solutions/leetcode/037-SudokuSolver/official.md
similarity index 100%
rename from leetcode/037-SudokuSolver/official.md
rename to solutions/leetcode/037-SudokuSolver/official.md
diff --git a/solutions/leetcode/048-RotateImage/README.md b/solutions/leetcode/048-RotateImage/README.md
new file mode 100644
index 0000000..7b78dec
--- /dev/null
+++ b/solutions/leetcode/048-RotateImage/README.md
@@ -0,0 +1,50 @@
+**48. 旋转图像**
+---
+[https://leetcode-cn.com/problems/rotate-image/](https://leetcode-cn.com/problems/rotate-image/)
+
+给定一个 n × n 的二维矩阵表示一个图像。
+
+将图像顺时针旋转 90 度。
+
+**说明:**
+
+你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。
+请**不要**使用另一个矩阵来旋转图像。
+
+**示例 1:**
+
+```
+给定 matrix =
+[
+ [1,2,3],
+ [4,5,6],
+ [7,8,9]
+],
+
+原地旋转输入矩阵,使其变为:
+[
+ [7,4,1],
+ [8,5,2],
+ [9,6,3]
+]
+```
+
+**示例 2:**
+
+```
+给定 matrix =
+[
+ [ 5, 1, 9,11],
+ [ 2, 4, 8,10],
+ [13, 3, 6, 7],
+ [15,14,12,16]
+],
+
+原地旋转输入矩阵,使其变为:
+[
+ [15,13, 2, 5],
+ [14, 3, 4, 1],
+ [12, 6, 8, 9],
+ [16, 7,10,11]
+]
+```
diff --git a/solutions/leetcode/048-RotateImage/zengdiqing.md b/solutions/leetcode/048-RotateImage/zengdiqing.md
new file mode 100644
index 0000000..9bea58f
--- /dev/null
+++ b/solutions/leetcode/048-RotateImage/zengdiqing.md
@@ -0,0 +1,51 @@
+48.你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
+
+示例 1:
+
+给定 matrix =
+[
+ [1,2,3],
+ [4,5,6],
+ [7,8,9]
+],
+
+原地旋转输入矩阵,使其变为:
+[
+ [7,4,1],
+ [8,5,2],
+ [9,6,3]
+]
+示例 2:
+
+给定 matrix =
+[
+ [ 5, 1, 9,11],
+ [ 2, 4, 8,10],
+ [13, 3, 6, 7],
+ [15,14,12,16]
+],
+
+原地旋转输入矩阵,使其变为:
+[
+ [15,13, 2, 5],
+ [14, 3, 4, 1],
+ [12, 6, 8, 9],
+ [16, 7,10,11]
+]
+
+思路:先用一个临时变量放置非对角线的数字,然后再把几行数组反过来排列
+
+```
+def rotate(matrix):
+ length = len(matrix)
+ for i in range(length):
+ for j in range(i+1,length):
+ temp = matrix[i][j]
+ matrix[i][j] = matrix[j][i]
+ matrix[j][i] = temp
+ for i in range(length):
+ matrix[i] = matrix[i][::-1]
+ return matrix
+```
+时间复杂度:O(n^2)
+空间复杂度:O(n)
diff --git a/leetcode/050-powxN/bigablecat.md b/solutions/leetcode/050-powxN/bigablecat.md
similarity index 100%
rename from leetcode/050-powxN/bigablecat.md
rename to solutions/leetcode/050-powxN/bigablecat.md
diff --git a/leetcode/051-NQueens/melody-l.md b/solutions/leetcode/051-NQueens/melody-l.md
similarity index 100%
rename from leetcode/051-NQueens/melody-l.md
rename to solutions/leetcode/051-NQueens/melody-l.md
diff --git a/leetcode/051-NQueens/official.md b/solutions/leetcode/051-NQueens/official.md
similarity index 100%
rename from leetcode/051-NQueens/official.md
rename to solutions/leetcode/051-NQueens/official.md
diff --git a/leetcode/052-N-QueensII/hatrick.md b/solutions/leetcode/052-N-QueensII/hatrick.md
similarity index 100%
rename from leetcode/052-N-QueensII/hatrick.md
rename to solutions/leetcode/052-N-QueensII/hatrick.md
diff --git a/leetcode/052-N-QueensII/official.md b/solutions/leetcode/052-N-QueensII/official.md
similarity index 100%
rename from leetcode/052-N-QueensII/official.md
rename to solutions/leetcode/052-N-QueensII/official.md
diff --git a/leetcode/053-maximumSubarray/BambooYH.md b/solutions/leetcode/053-maximumSubarray/BambooYH.md
similarity index 100%
rename from leetcode/053-maximumSubarray/BambooYH.md
rename to solutions/leetcode/053-maximumSubarray/BambooYH.md
diff --git a/solutions/leetcode/053-maximumSubarray/README.md b/solutions/leetcode/053-maximumSubarray/README.md
new file mode 100644
index 0000000..9c320ca
--- /dev/null
+++ b/solutions/leetcode/053-maximumSubarray/README.md
@@ -0,0 +1,13 @@
+**53. 最大子序和**
+---
+[https://leetcode-cn.com/problems/maximum-subarray/](https://leetcode-cn.com/problems/maximum-subarray/)
+
+给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
+
+**示例:**
+
+```
+输入: [-2,1,-3,4,-1,2,1,-5,4],
+输出: 6
+解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
+```
diff --git a/solutions/leetcode/053-maximumSubarray/zengdiqing1994.md b/solutions/leetcode/053-maximumSubarray/zengdiqing1994.md
new file mode 100644
index 0000000..4c4c9e1
--- /dev/null
+++ b/solutions/leetcode/053-maximumSubarray/zengdiqing1994.md
@@ -0,0 +1,26 @@
+53.给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
+
+示例:
+
+输入: [-2,1,-3,4,-1,2,1,-5,4],
+输出: 6
+解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
+
+思路:用DP来求解,只关注:当前值和当前值+过去的状态,是变好还是变坏
+
+状态定义方程:maxSum = [nums[0] for i in range(n)]
+
+状态转移:maxSum[i] = max(maxSum[i-1] + nums[i],nums[i]),一个是加上nums[i]的,另一个是从a[i]起头,重新开始。
+
+```py
+class Solution:
+ def maxSubArray(self, nums: List[int]) -> int:
+ n = len(nums)
+ maxSum = [nums[0] for i in range(n)]
+ for i in range(1,n):
+ maxSum[i] = max(maxSum[i-1] + nums[i],nums[i])
+ return max(maxSum)
+```
+
+时间复杂度O(n)
+空间复杂度O(1)
diff --git a/solutions/leetcode/054-SpiralMatrix/README.md b/solutions/leetcode/054-SpiralMatrix/README.md
new file mode 100644
index 0000000..3dbac1c
--- /dev/null
+++ b/solutions/leetcode/054-SpiralMatrix/README.md
@@ -0,0 +1,29 @@
+**54. 螺旋矩阵**
+---
+[https://leetcode-cn.com/problems/spiral-matrix/](https://leetcode-cn.com/problems/spiral-matrix/)
+
+给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
+
+**示例 1:**
+
+```
+输入:
+[
+ [ 1, 2, 3 ],
+ [ 4, 5, 6 ],
+ [ 7, 8, 9 ]
+]
+输出: [1,2,3,6,9,8,7,4,5]
+```
+
+**示例 2:**
+
+```
+输入:
+[
+ [1, 2, 3, 4],
+ [5, 6, 7, 8],
+ [9,10,11,12]
+]
+输出: [1,2,3,4,8,12,11,10,9,5,6,7]
+```
diff --git a/solutions/leetcode/054-SpiralMatrix/zengdiqing1994.md b/solutions/leetcode/054-SpiralMatrix/zengdiqing1994.md
new file mode 100644
index 0000000..0690c7f
--- /dev/null
+++ b/solutions/leetcode/054-SpiralMatrix/zengdiqing1994.md
@@ -0,0 +1,56 @@
+54.给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
+
+示例 1:
+
+输入:
+[
+ [ 1, 2, 3 ],
+ [ 4, 5, 6 ],
+ [ 7, 8, 9 ]
+]
+输出: [1,2,3,6,9,8,7,4,5]
+示例 2:
+
+输入:
+[
+ [1, 2, 3, 4],
+ [5, 6, 7, 8],
+ [9,10,11,12]
+]
+输出: [1,2,3,4,8,12,11,10,9,5,6,7]
+
+思路:用四个变量来控制辩解,方向总是“左右上下”,这个和Z字形变换很像。
+
+```py
+def spiralOrder(matrix):
+ if matrix == []:
+ return []
+ res = []
+ maxUp = maxLeft = 0
+ maxDown = len(matrix) - 1
+ maxRight = len(matrix[0]) - 1
+ direction = 0 # 0 go right , 1 go down, 2 go left, 3 up
+ while True:
+ if direction == 0: # go right
+ for i in range(maxLeft,maxRight+1):
+ res.append(matrix[maxUp][i])
+ maxUp += 1
+ elif direction == 1: # 1 go down
+ for i in range(maxUp,maxDown+1):
+ res.append(matrix[i][maxRight])
+ maxRight -= 1
+ elif direction == 2: # go left
+ for i in reversed(range(maxLeft,maxRight+1)):
+ res.append(matrix[maxDown][i])
+ maxDown -= 1
+ else: # go up
+ for i in reversed(range(maxUp,maxDown+1)):
+ res.append(matrix[i][maxLeft])
+ maxLeft += 1
+ if maxUp > maxDown or maxLeft > maxRight:
+ return res
+ direction = (direction + 1) % 4 # direction = 3之后就是0重新开始
+```
+时间复杂度:O(m*n)
+
+空间复杂度:O(1)
diff --git a/solutions/leetcode/059-SpiralMatrixII/README.md b/solutions/leetcode/059-SpiralMatrixII/README.md
new file mode 100644
index 0000000..15b513c
--- /dev/null
+++ b/solutions/leetcode/059-SpiralMatrixII/README.md
@@ -0,0 +1,18 @@
+**59. 螺旋矩阵 II**
+---
+[https://leetcode-cn.com/problems/spiral-matrix-ii/](https://leetcode-cn.com/problems/spiral-matrix-ii/)
+
+给定一个正整数 n,生成一个包含 1 到 n2 所有元素,
+且元素按顺时针顺序螺旋排列的正方形矩阵。
+
+**示例:**
+
+```
+输入: 3
+输出:
+[
+ [ 1, 2, 3 ],
+ [ 8, 9, 4 ],
+ [ 7, 6, 5 ]
+]
+```
diff --git a/solutions/leetcode/059-SpiralMatrixII/zengdiqing1994.md b/solutions/leetcode/059-SpiralMatrixII/zengdiqing1994.md
new file mode 100644
index 0000000..e4d7bad
--- /dev/null
+++ b/solutions/leetcode/059-SpiralMatrixII/zengdiqing1994.md
@@ -0,0 +1,49 @@
+59.给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
+
+示例:
+
+输入: 3
+输出:
+[
+ [ 1, 2, 3 ],
+ [ 8, 9, 4 ],
+ [ 7, 6, 5 ]
+]
+
+思路:和之前的那道螺旋矩阵题类似,只不过这次要自己生成一个矩阵
+
+```py
+class Solution:
+ def generateMatrix(self, n: int) -> List[List[int]]:
+ curNum = 0
+ matrix = [[0 for i in range(n)] for j in range(n)] #生成一个矩阵
+ maxUp = maxLeft = 0
+ maxDown = maxRight = n - 1
+ direction = 0
+ while True:
+ if direction == 0:
+ for i in range(maxLeft,maxRight+1):
+ curNum += 1
+ matrix[maxUp][i] = curNum #依次按顺序递增赋值
+ maxUp += 1
+ elif direction == 1:
+ for i in range(maxUp,maxDown+1):
+ curNum += 1
+ matrix[i][maxRight] = curNum
+ maxRight -= 1
+ elif direction == 2:
+ for i in reversed(range(maxLeft,maxRight+1)):
+ curNum += 1
+ matrix[maxDown][i] = curNum
+ maxDown -= 1
+ else:
+ for i in reversed(range(maxUp,maxDown+1)):
+ curNum += 1
+ matrix[i][maxLeft] = curNum
+ maxLeft += 1
+ if curNum >= n*n:
+ return matrix
+ direction = (direction + 1) % 4
+```
+时间复杂度O(N^2)
+空间复杂度O(N)
diff --git a/leetcode/062-UniquePaths/BambooYH.md b/solutions/leetcode/062-UniquePaths/BambooYH.md
similarity index 100%
rename from leetcode/062-UniquePaths/BambooYH.md
rename to solutions/leetcode/062-UniquePaths/BambooYH.md
diff --git a/leetcode/062-UniquePaths/official.md b/solutions/leetcode/062-UniquePaths/official.md
similarity index 100%
rename from leetcode/062-UniquePaths/official.md
rename to solutions/leetcode/062-UniquePaths/official.md
diff --git a/leetcode/063-UniquePathsII/SpecialYang.md b/solutions/leetcode/063-UniquePathsII/SpecialYang.md
similarity index 100%
rename from leetcode/063-UniquePathsII/SpecialYang.md
rename to solutions/leetcode/063-UniquePathsII/SpecialYang.md
diff --git a/leetcode/063-UniquePathsII/official.md b/solutions/leetcode/063-UniquePathsII/official.md
similarity index 100%
rename from leetcode/063-UniquePathsII/official.md
rename to solutions/leetcode/063-UniquePathsII/official.md
diff --git a/solutions/leetcode/064-minimumPathSum/README.md b/solutions/leetcode/064-minimumPathSum/README.md
new file mode 100644
index 0000000..82630f9
--- /dev/null
+++ b/solutions/leetcode/064-minimumPathSum/README.md
@@ -0,0 +1,20 @@
+**64. 最小路径和**
+---
+[https://leetcode-cn.com/problems/minimum-path-sum/](https://leetcode-cn.com/problems/minimum-path-sum/)
+
+给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
+
+说明:每次只能向下或者向右移动一步。
+
+**示例:**
+
+```
+输入:
+[
+ [1,3,1],
+ [1,5,1],
+ [4,2,1]
+]
+输出: 7
+解释: 因为路径 1→3→1→1→1 的总和最小。
+```
diff --git a/leetcode/064-minimumPathSum/melody-l.md b/solutions/leetcode/064-minimumPathSum/melody-l.md
old mode 100755
new mode 100644
similarity index 100%
rename from leetcode/064-minimumPathSum/melody-l.md
rename to solutions/leetcode/064-minimumPathSum/melody-l.md
diff --git a/solutions/leetcode/069-SqrtX/README.md b/solutions/leetcode/069-SqrtX/README.md
new file mode 100644
index 0000000..090507f
--- /dev/null
+++ b/solutions/leetcode/069-SqrtX/README.md
@@ -0,0 +1,25 @@
+**69. x 的平方根**
+---
+[https://leetcode-cn.com/problems/sqrtx/](https://leetcode-cn.com/problems/sqrtx/)
+
+实现 ```int sqrt(int x)``` 函数。
+
+计算并返回 x 的平方根,其中 x 是非负整数。
+
+由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
+
+**示例 1:**
+
+```
+输入: 4
+输出: 2
+```
+
+**示例 2:**
+
+```
+输入: 8
+输出: 2
+说明: 8 的平方根是 2.82842...,
+ 由于返回类型是整数,小数部分将被舍去。
+```
diff --git a/solutions/leetcode/069-SqrtX/bigablecat.md b/solutions/leetcode/069-SqrtX/bigablecat.md
new file mode 100644
index 0000000..ecbcc42
--- /dev/null
+++ b/solutions/leetcode/069-SqrtX/bigablecat.md
@@ -0,0 +1,54 @@
+**69. x 的平方根**
+---
+[https://leetcode-cn.com/problems/sqrtx/](https://leetcode-cn.com/problems/sqrtx/)
+
+* 网友高票Java题解:
+
+```java
+ /**
+ * https://leetcode.com/problems/sqrtx/discuss/25047/A-Binary-Search-Solution
+ * 网友高票答案
+ *
+ * @param x
+ * @return
+ */
+ public static int mySqrt(int x) {
+ //如果x是0,平方根为0
+ if (x == 0){
+ //直接返回结果0
+ return 0;
+ }
+ //分别设定左右边界left和right
+ //left从非负整数1开始,right到java运行的整数最大值上限Integer.MAX_VALUE为止
+ int left = 1, right = x;
+ //while (true) 进行一个无限循环,只能在方法体内结束循环
+ while (true) {
+ // 通过二分法不断缩小取值范围
+ // 目标是找到一个中间值mid,如果x介于mid²和(mid+1)²之间
+ // 那么mid就是x平方根的整数部分
+ int mid = left + (right - left) / 2;
+ // mid > x/mid 等价于 mid² > x
+ // 说明mid本身比x的平方根大
+ if (mid > x / mid) {
+ //将mid-1赋值给右边界right,在小于mid的范围内继续寻找x的平方根
+ right = mid - 1;
+ } else {
+ // mid + 1 > x/(mid + 1) 等价于 (mid + 1)² > x
+ // 说明 (mid + 1) 比 x 的平方根大
+ if (mid + 1 > x / (mid + 1))
+ // mid 小于或等于 x 的平方根
+ // (mid + 1) 大于 x 的平方根
+ // mid 即是要找的数字
+ return mid;
+ //如果 (mid + 1)² <
+ left = mid + 1;
+ }
+ }
+ }
+
+```
+
+**参考资料**
+
+* 网友高票Java解法:
+[https://leetcode.com/problems/sqrtx/discuss/25047/A-Binary-Search-Solution](https://leetcode.com/problems/sqrtx/discuss/25047/A-Binary-Search-Solution)
diff --git a/solutions/leetcode/070-ClimbingStairs/README.md b/solutions/leetcode/070-ClimbingStairs/README.md
new file mode 100644
index 0000000..ae4b0e0
--- /dev/null
+++ b/solutions/leetcode/070-ClimbingStairs/README.md
@@ -0,0 +1,30 @@
+**70. 爬楼梯**
+---
+[https://leetcode-cn.com/problems/climbing-stairs/](https://leetcode-cn.com/problems/climbing-stairs/)
+
+假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
+
+每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
+
+注意:给定 n 是一个正整数。
+
+**示例 1:**
+
+```
+输入: 2
+输出: 2
+解释: 有两种方法可以爬到楼顶。
+1. 1 阶 + 1 阶
+2. 2 阶
+```
+
+**示例 2:**
+
+```
+输入: 3
+输出: 3
+解释: 有三种方法可以爬到楼顶。
+1. 1 阶 + 1 阶 + 1 阶
+2. 1 阶 + 2 阶
+3. 2 阶 + 1 阶
+```
diff --git a/leetcode/070-ClimbingStairs/melody-l.md b/solutions/leetcode/070-ClimbingStairs/melody-l.md
similarity index 100%
rename from leetcode/070-ClimbingStairs/melody-l.md
rename to solutions/leetcode/070-ClimbingStairs/melody-l.md
diff --git a/leetcode/072-EditDistance/official.md b/solutions/leetcode/072-EditDistance/official.md
similarity index 100%
rename from leetcode/072-EditDistance/official.md
rename to solutions/leetcode/072-EditDistance/official.md
diff --git a/solutions/leetcode/075-SortColors/README.md b/solutions/leetcode/075-SortColors/README.md
new file mode 100644
index 0000000..8a74bde
--- /dev/null
+++ b/solutions/leetcode/075-SortColors/README.md
@@ -0,0 +1,24 @@
+**75. 颜色分类**
+---
+[https://leetcode-cn.com/problems/sort-colors/](https://leetcode-cn.com/problems/sort-colors/)
+
+给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
+
+此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
+
+**注意:**
+不能使用代码库中的排序函数来解决这道题。
+
+**示例:**
+
+```
+输入: [2,0,2,1,1,0]
+输出: [0,0,1,1,2,2]
+```
+
+**进阶:**
+
+* 一个直观的解决方案是使用计数排序的两趟扫描算法。
+首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
+
+* 你能想出一个仅使用常数空间的一趟扫描算法吗?
diff --git a/solutions/leetcode/075-SortColors/bigablecat.md b/solutions/leetcode/075-SortColors/bigablecat.md
new file mode 100644
index 0000000..3314af2
--- /dev/null
+++ b/solutions/leetcode/075-SortColors/bigablecat.md
@@ -0,0 +1,67 @@
+**75. 颜色分类**
+---
+[https://leetcode-cn.com/problems/sort-colors/](https://leetcode-cn.com/problems/sort-colors/)
+
+* 网友高票答案:
+
+```java
+
+ /**
+ * https://leetcode.com/problems/sort-colors/discuss/26472/Share-my-at-most-two-pass-constant-space-10-line-solution
+ * 网友高票答案
+ *
+ * @param A
+ */
+ public void sortColors(int A[]) {
+ // 定义整数second代表数字2蓝色,zero代表数字0红色
+ // 本方法的思路是将数字2蓝色后移到数组的右侧
+ // 数字0红色前移到数组左侧
+ // 剩余数字1白色在移动过程中也聚集到了中间
+ // second初始值为n-1,即数组A下标的上限
+ // zero初始值为0,即数组A下标的下限
+ int second = A.length - 1, zero = 0;
+ //从左向右遍历数组A
+ for (int i = 0; i <= second; i++) {
+ //如果当前元素A[i]为2蓝色,且下标i比second小
+ //交换当前元素A[i]和A[second]在数组A中的位置
+ //second--作为参数传入swap方法,递减是在swap方法结束之后才进行的
+ //所以swap方法中操作的是A[second]
+ while (A[i] == 2 && i < second) swap(A, i, second--);
+ //如果当前元素A[i]为0白色,且下标i比zero大
+ //交换当前元素A[i]和A[zero]在数组A中的位置
+ //zero++作为参数传入swap方法,递增是在swap方法结束之后才进行的
+ //所以swap方法中操作的是A[zero]
+ while (A[i] == 0 && i > zero) swap(A, i, zero++);
+ }
+ }
+
+ /**
+ * swap方法,交换数组中两个元素的位置
+ *
+ * @param nums 数组
+ * @param i 左侧元素的下标
+ * @param j 右侧元素的下标
+ * @return
+ */
+ public int[] swap(int[] nums, int i, int j) {
+ //定义一个临时变量存放右侧元素
+ int temp = nums[j];
+ //将左侧元素赋值给右侧元素
+ nums[j] = nums[i];
+ //将临时变量存储的原右侧元素赋值给左侧元素
+ nums[i] = temp;
+ //返回交换后的数组
+ return nums;
+ }
+
+```
+
+**复杂度分析**
+
+空间复杂度:O(1),
+只定义了3个整型变量,没有使用更多额外空间,空间复杂度是O(1)
+
+**参考资料**
+
+* 网友高票答案:
+[https://leetcode.com/problems/sort-colors/discuss/26472/Share-my-at-most-two-pass-constant-space-10-line-solution](https://leetcode.com/problems/sort-colors/discuss/26472/Share-my-at-most-two-pass-constant-space-10-line-solution)
diff --git a/solutions/leetcode/076-MinimumWindowSubstring/README.md b/solutions/leetcode/076-MinimumWindowSubstring/README.md
new file mode 100644
index 0000000..f43233d
--- /dev/null
+++ b/solutions/leetcode/076-MinimumWindowSubstring/README.md
@@ -0,0 +1,17 @@
+**76. 最小覆盖子串**
+---
+[https://leetcode-cn.com/problems/minimum-window-substring/](https://leetcode-cn.com/problems/minimum-window-substring/)
+
+给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
+
+**示例:**
+
+```
+输入: S = "ADOBECODEBANC", T = "ABC"
+输出: "BANC"
+```
+
+**说明:**
+
+* 如果 S 中不存这样的子串,则返回空字符串 ""。
+* 如果 S 中存在这样的子串,我们保证它是唯一的答案。
diff --git a/leetcode/085-MaximalRectangle/passself.md b/solutions/leetcode/085-MaximalRectangle/passself.md
similarity index 100%
rename from leetcode/085-MaximalRectangle/passself.md
rename to solutions/leetcode/085-MaximalRectangle/passself.md
diff --git a/leetcode/087-ScrambleString/official.md b/solutions/leetcode/087-ScrambleString/official.md
similarity index 100%
rename from leetcode/087-ScrambleString/official.md
rename to solutions/leetcode/087-ScrambleString/official.md
diff --git a/leetcode/091-DecodeWays/melody-l.md b/solutions/leetcode/091-DecodeWays/melody-l.md
old mode 100755
new mode 100644
similarity index 100%
rename from leetcode/091-DecodeWays/melody-l.md
rename to solutions/leetcode/091-DecodeWays/melody-l.md
diff --git a/leetcode/091-DecodeWays/official.md b/solutions/leetcode/091-DecodeWays/official.md
similarity index 100%
rename from leetcode/091-DecodeWays/official.md
rename to solutions/leetcode/091-DecodeWays/official.md
diff --git a/solutions/leetcode/091-DecodeWays/sandao.md b/solutions/leetcode/091-DecodeWays/sandao.md
new file mode 100644
index 0000000..caea69f
--- /dev/null
+++ b/solutions/leetcode/091-DecodeWays/sandao.md
@@ -0,0 +1,88 @@
+## **91. Decode Ways**
+
+https://leetcode.com/problems/decode-ways/
+
+
+
+思路:这个边界条件比较多,然后需要储存已经计算过的值。
+
+```java
+class Solution {
+ public int numDecodings(String s) {
+ if (s.startsWith("0") || s.length() == 0) {
+ return 0;
+ }
+ //用于储存已算出值的数组。
+ int[] cc = new int[s.length()+1];
+ //先填充
+ Arrays.fill(cc, -1);
+ return numDecodings2(s,cc);
+ }
+ private static int numDecodings2(String s,int[] cc) {
+ //首先查询这个值是否算出
+ if (cc[s.length()] != -1) {
+ return cc[s.length()];
+ }
+ int length = s.length();
+ if (length == 2) {
+ //拼接剩下的两位数
+ if (Integer.valueOf(s) > 26) {
+ //大于26,且个位数为0,则没有对应的字母,拆开来也没有,就返回0
+ if (0 == Integer.valueOf(s.substring(1,2))) {
+ return 0;
+ }
+ //大于26,个位数不为0,则虽然没有对应的字母,但是可以拆开来当作两个一位数字,返回1
+ return 1;
+ }
+ //小于26,但是个位数为0,则有对应的字母,但是不可以拆开来当作两个一位数字,返回1
+ if (0 == Integer.valueOf(s.substring(1,2))) {
+ return 1;
+ }
+ //小于26,个位数不为0,则有对应的字母,也可以拆开来当作两个一位数字,返回2
+ return 2;
+ }
+ if (length == 1) {
+ //只剩下一个数字,如果是0则返回0;
+ if ("0".equals(s)) {
+ return 0;
+ }
+ return 1;
+ }
+ //对于字符串"123456",可以分成两种情况
+ //R["123456"] = R["12345"]* R["6"] +R["1234"]*R["56"]
+ String sDel1 = s.substring(0,length-1);
+ String sDel2 = sDel1.substring(0,sDel1.length()-1);
+ //取两位数的情况(注意这里的两位数是不可拆的来计算)
+ int count2 = 1;
+ String sum = s.substring(length-2);
+ if (Integer.valueOf(sum) > 26) {
+ count2 = 0;
+ }
+ if (0 == Integer.valueOf(s.substring(length-2,length-1))) {
+ count2 = 0;
+ }
+ //取一位数的情况
+ int count1 = 1;
+ if ("0".equals(s.substring(length-1))) {
+ count1 = 0;
+ }
+ //向下计算
+ int sDel2Count;
+ if (cc[length-2] != -1) {
+ sDel2Count = cc[length-2];
+ } else {
+ sDel2Count = numDecodings2(sDel2,cc);
+ cc[length-2] = sDel2Count;
+ }
+ int sDel1Count = numDecodings2(sDel1,cc);
+
+ return sDel1Count * count1 + count2 * sDel2Count;
+ }
+}
+```
+
+
+
+**参考资料**
+
+无
\ No newline at end of file
diff --git a/leetcode/095-UniqueBinarySearchTreesII/melody-l.md b/solutions/leetcode/095-UniqueBinarySearchTreesII/melody-l.md
old mode 100755
new mode 100644
similarity index 100%
rename from leetcode/095-UniqueBinarySearchTreesII/melody-l.md
rename to solutions/leetcode/095-UniqueBinarySearchTreesII/melody-l.md
diff --git a/leetcode/095-UniqueBinarySearchTreesII/official.md b/solutions/leetcode/095-UniqueBinarySearchTreesII/official.md
similarity index 100%
rename from leetcode/095-UniqueBinarySearchTreesII/official.md
rename to solutions/leetcode/095-UniqueBinarySearchTreesII/official.md
diff --git a/leetcode/096-uniqueBinarySearchTrees/official.md b/solutions/leetcode/096-uniqueBinarySearchTrees/official.md
similarity index 100%
rename from leetcode/096-uniqueBinarySearchTrees/official.md
rename to solutions/leetcode/096-uniqueBinarySearchTrees/official.md
diff --git a/leetcode/097-InterleavingString/official.md b/solutions/leetcode/097-InterleavingString/official.md
similarity index 100%
rename from leetcode/097-InterleavingString/official.md
rename to solutions/leetcode/097-InterleavingString/official.md
diff --git a/leetcode/098-validateBinarySearchTree/BambooYH.md b/solutions/leetcode/098-validateBinarySearchTree/BambooYH.md
similarity index 100%
rename from leetcode/098-validateBinarySearchTree/BambooYH.md
rename to solutions/leetcode/098-validateBinarySearchTree/BambooYH.md
diff --git a/leetcode/102-BinaryTreeLevelOrderTraversal/SpecialYang.md b/solutions/leetcode/102-BinaryTreeLevelOrderTraversal/SpecialYang.md
similarity index 100%
rename from leetcode/102-BinaryTreeLevelOrderTraversal/SpecialYang.md
rename to solutions/leetcode/102-BinaryTreeLevelOrderTraversal/SpecialYang.md
diff --git a/leetcode/102-BinaryTreeLevelOrderTraversal/hatrick.md b/solutions/leetcode/102-BinaryTreeLevelOrderTraversal/hatrick.md
similarity index 100%
rename from leetcode/102-BinaryTreeLevelOrderTraversal/hatrick.md
rename to solutions/leetcode/102-BinaryTreeLevelOrderTraversal/hatrick.md
diff --git a/leetcode/102-BinaryTreeLevelOrderTraversal/official.md b/solutions/leetcode/102-BinaryTreeLevelOrderTraversal/official.md
similarity index 100%
rename from leetcode/102-BinaryTreeLevelOrderTraversal/official.md
rename to solutions/leetcode/102-BinaryTreeLevelOrderTraversal/official.md
diff --git a/leetcode/102-BinaryTreeLevelOrderTraversal/zengdiqing1994.md b/solutions/leetcode/102-BinaryTreeLevelOrderTraversal/zengdiqing1994.md
similarity index 100%
rename from leetcode/102-BinaryTreeLevelOrderTraversal/zengdiqing1994.md
rename to solutions/leetcode/102-BinaryTreeLevelOrderTraversal/zengdiqing1994.md
diff --git a/leetcode/104-MaximumDepthOfBinaryTree/melody-l.md b/solutions/leetcode/104-MaximumDepthOfBinaryTree/melody-l.md
similarity index 100%
rename from leetcode/104-MaximumDepthOfBinaryTree/melody-l.md
rename to solutions/leetcode/104-MaximumDepthOfBinaryTree/melody-l.md
diff --git a/leetcode/104-MaximumDepthOfBinaryTree/official.md b/solutions/leetcode/104-MaximumDepthOfBinaryTree/official.md
similarity index 100%
rename from leetcode/104-MaximumDepthOfBinaryTree/official.md
rename to solutions/leetcode/104-MaximumDepthOfBinaryTree/official.md
diff --git a/solutions/leetcode/110-BalancedBinaryTree/README.md b/solutions/leetcode/110-BalancedBinaryTree/README.md
new file mode 100644
index 0000000..d66a4ef
--- /dev/null
+++ b/solutions/leetcode/110-BalancedBinaryTree/README.md
@@ -0,0 +1,42 @@
+**110. 平衡二叉树**
+---
+[https://leetcode-cn.com/problems/balanced-binary-tree/](https://leetcode-cn.com/problems/balanced-binary-tree/)
+
+给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
+
+你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
+
+给定一个二叉树,判断它是否是高度平衡的二叉树。
+
+本题中,一棵高度平衡二叉树定义为:
+
+>一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
+
+**示例 1:**
+
+```
+给定二叉树 [3,9,20,null,null,15,7]
+
+ 3
+ / \
+ 9 20
+ / \
+ 15 7
+返回 true 。
+```
+
+**示例 2:**
+
+```
+给定二叉树 [1,2,2,3,3,null,null,4,4]
+
+ 1
+ / \
+ 2 2
+ / \
+ 3 3
+ / \
+ 4 4
+返回 false 。
+```
+
diff --git a/solutions/leetcode/110-BalancedBinaryTree/bigablecat.md b/solutions/leetcode/110-BalancedBinaryTree/bigablecat.md
new file mode 100644
index 0000000..ba0d8fd
--- /dev/null
+++ b/solutions/leetcode/110-BalancedBinaryTree/bigablecat.md
@@ -0,0 +1,61 @@
+**110. 平衡二叉树**
+---
+[https://leetcode-cn.com/problems/balanced-binary-tree/](https://leetcode-cn.com/problems/balanced-binary-tree/)
+
+* 网友高票Java解法:
+
+```java
+
+ /**
+ * 网友高票Java解法
+ *
+ * @param root
+ * @return
+ */
+ public boolean isBalanced(TreeNode root) {
+ return height(root) != -1;
+ }
+
+ /**
+ * 获取当前节点的树高
+ * 如果是高度平衡的二叉树,返回树的真实高度
+ * 如果不是高度平衡二叉树,返回-1
+ *
+ * @param node
+ * @return
+ */
+ public int height(TreeNode node) {
+ //检查当前节点是否为空
+ if (node == null) {
+ //空节点返回0
+ return 0;
+ }
+ //获取左子节点的树高
+ int lH = height(node.left);
+ //如果返回-1,说明左子节点不符合题意
+ if (lH == -1) {
+ return -1;
+ }
+ //同理判断右子节点
+ int rH = height(node.right);
+ if (rH == -1) {
+ return -1;
+ }
+ //检查左右子节点高度差的绝对值是否不超过1
+ if (lH - rH < -1 || lH - rH > 1) {
+ //绝对值超过1,不符合题意,返回-1
+ return -1;
+ }
+ //Math.max(lH,rH)返回左右子节点中高度较大的一个
+ //在子节点中较大的高度上+1,即当前节点自身的高度1
+ //返回的最终结果就是当前节点的树高
+ return Math.max(lH, rH) + 1;
+ }
+
+```
+
+**参考资料**
+
+* 网友高票答案:
+[https://leetcode.com/problems/balanced-binary-tree/discuss/35686/Java-solution-based-on-height-check-left-and-right-node-in-every-recursion-to-avoid-further-useless-search](https://leetcode.com/problems/balanced-binary-tree/discuss/35686/Java-solution-based-on-height-check-left-and-right-node-in-every-recursion-to-avoid-further-useless-search)
+
diff --git a/solutions/leetcode/110-BalancedBinaryTree/zengdiqing1994.md b/solutions/leetcode/110-BalancedBinaryTree/zengdiqing1994.md
new file mode 100644
index 0000000..f348f7a
--- /dev/null
+++ b/solutions/leetcode/110-BalancedBinaryTree/zengdiqing1994.md
@@ -0,0 +1,51 @@
+110.给定一个二叉树,判断它是否是高度平衡的二叉树。
+
+本题中,一棵高度平衡二叉树定义为:
+
+一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
+
+示例 1:
+
+给定二叉树 [3,9,20,null,null,15,7]
+
+ 3
+ / \
+ 9 20
+ / \
+ 15 7
+返回 true 。
+
+示例 2:
+
+给定二叉树 [1,2,2,3,3,null,null,4,4]
+
+ 1
+ / \
+ 2 2
+ / \
+ 3 3
+ / \
+ 4 4
+返回 false 。
+
+思路:递归,判断左右子树最大高度差不超过1且左右子树均为平衡树
+
+```py
+class Solution(object):
+ def isBalanced(self, root):
+ """
+ :type root: TreeNode
+ :rtype: bool
+ """
+ def getDepth(root):
+ if not root:
+ return 0
+ return 1 + max(getDepth(root.left), getDepth(root.right)) #左右子树最大的深度,记住加一
+
+ if not root:
+ return True
+ if abs(getDepth(root.left) - getDepth(root.right))>1: #判断左右子树的最大深度差是否超过1
+ return False
+ return self.isBalanced(root.left) and self.isBalanced(root.right)
+```
+时间复杂度:O(n)
diff --git a/leetcode/115-DistinctSubsequences/official.md b/solutions/leetcode/115-DistinctSubsequences/official.md
similarity index 100%
rename from leetcode/115-DistinctSubsequences/official.md
rename to solutions/leetcode/115-DistinctSubsequences/official.md
diff --git a/leetcode/120-Triangle/melody-l.md b/solutions/leetcode/120-Triangle/melody-l.md
similarity index 100%
rename from leetcode/120-Triangle/melody-l.md
rename to solutions/leetcode/120-Triangle/melody-l.md
diff --git a/leetcode/120-Triangle/official.md b/solutions/leetcode/120-Triangle/official.md
similarity index 100%
rename from leetcode/120-Triangle/official.md
rename to solutions/leetcode/120-Triangle/official.md
diff --git a/leetcode/121-bestTimeToBuyAndSellStock/bigablecat.md b/solutions/leetcode/121-bestTimeToBuyAndSellStock/bigablecat.md
similarity index 100%
rename from leetcode/121-bestTimeToBuyAndSellStock/bigablecat.md
rename to solutions/leetcode/121-bestTimeToBuyAndSellStock/bigablecat.md
diff --git a/leetcode/121-bestTimeToBuyAndSellStock/official.md b/solutions/leetcode/121-bestTimeToBuyAndSellStock/official.md
similarity index 100%
rename from leetcode/121-bestTimeToBuyAndSellStock/official.md
rename to solutions/leetcode/121-bestTimeToBuyAndSellStock/official.md
diff --git a/leetcode/122-bestTimeToBuyAndSellStockII/SpecialYang.md b/solutions/leetcode/122-bestTimeToBuyAndSellStockII/SpecialYang.md
similarity index 100%
rename from leetcode/122-bestTimeToBuyAndSellStockII/SpecialYang.md
rename to solutions/leetcode/122-bestTimeToBuyAndSellStockII/SpecialYang.md
diff --git a/leetcode/122-bestTimeToBuyAndSellStockII/bigablecat.md b/solutions/leetcode/122-bestTimeToBuyAndSellStockII/bigablecat.md
similarity index 100%
rename from leetcode/122-bestTimeToBuyAndSellStockII/bigablecat.md
rename to solutions/leetcode/122-bestTimeToBuyAndSellStockII/bigablecat.md
diff --git a/leetcode/123-BestTimeToBuyAndSellStockIII/SpecialYang.md b/solutions/leetcode/123-BestTimeToBuyAndSellStockIII/SpecialYang.md
similarity index 100%
rename from leetcode/123-BestTimeToBuyAndSellStockIII/SpecialYang.md
rename to solutions/leetcode/123-BestTimeToBuyAndSellStockIII/SpecialYang.md
diff --git a/leetcode/123-BestTimeToBuyAndSellStockIII/official.md b/solutions/leetcode/123-BestTimeToBuyAndSellStockIII/official.md
similarity index 100%
rename from leetcode/123-BestTimeToBuyAndSellStockIII/official.md
rename to solutions/leetcode/123-BestTimeToBuyAndSellStockIII/official.md
diff --git a/leetcode/131-PalindromePartitioning/official.md b/solutions/leetcode/131-PalindromePartitioning/official.md
similarity index 100%
rename from leetcode/131-PalindromePartitioning/official.md
rename to solutions/leetcode/131-PalindromePartitioning/official.md
diff --git a/leetcode/132-PalindromePartitioningII/official.md b/solutions/leetcode/132-PalindromePartitioningII/official.md
similarity index 100%
rename from leetcode/132-PalindromePartitioningII/official.md
rename to solutions/leetcode/132-PalindromePartitioningII/official.md
diff --git a/leetcode/139-WordBreak/official.md b/solutions/leetcode/139-WordBreak/official.md
similarity index 100%
rename from leetcode/139-WordBreak/official.md
rename to solutions/leetcode/139-WordBreak/official.md
diff --git a/leetcode/140-WordBreakII/official.md b/solutions/leetcode/140-WordBreakII/official.md
similarity index 100%
rename from leetcode/140-WordBreakII/official.md
rename to solutions/leetcode/140-WordBreakII/official.md
diff --git a/leetcode/141-linkedListCycle/official.md b/solutions/leetcode/141-linkedListCycle/official.md
similarity index 100%
rename from leetcode/141-linkedListCycle/official.md
rename to solutions/leetcode/141-linkedListCycle/official.md
diff --git a/leetcode/142-linkedListCycleII/bigablecat.md b/solutions/leetcode/142-linkedListCycleII/bigablecat.md
similarity index 67%
rename from leetcode/142-linkedListCycleII/bigablecat.md
rename to solutions/leetcode/142-linkedListCycleII/bigablecat.md
index 3698b0d..d9131ac 100644
--- a/leetcode/142-linkedListCycleII/bigablecat.md
+++ b/solutions/leetcode/142-linkedListCycleII/bigablecat.md
@@ -2,12 +2,24 @@
---
[https://leetcode-cn.com/problems/linked-list-cycle-ii/](https://leetcode-cn.com/problems/linked-list-cycle-ii/)
-* 网友高票Java解法,双指针法
+* 网友高票Java解法:
```java
-
+
+ /**
+ * 双指针法
+ *