pair = stack.pop();
+ for (int k = 0; k < 4; ++k) {
+ x = pair.getKey() + direction[k];
+ y = pair.getValue() + direction[k + 1];
+ if (checkArea(grid, visited, x, y)) {
+ areaCount++;
+ visited[x][y] = 1;
+ stack.push(new Pair<>(x, y));
+ }
+ }
+
+ }
+
+ res = Math.max(res, areaCount);
+ }
+ }
+ }
+ return res;
+ }
+
+ private boolean checkArea(int[][] grid, int[][] visited, int x, int y) {
+ // i,j未超界
+ if (x < 0 || y < 0 || x >= grid.length || y >= grid[0].length) {
+ return false;
+ }
+ // 已经来过不处理
+ if (visited[x][y] == 1 || grid[x][y] == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public static void main(String[] args) {
+ int[][] x = {
+ {0,0,1,0,0,0,0,1,0,0,0,0,0},
+ {0,0,0,0,0,0,0,1,1,1,0,0,0},
+ {0,1,1,0,1,0,0,0,0,0,0,0,0},
+ {0,1,0,0,1,1,0,0,1,0,1,0,0},
+ {0,1,0,0,1,1,0,0,1,1,1,0,0},
+ {0,0,0,0,0,0,0,0,0,0,1,0,0},
+ {0,0,0,0,0,0,0,1,1,1,0,0,0},
+ {0,0,0,0,0,0,0,1,1,0,0,0,0}};
+ System.out.println(new Solution2().maxAreaOfIsland(x));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\347\234\201\344\273\275\346\225\260\351\207\217_547_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\347\234\201\344\273\275\346\225\260\351\207\217_547_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..3138fb69
--- /dev/null
+++ "b/algorithms/leetcode2/dfsbfs/src/main/java/cn/cunchang/\347\234\201\344\273\275\346\225\260\351\207\217_547_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,40 @@
+
+package cn.cunchang.省份数量_547_中等;
+
+class Solution {
+ /**
+ * 有几个需要注意的条件
+ * isConnected[i][i] == 1
+ * isConnected[i][j] == isConnected[j][i]
+ *
+ * isConnected[i][i] == 1 说明是个无向图
+ */
+ public int findCircleNum(int[][] isConnected) {
+ boolean[] visited = new boolean[isConnected.length];
+
+ int res = 0;
+ for (int i = 0; i < isConnected.length; i++) {
+ if (!visited[i]) {
+ findCircleNum(isConnected, i, visited);
+ res++;
+ }
+ }
+ return res;
+ }
+ // 深度遍历,相邻节点,并对访问过的节点进行标记
+ private void findCircleNum(int[][] isConnected, int i, boolean[] visited) {
+ visited[i] = true;
+ for (int j = 0; j < isConnected.length; j++) {
+ if (isConnected[i][j] == 1 && !visited[j]) {
+ findCircleNum(isConnected, j, visited);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ int[][] isConnected = {{1, 1, 0},
+ {1, 1, 0},
+ {0, 0, 1}};
+ System.out.println(new Solution().findCircleNum(isConnected));
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/dynamic2/pom.xml b/algorithms/leetcode2/dynamic2/pom.xml
new file mode 100644
index 00000000..77cc2ec4
--- /dev/null
+++ b/algorithms/leetcode2/dynamic2/pom.xml
@@ -0,0 +1,19 @@
+
+
+
+ leetcode2
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ dynamic
+
+
+ 8
+ 8
+
+
+
\ No newline at end of file
diff --git a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/knapsack01/knapsack01.md b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/knapsack01/knapsack01.md
new file mode 100644
index 00000000..7431ee35
--- /dev/null
+++ b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/knapsack01/knapsack01.md
@@ -0,0 +1,15 @@
+| id | 0 | 1 | 2 |
+| ------ | ---- | ---- | ---- |
+| weight | 1 | 2 | 3 |
+| value | 6 | 10 | 12 |
+
+
+
+
+
+| 物品编号\背包容量 | 0 | 1 | 2 | 3 | 4 | 5 |
+|-----------| ---- | ---- | ---- | ---- | ---- | ---- |
+| 0 | 0 | 6 | 6 | 6 | 6 | 6 |
+| 1 | 0 | 6 | 10 | 16 | 16 | 16 |
+| 2 | 0 | 6 | 10 | 16 | 18 | 22 |
+
diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..09910cfd
--- /dev/null
+++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,30 @@
+package cn.cunchang.打家劫舍_198_中等;
+
+class Solution {
+ public int rob(int[] nums) {
+ return tryRob(0, nums);
+ }
+
+ /**
+ * idx 偷窃的起始位置
+ */
+ public int tryRob(int idx, int[] nums) {
+ if (idx >= nums.length) {
+ return 0;
+ }
+ int max = 0, res = 0;
+ // 对[idx,nums.length-1]每个位置进行偷窃
+ for (int i = idx; i < nums.length; i++) {
+ // 找当前位置可以偷窃的最佳金额
+ int subMax = tryRob(i + 2, nums);
+ res = nums[i] + subMax;
+ max = Math.max(max, res);
+ }
+ return max;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().rob(new int[]{1,2,3,1}));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution2.java"
new file mode 100644
index 00000000..dcb878b2
--- /dev/null
+++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\346\211\223\345\256\266\345\212\253\350\210\215_198_\344\270\255\347\255\211/Solution2.java"
@@ -0,0 +1,38 @@
+package cn.cunchang.打家劫舍_198_中等;
+
+import java.util.Arrays;
+
+class Solution2 {
+ public int rob(int[] nums) {
+ int[] moment = new int[nums.length];
+ Arrays.fill(moment, -1);
+ return tryRob(0, nums, moment);
+ }
+
+ /**
+ * idx 偷窃的起始位置
+ */
+ public int tryRob(int idx, int[] nums, int[] moment) {
+ if (idx >= nums.length) {
+ return 0;
+ }
+ if (moment[idx] != -1) {
+ return moment[idx];
+ }
+ int max = 0, res = 0;
+ // 对[idx,nums.length-1]每个位置进行偷窃
+ for (int i = idx; i < nums.length; i++) {
+ // 找当前位置可以偷窃的最佳金额
+ int subMax = tryRob(i + 2, nums, moment);
+ res = nums[i] + subMax;
+ max = Math.max(max, res);
+ }
+ moment[idx] = max;
+ return max;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution2().rob(new int[]{1, 2, 3, 1}));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..4c715f6d
--- /dev/null
+++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\347\210\254\346\245\274\346\242\257_70_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,21 @@
+package cn.cunchang.爬楼梯_70_简单;
+
+class Solution {
+ public int climbStairs(int n) {
+ if (n == 1) {
+ return 1;
+ }
+ if (n == 2) {
+ return 2;
+ }
+ int f1 = 1, f2 = 2;
+ int res = 0;
+ for (int i = 2; i < n; i++) {
+ res = f1 + f2;
+ f1 = f2;
+ f2 = res;
+ }
+
+ return res;
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..f453307e
--- /dev/null
+++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,47 @@
+package cn.cunchang.零钱兑换_322_中等;
+
+import java.util.HashMap;
+
+/**
+ * @author cunchang
+ * @date 2022/6/23 5:07 PM
+ */
+class Solution {
+
+ public int coinChange(int[] coins, int amount) {
+ HashMap meno = new HashMap<>();
+ return coinChange0(coins, amount, meno);
+ }
+
+ public int coinChange0(int[] coins, int amount, HashMap meno) {
+ if (amount < 0) {
+ return -1;
+ }
+ if (amount == 0) {
+ return 0;
+ }
+ if (meno.get(amount) != null) {
+ return meno.get(amount);
+ }
+ int res = Integer.MAX_VALUE;
+ for (int coin : coins) {
+ int subRes = coinChange0(coins, amount - coin, meno);
+ // 子问题无解
+ if (subRes == -1) {
+ continue;
+ }
+ // 找子问题最小解
+ res = Math.min(res, subRes + 1);
+ }
+
+ res = (res == Integer.MAX_VALUE) ? -1 : res;
+ // 对amount的结果进行缓存
+ meno.put(amount, res);
+ return res;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().coinChange(new int[]{1, 2, 5}, 11));
+// System.out.println(new Solution().coinChange(new int[]{2}, 3));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution2.java"
new file mode 100644
index 00000000..c804b59d
--- /dev/null
+++ "b/algorithms/leetcode2/dynamic2/src/main/java/cn/cunchang/\351\233\266\351\222\261\345\205\221\346\215\242_322_\344\270\255\347\255\211/Solution2.java"
@@ -0,0 +1,30 @@
+package cn.cunchang.零钱兑换_322_中等;
+
+import java.util.Arrays;
+
+/**
+ * @author cunchang
+ * @date 2022/6/23 5:07 PM
+ */
+class Solution2 {
+
+ public int coinChange(int[] coins, int amount) {
+ int max = amount + 1;
+ int[] dp = new int[amount + 1];
+ Arrays.fill(dp, max);
+ dp[0] = 0;
+ for (int i = 1; i <= amount; i++) {
+ for (int j = 0; j < coins.length; j++) {
+ if (coins[j] <= i) {
+ dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
+ }
+ }
+ }
+ return dp[amount] > amount ? -1 : dp[amount];
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution2().coinChange(new int[]{1, 2, 5}, 11));
+// System.out.println(new Solution().coinChange(new int[]{2}, 3));
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/greedy/pom.xml b/algorithms/leetcode2/greedy/pom.xml
new file mode 100644
index 00000000..31a3db05
--- /dev/null
+++ b/algorithms/leetcode2/greedy/pom.xml
@@ -0,0 +1,22 @@
+
+
+ 4.0.0
+
+ greedy
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+
+
+
+ junit
+ junit
+ 4.12
+
+
+
\ No newline at end of file
diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II_122_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II_122_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..46b7e94e
--- /dev/null
+++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272II_122_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,31 @@
+package cn.cunchang.买卖股票的最佳时机II_122_简单;
+
+import org.junit.Assert;
+
+class Solution {
+ /**
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ * 贪心策略:从后往前遍历
+ * -------------------------------------------------------------------
+ * 时间复杂度:
+ * 空间复杂度:
+ */
+ public int maxProfit(int[] prices) {
+ int profit = 0;
+ for (int i = prices.length - 1; i > 0; i--) {
+ if (prices[i] > prices[i - 1]) {
+ profit += prices[i] - prices[i - 1];
+ }
+ }
+ return profit;
+ }
+
+ public static void main(String[] args) {
+// int[] prices = {7, 1, 5, 3, 6, 4};
+// Assert.assertEquals(7, new Solution().maxProfit(prices));
+ int[] prices = {1,2,3,4,5};
+ Assert.assertEquals(4, new Solution().maxProfit(prices));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\347\263\226\346\236\234_135_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\347\263\226\346\236\234_135_\345\233\260\351\232\276/Solution1.java"
new file mode 100644
index 00000000..830f84ab
--- /dev/null
+++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\347\263\226\346\236\234_135_\345\233\260\351\232\276/Solution1.java"
@@ -0,0 +1,51 @@
+package cn.cunchang.分发糖果_135_困难;
+
+import org.junit.Assert;
+
+import java.util.Arrays;
+
+public class Solution1 {
+ /**
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ * 从前往后贪一次,从后往前再贪一次,不过第二次要判断大小,只贪最大的哪个
+ *
+ * -------------------------------------------------------------------
+ * 时间复杂度:O(n)
+ * 空间复杂度:O(n)
+ */
+ public int candy(int[] ratings) {
+ if (ratings.length < 2) {
+ return ratings.length;
+ }
+ int[] resArr = new int[ratings.length];
+ Arrays.fill(resArr, 1);
+ // 先从左往右遍历一遍,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加 1;
+ for (int i = 1; i < ratings.length; i++) {// i = 1而不是i = 0
+ if (ratings[i] > ratings[i - 1]) {
+ resArr[i] = resArr[i - 1] + 1;
+ }
+ }
+ // 再从右往左遍历一遍,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数,
+ // 则左边孩子的糖果数更新为右边孩子的糖果数加 1。
+ for (int i = ratings.length - 1; i > 0; i--) {// i > 0而不是i >= 0
+ if (ratings[i] < ratings[i - 1]) {
+ resArr[i - 1] = Math.max(resArr[i - 1], resArr[i] + 1);
+ }
+ }
+
+ int count = 0;
+ for (int res : resArr) {
+ count += res;
+ }
+ return count;
+ }
+
+ public static void main(String[] args) {
+// int[] g = new int[]{1, 2, 87, 87, 87, 2, 1};
+ int[] g = new int[]{1, 0, 2};
+ Assert.assertEquals(5, new Solution1().candy(g));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\351\245\274\345\271\262_455_\347\256\200\345\215\225/Solution1.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\351\245\274\345\271\262_455_\347\256\200\345\215\225/Solution1.java"
new file mode 100644
index 00000000..d8ff0bf0
--- /dev/null
+++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\345\210\206\345\217\221\351\245\274\345\271\262_455_\347\256\200\345\215\225/Solution1.java"
@@ -0,0 +1,48 @@
+package cn.cunchang.分发饼干_455_简单;
+
+import org.junit.Assert;
+
+import java.util.Arrays;
+
+public class Solution1 {
+ /**
+ * 思考:因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。为了尽量使得剩下的饼干可
+ * 以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的、且大小最小的饼干给这
+ * 个孩子。满足了这个孩子之后,我们采取同样的策略,考虑剩下孩子里饥饿度最小的孩子,直到
+ * 没有满足条件的饼干存在。
+ * -------------------------------------------------------------------
+ * 思路:
+ * 1、排序,对孩子的胃口和饼干大小降序排序
+ * 2、将最小的饼干s[j]给胃口最小的孩子g[i],s[j] >= g[i],说明满足,满足孩子数+1、继续分发下一块饼干;
+ * 不满足的话,孩子数不加,继续分发下一块饼干;
+ *
+ *
+ * -------------------------------------------------------------------
+ * 时间复杂度:n
+ * 空间复杂度:
+ */
+ public int findContentChildren(int[] childs, int[] cookies) {
+ Arrays.sort(childs);
+ Arrays.sort(cookies);
+ int child = 0, cookie = 0;
+ while (child < childs.length && cookie < cookies.length) {
+ if (cookies[cookie] >= childs[child]) {
+ child++;
+ }
+ cookie++;
+ }
+ return child;
+ }
+
+ public static void main(String[] args) {
+// int[] g = new int[]{1, 2};
+// int[] s = new int[]{1, 2, 3};
+// Assert.assertEquals(2, new Solution1().findContentChildren(g, s));
+
+ int[] g = new int[]{1, 2, 3};
+ int[] s = new int[]{1, 1};
+ Assert.assertEquals(1, new Solution1().findContentChildren(g, s));
+
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264_435_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264_435_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..ac08712c
--- /dev/null
+++ "b/algorithms/leetcode2/greedy/src/main/java/cn/cunchang/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264_435_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,45 @@
+package cn.cunchang.无重叠区间_435_中等;
+
+import org.junit.Assert;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class Solution {
+ /**
+ * 思考:
+ * 1. 什么是“区间不重叠”?intervals[i][1]<=intervals[i+1][0],说明区间i和区间i+1不重叠,否则就是重叠
+ * 2. 什么是“移除区间的最小数量,使剩余区间互不重叠”?比如“[[1,100],[11,22],[1,11],[2,12]]”移除后三个区间也不重叠,但是最小数量是移除1、4区间。
+ * -------------------------------------------------------------------
+ * 思路:
+ * 1、按照区间结尾升序
+ * 2、相邻单位区间,重合就移除;不重叠继续判断
+ * -------------------------------------------------------------------
+ * 时间复杂度:
+ * 空间复杂度:
+ */
+ public int eraseOverlapIntervals(int[][] intervals) {
+ Arrays.sort(intervals, new Comparator() {
+ @Override
+ public int compare(int[] interval1, int[] interval2) {
+ return interval1[1] - interval2[1];
+ }
+ });
+
+ int total = 0, pre = intervals[0][1];
+ for (int i = 1; i < intervals.length; i++) {
+ if (intervals[i][0] >= pre) {
+ pre = intervals[i][1];
+ } else {
+ total++;
+ }
+ }
+ return total;
+ }
+
+ public static void main(String[] args) {
+ int[][] g = new int[][]{{1, 100}, {11, 22}, {1, 11}, {2, 12}};
+ Assert.assertEquals(2, new Solution().eraseOverlapIntervals(g));
+
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/leetcode2-common/pom.xml b/algorithms/leetcode2/leetcode2-common/pom.xml
new file mode 100644
index 00000000..9e8d3916
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/pom.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+ 4.0.0
+
+ leetcode2-common
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+
+
+
\ No newline at end of file
diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/array/ArrayUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/array/ArrayUtil.java
new file mode 100644
index 00000000..5e3e6325
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/array/ArrayUtil.java
@@ -0,0 +1,75 @@
+package cn.cunchang.array;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author lastwhisper
+ * @date 2020/2/4
+ */
+public class ArrayUtil {
+
+ public static int[] createArrays(int... arr) {
+ return arr;
+ }
+
+ /**
+ * {"ab","cd"}=>
+ * 创建二维字符数组
+ */
+ public static char[][] createCharArrays(String[] arr) {
+ int m = arr.length, n = arr[0].length();
+ char[][] chars = new char[m][n];
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < n; j++) {
+ chars[i][j] = arr[i].charAt(j);
+ }
+ }
+ return chars;
+ }
+
+ /**
+ * {{"a","b","c","d"}}=>
+ * 创建二维字符数组
+ */
+ public static char[][] createCharArrays(String[][] arr) {
+ int m = arr.length, n = arr[0].length;
+ char[][] chars = new char[m][n];
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < n; j++) {
+ chars[i][j] = arr[i][j].charAt(0);
+ }
+ }
+ return chars;
+ }
+
+ /**
+ * 创建二维数组
+ */
+ public static int[][] createIntArrays(String[] arr) {
+ int m = arr.length, n = arr[0].length();
+ int[][] ints = new int[m][n];
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < n; j++) {
+ ints[i][j] = arr[i].charAt(j) - '0';
+ }
+ }
+ return ints;
+ }
+
+
+ /**
+ * 创建list
+ */
+ public static List> createList(int[][] arrays) {
+ List> lists = new ArrayList<>(arrays.length);
+ for (int[] array : arrays) {
+ List list = new ArrayList<>(array.length);
+ for (int num : array) {
+ list.add(num);
+ }
+ lists.add(list);
+ }
+ return lists;
+ }
+}
diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/LinkedListUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/LinkedListUtil.java
new file mode 100644
index 00000000..bdafc303
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/LinkedListUtil.java
@@ -0,0 +1,58 @@
+package cn.cunchang.linkedlist;
+
+
+/**
+ * 操作链表工具类
+ *
+ * @author lastwhisper
+ * @date 1/7/2020
+ */
+public class LinkedListUtil {
+
+ /**
+ * 创建单链表
+ */
+ public static ListNode createListNode(int... arr) {
+ if (arr == null || arr.length == 0) {
+ return null;
+ }
+ ListNode head = new ListNode(arr[0]);
+ ListNode current = head;
+ for (int i = 1; i < arr.length; i++) {
+ current.next = new ListNode(arr[i]);
+ current = current.next;
+ }
+ return head;
+ }
+
+ /**
+ * 打印单链表
+ */
+ public static void printListNode(String msg, ListNode head) {
+ System.out.println(msg + appendVal(head));
+ }
+
+ /**
+ * 打印单链表
+ */
+ public static void printListNode(ListNode head) {
+ System.out.println(appendVal(head));
+ }
+
+ private static String appendVal(ListNode head) {
+ StringBuilder sb = new StringBuilder();
+ ListNode current = head;
+ while (current != null) {
+ sb.append(current.val);
+ sb.append("->");
+ current = current.next;
+ }
+ sb.append("NULL");
+ return sb.toString();
+ }
+
+
+ public static void main(String[] args) {
+ printListNode(createListNode(1, 2, 3, 4, 5, 6, 7));
+ }
+}
diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/ListNode.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/ListNode.java
new file mode 100644
index 00000000..3db97b0e
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/linkedlist/ListNode.java
@@ -0,0 +1,11 @@
+package cn.cunchang.linkedlist;
+
+public class ListNode {
+ public int val;
+ public ListNode next;
+
+ public ListNode(int x) {
+ val = x;
+ }
+
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/print/PrintUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/print/PrintUtil.java
new file mode 100644
index 00000000..d87301ac
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/print/PrintUtil.java
@@ -0,0 +1,93 @@
+package cn.cunchang.print;
+
+import java.util.Collection;
+import java.util.List;
+
+
+/**
+ * 打印工具类
+ * @author lastwhisper
+ * @date 2020/2/1
+ */
+public class PrintUtil {
+
+ /**
+ * 层次打印二维数组
+ */
+ public static void printLists(List> lists) {
+ System.out.println("[");
+ int counter1 = 1;
+ for (List list : lists) {
+ System.out.print("\t[\"");
+ int counter2 = 1;
+ for (Integer i : list) {
+ if (counter2 != list.size()) {
+ System.out.print(i + "\",\"");
+ } else {
+ System.out.print(i);
+ }
+ counter2++;
+ }
+ if (counter1 != lists.size()) {
+ System.out.print("\"],\n");
+ } else {
+ System.out.print("\"]\n");
+ }
+ counter1++;
+ }
+ System.out.println("]");
+ }
+
+ public static void printStringLists(List> lists) {
+ System.out.println("[");
+ int counter1 = 1;
+ for (List list : lists) {
+ System.out.print("\t[\"");
+ int counter2 = 1;
+ for (String i : list) {
+ if (counter2 != list.size()) {
+ System.out.print(i + "\",\"");
+ } else {
+ System.out.print(i );
+ }
+ counter2++;
+ }
+ if (counter1 != lists.size()) {
+ System.out.print("\"],\n");
+ } else {
+ System.out.print("\"]\n");
+ }
+ counter1++;
+ }
+ System.out.println("]");
+ }
+
+ /**
+ * 打印数组
+ */
+ public static void printList(Collection> collection) {
+ System.out.println(collection2String(collection));
+ }
+
+ /**
+ * 将Collection扁平化迭代成String
+ */
+ public static String collection2String(Collection> collection) {
+ StringBuilder sb = new StringBuilder();
+ try {
+ sb.append("[\"");
+ int counter = 1;
+ for (Object object : collection) {
+ sb.append(object);
+ if (counter != collection.size()) {
+ sb.append("\",\"");
+ }
+ counter++;
+ }
+ sb.append("\"]");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return sb.toString();
+ }
+}
diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeNode.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeNode.java
new file mode 100644
index 00000000..d3b599af
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeNode.java
@@ -0,0 +1,11 @@
+package cn.cunchang.tree;
+
+public class TreeNode {
+ public int val;
+ public TreeNode left;
+ public TreeNode right;
+
+ public TreeNode(int x) {
+ val = x;
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeUtil.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeUtil.java
new file mode 100644
index 00000000..958d39fd
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TreeUtil.java
@@ -0,0 +1,121 @@
+package cn.cunchang.tree;
+
+import cn.cunchang.print.PrintUtil;
+import javafx.util.Pair;
+
+import java.util.*;
+
+
+/**
+ * 树相关工具类
+ * @author lastwhisper
+ * @date 1/16/2020
+ */
+public class TreeUtil {
+
+ /**
+ * 根据数组创建二叉树
+ * 一、[5,4,8,11,null,13,4,7,2,null,null,null,1]
+ * 5
+ * / \
+ * 4 8
+ * / / \
+ * 11 13 4
+ * / \ \
+ * 7 2 1
+ * 二、[1,null,2,3]
+ * 1
+ * \
+ * 2
+ * /
+ * 3
+ * 参考 https://blog.csdn.net/lenfranky/article/details/84444816
+ * @param array 数组
+ */
+ public static TreeNode createTree(Integer... array) {
+ if (array.length == 0) return new TreeNode(0);
+ Deque nodeQueue = new LinkedList<>();
+ // 创建一个根节点
+ TreeNode root = new TreeNode(array[0]);
+ nodeQueue.offer(root);
+ TreeNode current;
+ // 记录当前行节点的数量(注意不一定是2的幂,而是上一行中非空节点的数量乘2)
+ int lineNodeNum = 2;
+ // 记录当前行中数字在数组中的开始位置
+ int startIndex = 1;
+ // 记录数组中剩余的元素的数量
+ int restLength = array.length - 1;
+
+ while (restLength > 0) {
+ // 只有最后一行可以不满,其余行必须是满的
+// // 若输入的数组的数量是错误的,直接跳出程序
+// if (restLength < lineNodeNum) {
+// System.out.println("Wrong Input!");
+// return new TreeNode(0);
+// }
+ for (int i = startIndex; i < startIndex + lineNodeNum; i = i + 2) {
+ // 说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root
+ if (i == array.length) return root;
+ current = nodeQueue.poll();
+ if (array[i] != null) {
+ current.left = new TreeNode(array[i]);
+ nodeQueue.offer(current.left);
+ }
+ // 同上,说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root
+ if (i + 1 == array.length) return root;
+ if (array[i + 1] != null) {
+ current.right = new TreeNode(array[i + 1]);
+ nodeQueue.offer(current.right);
+ }
+ }
+ startIndex += lineNodeNum;
+ restLength -= lineNodeNum;
+ lineNodeNum = nodeQueue.size() * 2;
+ }
+
+ return root;
+ }
+
+ /**
+ * 二叉树层次遍历
+ */
+ public static List> levelOrder(TreeNode root) {
+ List> result = new ArrayList<>();
+ if (root == null)
+ return result;
+
+ Queue queue = new LinkedList<>();
+ queue.add(root);
+ while (!queue.isEmpty()) {
+ // 遍历每层的数据
+ int size = queue.size();
+ List list = new ArrayList<>();
+ while (size > 0) {
+ root = queue.poll();
+ list.add(root.val);
+ if (root.left != null) {
+ queue.add(root.left);
+ }
+ if (root.right != null) {
+ queue.add(root.right);
+ }
+ size--;
+ }
+ result.add(list);
+ }
+ return result;
+ }
+
+ /**
+ * 输出二叉树层次遍历的结果
+ */
+ public static void printLevelOrder(TreeNode root) {
+ PrintUtil.printLists(levelOrder(root));
+ }
+
+ public static void main(String[] args) {
+// printLevelOrder(createTree(1, null, 2, 3));
+ printLevelOrder(createTree(5, 4, 8, 11, null, 13, 4, 7, 2, null, null, null, 1));
+ //printLevelOrder(createTree(1,2,3,null,4,5,null));
+ }
+}
diff --git a/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TrieNode.java b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TrieNode.java
new file mode 100644
index 00000000..21358912
--- /dev/null
+++ b/algorithms/leetcode2/leetcode2-common/src/main/java/cn/cunchang/tree/TrieNode.java
@@ -0,0 +1,34 @@
+package cn.cunchang.tree;
+
+public class TrieNode {
+ // 26个字母
+ private final int R = 26;
+ // 不存储真实的值,TrieNode[]中不为null表示存在
+ private TrieNode[] links;
+ private boolean isEnd;
+
+ public TrieNode() {
+ links = new TrieNode[R];
+ }
+
+
+ public boolean containsKey(char ch) {
+ return links[ch - 'a'] != null;
+ }
+
+ public TrieNode get(char ch) {
+ return links[ch - 'a'];
+ }
+
+ public void put(char ch, TrieNode node) {
+ links[ch - 'a'] = node;
+ }
+
+ public void setEnd() {
+ isEnd = true;
+ }
+
+ public boolean isEnd() {
+ return isEnd;
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/linkedlist/pom.xml b/algorithms/leetcode2/linkedlist/pom.xml
new file mode 100644
index 00000000..b3ee7d09
--- /dev/null
+++ b/algorithms/leetcode2/linkedlist/pom.xml
@@ -0,0 +1,23 @@
+
+
+ 4.0.0
+
+ linkedlist
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+
+
+
+
+ leetcode2-common
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/K\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250_25_\345\233\260\351\232\276/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/K\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250_25_\345\233\260\351\232\276/Solution.java"
new file mode 100644
index 00000000..52526c46
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/K\344\270\252\344\270\200\347\273\204\347\277\273\350\275\254\351\223\276\350\241\250_25_\345\233\260\351\232\276/Solution.java"
@@ -0,0 +1,69 @@
+package cn.cunchang.K个一组翻转链表_25_困难;
+
+import cn.cunchang.linkedlist.LinkedListUtil;
+import cn.cunchang.linkedlist.ListNode;
+
+/**
+ * @author cunchang
+ * @date 2022/6/20 8:33 PM
+ */
+public class Solution {
+
+ public ListNode reverseKGroup(ListNode head, int k) {
+ if (head == null) {
+ return null;
+ }
+ int step = 0;
+ ListNode result = null; // 返回结果
+ ListNode current = head; // 当前起点
+ ListNode next = current; // 下一个k起点
+ ListNode preTail = null; // 上一次反转后的尾结点
+ while (current != null) {
+ while (next != null && step < k) {
+ next = next.next;
+ step++;
+ }
+ // 剩余链表不够反转,就不反转了
+ // next == null不能够代表"剩余链表不够反转",可能是刚好够反转
+ if (step < k && preTail != null) {
+ preTail.next = current;
+ break;
+ }
+
+ step = 0;
+ // 反转后返回头结点
+ ListNode tail = reverse1(current, k);
+ if (preTail != null) {
+ preTail.next = tail;
+ }
+ if (preTail == null) { // 第一次反转的头结点
+ result = tail;
+ }
+ preTail = current;//反转链表的尾结点
+
+ current = next;
+ }
+ return result;
+ }
+
+ // 返回头
+ public ListNode reverse1(ListNode head, int k) {
+ ListNode pre = null;
+ ListNode current = head;
+ ListNode next = null;
+ while (current != null && k > 0) {
+ next = current.next;
+ current.next = pre;
+ pre = current;
+ current = next;
+ k--;
+ }
+ return pre;
+ }
+
+ public static void main(String[] args) {
+ ListNode listNode1 = new Solution().reverseKGroup(
+ LinkedListUtil.createListNode(1,2,3,4), 2);
+ LinkedListUtil.printListNode(listNode1);
+ }
+}
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\344\270\244\344\270\244\344\272\244\346\216\245\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\344\270\244\344\270\244\344\272\244\346\216\245\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..8ddba5a7
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\344\270\244\344\270\244\344\272\244\346\216\245\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271_24_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,58 @@
+package cn.cunchang.两两交接链表中的节点_24_中等;
+
+import cn.cunchang.linkedlist.LinkedListUtil;
+import cn.cunchang.linkedlist.ListNode;
+
+class Solution {
+
+ public ListNode swapPairs(ListNode head) {
+ if (head == null || head.next == null) {
+ return head;
+ }
+ ListNode holder = head.next;
+ ListNode pre = null;
+ ListNode headTemp = head;
+ while (headTemp != null && headTemp.next != null) {
+ ListNode next = headTemp.next.next;
+ // 2的next执行1
+ // 4的next执行3
+ headTemp.next.next = headTemp;
+ if (pre != null) {
+ // 4的next执行3时,1指向4,而不是1指向3
+ pre.next = headTemp.next;
+ }
+ // 当前节点next指向下下个节点;1指向3
+ headTemp.next = next;
+ pre = headTemp;
+ headTemp = next;
+ }
+ return holder;
+ }
+
+// public ListNode swapPairs(ListNode head) {
+// ListNode holder = new ListNode(-1);
+// holder.next = head;
+// ListNode virtual = holder;
+// while (virtual.next != null && virtual.next.next != null) {
+// ListNode start = virtual.next;
+// ListNode end = virtual.next.next;
+// // 虚拟节点的next指向2
+// virtual.next = end;
+// // 1的next指向2的next,就是3,1.next=3
+// start.next = end.next;
+// // 2的next指向1,2.next = 1
+// end.next = start;
+// // 目前就是 -1,2,1,3,4,start=1
+// virtual = start;
+// }
+// return holder.next;
+// }
+
+ public static void main(String[] args) {
+ LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1, 2, 3, 4)));
+ LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1, 2, 3, 4, 5, 6)));
+ LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1, 2, 3, 4, 5)));
+ LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode(1)));
+ LinkedListUtil.printListNode(new Solution().swapPairs(LinkedListUtil.createListNode()));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..3406a2d6
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,58 @@
+package cn.cunchang.反转链表_206_简单;
+
+import cn.cunchang.linkedlist.LinkedListUtil;
+import cn.cunchang.linkedlist.ListNode;
+
+import java.util.Stack;
+
+class Solution {
+
+ // 递归
+// public ListNode reverseList(ListNode head) {
+// if (head == null || head.next == null) {
+// return head;
+// }
+// // newHead其实就是最后一个节点,唯一的作用就是让函数调用方拿到这个反转后的单链表的头,原先的head节点现在是尾结点了
+// // 通过递归遍历链表,在遍历每一个节点的时候,让当前节点的下一个节点next指向当前节点,当前节点next指向null
+// // 由于栈先进后出,所以其实是从后往前遍历的,所以不需要像正向遍历的时候那样,记录前指针、next指针
+// ListNode newHead = reverseList(head.next);
+// head.next.next = head;
+// head.next = null;
+// return newHead;
+// }
+
+ // 栈
+ public ListNode reverseList(ListNode head) {
+ if (head == null) {
+ return null;
+ }
+ ListNode newHead;
+
+ Stack stack = new Stack<>();
+ // head=>1->2->3->4->5
+ // stack=4<-3<-2<-1
+ while (head.next != null) {
+ stack.push(head);
+ head = head.next;
+ }
+ // 握住尾结点,将来它是首节点;等价递归里面的newHead,也可以不要直接返回head
+ newHead = head;
+ // stack=4<-3<-2<-1
+ while (!stack.isEmpty()) {
+ // 把4弹出来,4->5;依次把321都弹出来
+ ListNode current = stack.pop();
+ // 5->4
+ current.next.next = current;
+ // 4->null
+ current.next = null;
+ }
+ return newHead;
+ }
+
+ public static void main(String[] args) {
+ ListNode listNode = LinkedListUtil.createListNode(1, 2, 3, 4, 5);
+ LinkedListUtil.printListNode(listNode);
+ LinkedListUtil.printListNode(new Solution().reverseList(listNode));
+ }
+
+}
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java"
new file mode 100644
index 00000000..19d8a2f5
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\217\215\350\275\254\351\223\276\350\241\250_206_\347\256\200\345\215\225/Solution2.java"
@@ -0,0 +1,22 @@
+package cn.cunchang.反转链表_206_简单;
+
+
+import cn.cunchang.linkedlist.ListNode;
+
+class Solution2 {
+
+ public ListNode reverseList(ListNode head) {
+ ListNode pre = null;//无法找到前一个节点,所以需要记录前一个节点
+ ListNode current = head;// 当前节点
+
+ while (current != null) {
+ ListNode next = current.next;// next节点,防止current反转后找不到next了
+ current.next = pre;
+ pre = current;
+ current = next;
+ }
+
+ return pre;
+ }
+
+}
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..70bf5f86
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250_21_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,34 @@
+package cn.cunchang.合并两个有序链表_21_中等;
+
+import cn.cunchang.linkedlist.LinkedListUtil;
+import cn.cunchang.linkedlist.ListNode;
+
+class Solution {
+ public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
+ ListNode mergeList = new ListNode(-1);
+ ListNode mergeNode = mergeList;
+ while (list1 != null && list2 != null) {
+ if (list1.val >= list2.val) {
+ mergeNode.next = list2;
+ list2 = list2.next;
+ } else {
+ mergeNode.next = list1;
+ list1 = list1.next;
+ }
+ mergeNode = mergeNode.next;
+ }
+ if (list1 != null) {
+ mergeNode.next = list1;
+ }
+ if (list2 != null) {
+ mergeNode.next = list2;
+ }
+ return mergeList.next;
+ }
+
+ public static void main(String[] args) {
+ ListNode list1 = LinkedListUtil.createListNode(1, 2, 4);
+ ListNode list2 = LinkedListUtil.createListNode(1, 3, 4);
+ LinkedListUtil.printListNode(new Solution().mergeTwoLists(list1, list2));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..ff87fe54
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\345\233\236\346\226\207\351\223\276\350\241\250_234_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,48 @@
+package cn.cunchang.回文链表_234_简单;
+
+import cn.cunchang.linkedlist.LinkedListUtil;
+import cn.cunchang.linkedlist.ListNode;
+
+class Solution {public boolean isPalindrome(ListNode head) {
+ if (head == null || head.next == null) {
+ return true;
+ }
+ ListNode fast = head, slow = head;
+ while (fast.next != null && fast.next.next != null) {
+ slow = slow.next;
+ fast = fast.next.next;
+ }
+ ListNode list1 = reverse(slow);
+ ListNode list2 = head;
+ while (list1 != null && list2 != null) {
+ if (list1.val != list2.val) {
+ return false;
+ }
+ list1 = list1.next;
+ list2 = list2.next;
+ }
+
+ return true;
+}
+
+ public ListNode reverse(ListNode head) {
+ ListNode pre = null;//无法找到前一个节点,所以需要记录前一个节点
+ ListNode current = head;// 当前节点
+ while (current != null) {
+ ListNode next = current.next;// next节点,防止current反转后找不到next了
+ current.next = pre;
+ pre = current;
+ current = next;
+ }
+ return pre;
+ }
+
+
+ public static void main(String[] args) {
+// ListNode listNode = LinkedListUtil.createListNode(1, 2, 2, 1);
+// ListNode listNode = LinkedListUtil.createListNode(1, 2, 3, 2, 1);
+ ListNode listNode = LinkedListUtil.createListNode(1, 1);
+ LinkedListUtil.printListNode(listNode);
+ System.out.println(new Solution().isPalindrome(listNode));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\346\216\222\345\272\217\351\223\276\350\241\250_148_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\346\216\222\345\272\217\351\223\276\350\241\250_148_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..157baf5e
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\346\216\222\345\272\217\351\223\276\350\241\250_148_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,61 @@
+package cn.cunchang.排序链表_148_中等;
+
+import cn.cunchang.linkedlist.LinkedListUtil;
+import cn.cunchang.linkedlist.ListNode;
+
+class Solution {
+ public ListNode sortList(ListNode head) {
+ // 递归终止点
+ if (head == null || head.next == null) {
+ return head;
+ }
+ // 1. 快慢指针法,遍历链表找到中间节点
+ ListNode fast = middleBeforeNode(head);
+ // 2. 中间节点切断链表
+ ListNode mid = fast.next;//直接用fast当中间节点也可以,但是为了切断链表,用next比较方便
+ fast.next = null;
+ // 3. 分别用归并排序排左右子链表
+ ListNode leftNode = sortList(head);
+ ListNode rightNode = sortList(mid);
+ // 4. 合并子链表
+ return mergeTwoLists(leftNode, rightNode);
+ }
+
+ public static ListNode middleBeforeNode(ListNode head) {
+ ListNode fast = head;
+ ListNode slow = head;
+ while (fast.next != null && fast.next.next != null) {
+ fast = fast.next.next;
+ slow = slow.next;
+ }
+ return slow;
+ }
+
+ public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
+ ListNode mergeList = new ListNode(-1);
+ ListNode mergeNode = mergeList;
+ while (list1 != null && list2 != null) {
+ if (list1.val >= list2.val) {
+ mergeNode.next = list2;
+ list2 = list2.next;
+ } else {
+ mergeNode.next = list1;
+ list1 = list1.next;
+ }
+ mergeNode = mergeNode.next;
+ }
+ if (list1 != null) {
+ mergeNode.next = list1;
+ }
+ if (list2 != null) {
+ mergeNode.next = list2;
+ }
+ return mergeList.next;
+ }
+
+ public static void main(String[] args) {
+ LinkedListUtil.printListNode(new Solution().
+ sortList(LinkedListUtil.createListNode(9, 8, 7, 6, 5, 4, 3, 2, 1)));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..d6f9e707
--- /dev/null
+++ "b/algorithms/leetcode2/linkedlist/src/main/java/cn/cunchang/\347\233\270\344\272\244\351\223\276\350\241\250_160_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,44 @@
+package cn.cunchang.相交链表_160_简单;
+
+import cn.cunchang.linkedlist.ListNode;
+
+public class Solution {
+ public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
+ // 计算ab的长度
+ int lenA = 0, lenB = 0;
+ ListNode lenHeadA = headA;
+ ListNode lenHeadB = headB;
+ while (lenHeadA != null) {
+ lenA++;
+ lenHeadA = lenHeadA.next;
+ }
+ while (lenHeadB != null) {
+ lenB++;
+ lenHeadB = lenHeadB.next;
+ }
+ // 将ab头设置到相同位置
+ int diff = Math.abs(lenA - lenB);
+ ListNode startHeadA = headA;
+ ListNode startHeadB = headB;
+ if (lenA > lenB) {
+ while (diff > 0) {
+ startHeadA = startHeadA.next;
+ diff--;
+ }
+ } else {
+ while (diff > 0) {
+ startHeadB = startHeadB.next;
+ diff--;
+ }
+ }
+ // 比较,有相同说明相交
+ while (startHeadA != null && startHeadB != null) {
+ if (startHeadA == startHeadB) {
+ return startHeadA;
+ }
+ startHeadA = startHeadA.next;
+ startHeadB = startHeadB.next;
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/other-algo/pom.xml b/algorithms/leetcode2/other-algo/pom.xml
new file mode 100644
index 00000000..2f4ad098
--- /dev/null
+++ b/algorithms/leetcode2/other-algo/pom.xml
@@ -0,0 +1,19 @@
+
+
+
+ leetcode2
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ other-algo
+
+
+ 8
+ 8
+
+
+
\ No newline at end of file
diff --git "a/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache.java" "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache.java"
new file mode 100644
index 00000000..19e14ec9
--- /dev/null
+++ "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache.java"
@@ -0,0 +1,126 @@
+package cn.cunchang.LRU缓存_146_中等;
+
+import org.junit.Assert;
+
+import java.util.HashMap;
+
+/**
+ * @author cunchang
+ * @date 2022/7/4 10:28 AM
+ */
+class LRUCache {
+
+ public static void main(String[] args) {
+ LRUCache lRUCache = new LRUCache(2);
+ lRUCache.put(2, 1);
+ lRUCache.put(3, 2);
+ Assert.assertEquals(2, lRUCache.get(3));
+ Assert.assertEquals(1, lRUCache.get(2));
+ lRUCache.put(4, 3);
+ Assert.assertEquals(1, lRUCache.get(2));
+ Assert.assertEquals(-1, lRUCache.get(3));
+ Assert.assertEquals(3, lRUCache.get(4));
+ }
+
+ // 要求"函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。"
+ // hashmap存储kv保证 get、put O(1)、linkedlist存储k保证淘汰队尾
+ DoubleLinkedList list;
+ HashMap kv;
+ int capacity;
+
+ /**
+ * 以 正整数 作为容量 capacity 初始化 LRU 缓存
+ */
+ public LRUCache(int capacity) {
+ this.capacity = capacity;
+ list = new DoubleLinkedList();
+ kv = new HashMap<>();
+ }
+
+ /**
+ * 要求:如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
+ * 实现:
+ * 1、直接从map里面get,不存在返回-1
+ * 2、存在,将list里面的node节点删除,并加到队头
+ */
+ public int get(int key) {
+ Node node = kv.get(key);
+ if (node == null) {
+ return -1;
+ }
+ list.remove(node);
+ list.addFirst(node);
+ return node.v;
+ }
+
+ /**
+ * 要求:
+ * 1、如果关键字 key 已经存在,则变更其数据值 value ;
+ * 2、如果不存在,则向缓存中插入该组 key-value 。
+ * 3、如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
+ * 实现:
+ * 1、k在map中存在,直接覆盖
+ * 2、k在map中不存在,
+ * - 如果插入关键字数量未超过 capacity,put到map,add到list
+ * - 超过了,走淘汰逻辑,移除list队尾的k,同时在map中删除k。然后继续put即可
+ */
+ public void put(int key, int value) {
+ Node node = kv.get(key);
+ if (node != null) {
+ list.remove(node);
+ list.addFirst(node);
+ node.v = value;
+ return;
+ }
+ if (kv.size() >= capacity) {
+ Node last = list.removeLast();
+ kv.remove(last.k);
+ }
+ node = new Node(key, value);
+ kv.put(key, node);
+ list.addFirst(node);
+ }
+
+ class DoubleLinkedList {
+ Node head;
+ Node tail;
+
+ public DoubleLinkedList() {
+ head = new Node(0, 0);
+ tail = new Node(0, 0);
+ head.next = tail;
+ tail.prev = head;
+ }
+
+ // 删除某个节点
+ public void remove(Node node) {
+ node.prev.next = node.next;
+ node.next.prev = node.prev;
+ }
+
+ // node节点插入
+ public void addFirst(Node node) {
+ node.next = head.next;//构建node.next
+ node.prev = head; // 构建node.pre
+ head.next.prev = node;// 构建原head.pre
+ head.next = node;// 构建head.next
+ }
+ public Node removeLast() {
+ if (tail.prev == head)
+ return null;
+ Node last = tail.prev;
+ remove(last);
+ return last;
+ }
+ }
+
+ static class Node {
+ int k, v;
+ Node prev, next;
+
+ public Node(int k, int v) {
+ this.k = k;
+ this.v = v;
+ }
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache2.java" "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache2.java"
new file mode 100644
index 00000000..b799ea81
--- /dev/null
+++ "b/algorithms/leetcode2/other-algo/src/main/java/cn/cunchang/LRU\347\274\223\345\255\230_146_\344\270\255\347\255\211/LRUCache2.java"
@@ -0,0 +1,59 @@
+package cn.cunchang.LRU缓存_146_中等;
+
+import org.junit.Assert;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+
+class LRUCache2 {
+
+ private int capacity;
+
+ private LinkedList keyCache = new LinkedList<>();
+
+ private HashMap keyAndValueCache = new HashMap<>();
+
+ public LRUCache2(int capacity) {
+ this.capacity = capacity;
+ }
+
+ public int get(int key) {
+ final Integer value = keyAndValueCache.get(key);
+ if (value == null) {
+ return -1;
+ }
+ keyCache.remove((Object)key);
+ keyCache.addLast(key);
+ return value;
+ }
+
+ public void put(int key, int value) {
+ if (keyCache.contains(key)) {
+ keyCache.remove((Object)key);
+ keyCache.addLast(key);
+ keyAndValueCache.put(key, value);
+ return;
+ }
+
+ if (keyCache.size() >= capacity) {
+ Integer k = keyCache.removeFirst();
+ keyAndValueCache.remove(k);
+ }
+ keyCache.addLast(key);
+ keyAndValueCache.put(key, value);
+ }
+
+
+ public static void main(String[] args) {
+ LRUCache2 lRUCache = new LRUCache2(2);
+ lRUCache.put(2, 1);
+ lRUCache.put(3, 2);
+ Assert.assertEquals(2,lRUCache.get(3));
+ Assert.assertEquals(1,lRUCache.get(2));
+ lRUCache.put(4, 3);
+ Assert.assertEquals(1,lRUCache.get(2));
+ Assert.assertEquals(-1,lRUCache.get(3));
+ Assert.assertEquals(3,lRUCache.get(4));
+ }
+
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/point/pom.xml b/algorithms/leetcode2/point/pom.xml
new file mode 100644
index 00000000..deb07872
--- /dev/null
+++ b/algorithms/leetcode2/point/pom.xml
@@ -0,0 +1,15 @@
+
+
+ 4.0.0
+
+ point
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+ 8
+ 8
+
+
+
\ No newline at end of file
diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..c914c932
--- /dev/null
+++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\344\270\244\346\225\260\344\271\213\345\222\214_II_\350\276\223\345\205\245\346\234\211\345\272\217\346\225\260\347\273\204_167_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,42 @@
+package cn.cunchang.两数之和_II_输入有序数组_167_简单;
+
+import java.util.Arrays;
+
+class Solution {
+ /**
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ * "非递减顺序排列"表示升序
+ * p1指向头,p2指向尾;num[p1]+num[p2]和target比会有三种情况;
+ * num[p1]+num[p2]==target说明p1、p2就是两数之和
+ * num[p1]+num[p2]>target说明p2大了,p2-1再试试
+ * num[p1]+num[p2] target) {
+ p2--;
+ } else if (tmp < target) {
+ p1++;
+ } else {
+ break;
+ }
+ }
+ return new int[]{p1+1, p2+1};
+ }
+
+ public static void main(String[] args) {
+ int[] numbers = new int[]{2, 7, 11, 15};
+ int target = 9;
+ System.out.println(Arrays.toString(
+ new Solution().twoSum(numbers, target)));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..a2ce97f2
--- /dev/null
+++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204_88_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,40 @@
+package cn.cunchang.合并两个有序数组_88_简单;
+
+class Solution {
+ /**
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ * m为num1指针,n为num2指针,p=m+n+1为复制位置指针
+ * num1、num2从后往前,最大复制到num1尾部
+ * num1复制完了,把num2剩余复制到num1。num2复制完了,就结束了。
+ *
+ * -------------------------------------------------------------------
+ * 时间复杂度:
+ * 空间复杂度:
+ */
+ public void merge(int[] nums1, int m, int[] nums2, int n) {
+ // 记录复制的位置
+ int p = m + n - 1;
+ m--;
+ n--;
+ while (m >= 0 && n >= 0) {
+ if (nums2[n] > nums1[m]) {
+ nums1[p] = nums2[n];
+ n--;
+ } else {
+ nums1[p] = nums1[m];
+ m--;
+ }
+ p--;
+ }
+ // 复制num2
+ if (n >= 0) {
+ for (int i = n; i >= 0; i--) {
+ nums1[p] = nums2[i];
+ p--;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution1.java"
new file mode 100644
index 00000000..0f80d8a8
--- /dev/null
+++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution1.java"
@@ -0,0 +1,72 @@
+package cn.cunchang.最小覆盖子串_76_困难;
+
+class Solution1 {
+ /**
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ * 1、将s串中的所有子串与t串比较,取最短的子串
+ * 2、s子串与t串比较的逻辑:数组sarr记录t字符串的频率,遍历s字符,删除sarr中记录t字符的频率
+ * 最后遍历sarr查看t字符串的频率是否还存在,存在说明不是覆盖子串
+ *
+ * 暴力解法,超时了
+ * -------------------------------------------------------------------
+ * 时间复杂度:
+ * 空间复杂度:
+ */
+ public String minWindow(String s, String t) {
+ if (s.length() < t.length()) {
+ return ""; //"a","aa"
+ }
+ if (s.equals(t)) {
+ return s;
+ }
+ int l = 0, r = 0;
+ String target = "";
+ while (l <= s.length() && r <= s.length()) {
+ if (r - l >= t.length()) {
+ String sub = s.substring(l, r);
+ if (isSub(sub, t)) {
+ if ("".equals(target)) {// 第一次找到
+ target = sub;
+ }
+ if (target.length() > sub.length()) { //第n次找到,要最优的
+ target = sub;
+ }
+ l++;
+ r = l;
+ }
+ }
+ r++;
+ }
+ return target;
+ }
+
+ private boolean isSub(String sub, String t) {
+ if (sub.length() < t.length()) {
+ return false;
+ }
+ int[] set = new int[128];
+ for (char c : t.toCharArray()) {
+ set[c]++;//记录t字符
+ }
+ for (char c : sub.toCharArray()) {
+ set[c]--;//删除t字符
+ }
+ for (char c : t.toCharArray()) {
+ if (set[c] > 0) {// 说明有t字符没有被删除,即sub不完全包含t
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static void main(String[] args) {
+// String s = "ADOBECODEBANC", t = "ABC";
+// System.out.println(new Solution().minWindow(s, t));
+ String s = "obzcopzocynyrsgsarijyxnkpnukkrvzuwdjldxndmnvevpgmxrmvfwkutwekrffnloyqnntbdohyfqndhzyoykiripdzwiojyoznbtogjyfpouuxvumtewmmnqnkadvzrvouqfbbdiqremqzgevkbhyoznacqwbhtrcjwfkzpdstpjswnpiqxjhywjanhdwavajrhwtwzlrqwmombxcaijzevbtcfsdcuovckoalcseaesmhrrizcjgxkbartdtotpsefsrjmvksqyahpijsrppdqpvmuocofuunonybjivbjviyftsyiicbzxnwnrmvlgkzticetyfcvqcbjvbufdxgcmesdqnowzpshuwcseenwjqhgsdlxatamysrohfnixfprdsljyyfhrnnjsagtuihuczilgvtfcjwgdhpbixlzmakebszxbhrdibpoxiwztshwczamwnninzmqrmpsviydkptjzpktksrortapgpxwojofxeasoyvyprjoguhqobehugwdvtzlenrcttuitsiijswpogicjolfxhiscjggzzissfcnxnvgftxvbfzkukqrtalvktdjsodmtgzqtuyaqvvrbuexgwqzwduixzrpnvegddyyywaquxjxrnuzlmyipuqotkghfkpknqinoidifnfyczzonxydtqroazxhjnrxfbmtlqcsfhshjrxwqvblovaouxwempdrrplefnxmwrwfjtebrfnfanvvmtbzjesctdgbsfnpxlwihalyiafincfcwgdfkvhebphtxukwgjgplrntsuchyjjuqozakiglangxkttsczhnswjksnuqwflmumpexxrznzwxurrysaokwxxqkrggytvsgkyfjrewrcvntomnoazmzycjrjrqemimyhriyxgrzcfuqtjhvjtuhwfzhwpljzajitrhryaqchnuawbxhxrpvyqcvhpggrpplhychyulijhkglinibedauhvdydkqszdbzfkzbvhldstocgydnbfjkcnkfxcyyfbzmmyojgzmasccaahpdnzproaxnexnkamwmkmwslksfpwirexxtymkmojztgmfhydvlqtddewjvsrmyqjrpycbmndhupmdqqabiuelacuvxnhxgtpvrtwfgzpcrbhhtikbcqpctlxszgpfbgcsbaaiapmtsucocmpecgixshrrnhyrpalralbccnxvjzjllarqhznzghswqsnfuyywmzbopyjyauknxddgdthlabjqtwxpxwljvoxkpjjpfvccyikbbrpdsyvlxscuoofkecwtnfkvcnzbxkeabtdusyhrqklhaqreupakxkfzxgawqfwsaboszvlshwzhosojjotgyagygguzntrouhiweuomqptfjjqsxlbylhwtpssdlltgubczxslqjgxuqnmpynnlwjgmebrpokxjnbiltvbebyytnnjlcwyzignmhedwqbfdepqakrelrdfesqrumptwwgifmmbepiktxavhuavlfaqxqhreznbvvlakzeoomykkzftthoemqwliednfsqcnbexbimrvkdhllcesrlhhjsspvfupxwdybablotibypmjutclgjurbmhztboqatrdwsomnxnmocvixxvfiqwmednahdqhxjkvcyhpxxdmzzuyyqdjibvmfkmonfxmohhshpkhmntnoplphqyprveyfsmsxjfosmicdsjrieeytpnbhlsziwxnpmgoxneqbnufhfwrjbqcsdfarybzwaplmxckkgclvwqdbpumsmqkswmjwnkuqbicykoisqwoootrdpdvcuiuswfqmrkctsgrevcxnyncmivsxbpbxzxpwchiwtkroqisnmrbmefbmatmdknaklpgpyqlsccgunaibsloyqpnsibwuowebomrmcegejozypjzjunjmeygozcjqbnrpakdermjcckartbcppmbtkhkmmtcngteigjnxxyzaibtdcwutkvpwezisskfaeljmxyjwykwglqlnofhycwuivdbnpintuyhtyqpwaoelgpbuwiuyeqhbvkqlsfgmeoheexbhnhutxvnvfjwlzfmvpcghiowocdsjcvqrdmkcizxnivbianfpsnzabxqecinhgfyjrjlbikrrgsbgfgyxtzzwwpayapfgueroncpxogouyrdgzdfucfrywtywjeefkvtzxlwmrniselyeodysirqflpduvibfdvedgcrzpzrunpadvawfsmmddqzaaahfxlifobffbyzqqbtlcpquedzjvykvarayfldvmkapjcfzfbmhscdwhciecsbdledspgpdtsteuafzbrjuvmsfrajtulwirzagiqjdiehefmfifocadxfuxrpsemavncdxuoaetjkavqicgndjkkfhbvbhjdcygfwcwyhpirrfjziqonbyxhibelinpllxsjzoiifscwzlyjdmwhnuovvugfhvquuleuzmehggdfubpzolgbhwyeqekzccuypaspozwuhbzbdqdtejuniuuyagackubauvriwneeqfhtwkocuipcelcfrcjcymcuktegiikyosumeioatfcxrheklookaqekljtvtdwhxsteajevpjviqzudnjnqbucnfvkybggaybebljwcstmktgnipdyrxbgewqczzkaxmeazpzbjsntltjwlmuclxirwytvxgvxscztryubtjweehapvxrguzzsatozzjytnamfyiitreyxmanhzeqwgpoikcjlokebksgkaqetverjegqgkicsyqcktmwjwakivtsxjwrgakphqincqrxqhzbcnxljzwturmsaklhnvyungjrxaonjqomdnxpnvihmwzphkyuhwqwdboabepmwgyatyrgtboiypxfavbjtrgwswyvcqhzwibpisydtmltbkydhznbsvxktyfxopwkxzbftzknnwipghuoijrbgqnzovxckvojvsqqraffwowfvqvfcmiicwitrhxdeombgesxexedlakitfovtydxunqnwqqdeeekiwjnwoshqcsljiicgobbbuqakjdonjawgjlezdnqhfdqnmsuavxdpnfzwipmspiabveaarshzwxmirgkmfncvtdrdvfxkpxlkdokxgtwcskmjryyymcthfnkasinihaunohkxaibtsqelockaefjmsuolebtnepauwmrxutspjwaxbmahsjtkfkxlnszribmeofbkyvbjscjtqjakuwvcgunvnonvqbbggfshauqsyznokqbhowjusypfnecffenojfvlblgzntqzlrgzprvhqnpfrrkzxznieiuivajivzijsqijigtatifmbplzqahuidegfoobpymkputzamzvweiyvvzlwihgmmmrcburbgbsdxrfjsbiylitghgcpqjbevvgypxcybubyoijijrhuzcdijfybqbfowlookqmlnplbxvjjosfqviygqyhgamuwzjklbyzopkrnhbywtfoqomweldmlrhjqswctubiknzzvcztyehouvnyiqnvkufaobehxhrjvtisxjlxoumipzjarwvbsaegdkpbsjmpevjbewzuqnfhoohhmdjgfpmjzdmtmykqvtucptwfidpwtwffzolffzqfdearclkyeecuzabjeqhxpmfodsvisnpxrqowdawheydfyhoexvcmihdlzavtqlshdhdgjzpozvvackebhgqppvcrvymljfvooauxcjnbejdivikcoaugxwzsulgfqdtefpehbrlhaoqxwcancuvbqutnfbuygoemditeagmcveatgaikwflozgdhkyfqmjcruyyuemwbqwxyyfiwnvlmbovlmccaoguieu",
+ t = "cjgamyzjwxrgwedhsexosmswogckohesskteksqgrjonnrwhywxqkqmywqjlxnfrayykqotkzhxmbwvzstrcjfchvluvbaobymlrcgbbqaprwlsqglsrqvynitklvzmvlamqipryqjpmwhdcsxtkutyfoiqljfhxftnnjgmbpdplnuphuksoestuckgopnlwiyltezuwdmhsgzzajtrpnkkswsglhrjprxlvwftbtdtacvclotdcepuahcootzfkwqhtydwrgqrilwvbpadvpzwybmowluikmsfkvbebrxletigjjlealczoqnnejvowptikumnokysfjyoskvsxztnqhcwsamopfzablnrxokdxktrwqjvqfjimneenqvdxufahsshiemfofwlyiionrybfchuucxtyctixlpfrbngiltgtbwivujcyrwutwnuajcxwtfowuuefpnzqljnitpgkobfkqzkzdkwwpksjgzqvoplbzzjuqqgetlojnblslhpatjlzkbuathcuilqzdwfyhwkwxvpicgkxrxweaqevziriwhjzdqanmkljfatjifgaccefukavvsfrbqshhswtchfjkausgaukeapanswimbznstubmswqadckewemzbwdbogogcysfxhzreafwxxwczigwpuvqtathgkpkijqiqrzwugtr";
+ System.out.println(new Solution1().minWindow(s, t));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution2.java"
new file mode 100644
index 00000000..3b80d759
--- /dev/null
+++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262_76_\345\233\260\351\232\276/Solution2.java"
@@ -0,0 +1,49 @@
+package cn.cunchang.最小覆盖子串_76_困难;
+
+import java.util.HashMap;
+
+class Solution2 {
+
+ public String minWindow(String s, String t) {
+ HashMap windows = new HashMap<>();
+ // 记录字符串需要的字符以及数量
+ HashMap need = new HashMap<>();
+ for (int i = 0; i < t.length(); i++) {
+ char c = t.charAt(i);
+ need.put(c, need.getOrDefault(c, 0) + 1);
+ }
+ int l = 0, r = 0;
+ int valid = 0;
+ int start = 0, len = Integer.MAX_VALUE;
+ while (r < s.length()) {
+ char c = s.charAt(r);
+ // 扩大窗口
+ r++;
+
+ if (need.containsKey(c)) {
+ windows.put(c, windows.getOrDefault(c, 0) + 1);
+ if (windows.get(c).equals(need.get(c))) {
+ valid++;
+ }
+ }
+
+ // s串窗口中寻找到的满足t串
+ while (valid == need.size()) {
+
+ }
+
+
+ }
+
+ return null;
+ }
+
+
+ public static void main(String[] args) {
+ String s = "ADOBECODEBANC", t = "ABC";
+ System.out.println(new Solution2().minWindow(s, t));
+// String s = "obzcopzocynyrsgsarijyxnkpnukkrvzuwdjldxndmnvevpgmxrmvfwkutwekrffnloyqnntbdohyfqndhzyoykiripdzwiojyoznbtogjyfpouuxvumtewmmnqnkadvzrvouqfbbdiqremqzgevkbhyoznacqwbhtrcjwfkzpdstpjswnpiqxjhywjanhdwavajrhwtwzlrqwmombxcaijzevbtcfsdcuovckoalcseaesmhrrizcjgxkbartdtotpsefsrjmvksqyahpijsrppdqpvmuocofuunonybjivbjviyftsyiicbzxnwnrmvlgkzticetyfcvqcbjvbufdxgcmesdqnowzpshuwcseenwjqhgsdlxatamysrohfnixfprdsljyyfhrnnjsagtuihuczilgvtfcjwgdhpbixlzmakebszxbhrdibpoxiwztshwczamwnninzmqrmpsviydkptjzpktksrortapgpxwojofxeasoyvyprjoguhqobehugwdvtzlenrcttuitsiijswpogicjolfxhiscjggzzissfcnxnvgftxvbfzkukqrtalvktdjsodmtgzqtuyaqvvrbuexgwqzwduixzrpnvegddyyywaquxjxrnuzlmyipuqotkghfkpknqinoidifnfyczzonxydtqroazxhjnrxfbmtlqcsfhshjrxwqvblovaouxwempdrrplefnxmwrwfjtebrfnfanvvmtbzjesctdgbsfnpxlwihalyiafincfcwgdfkvhebphtxukwgjgplrntsuchyjjuqozakiglangxkttsczhnswjksnuqwflmumpexxrznzwxurrysaokwxxqkrggytvsgkyfjrewrcvntomnoazmzycjrjrqemimyhriyxgrzcfuqtjhvjtuhwfzhwpljzajitrhryaqchnuawbxhxrpvyqcvhpggrpplhychyulijhkglinibedauhvdydkqszdbzfkzbvhldstocgydnbfjkcnkfxcyyfbzmmyojgzmasccaahpdnzproaxnexnkamwmkmwslksfpwirexxtymkmojztgmfhydvlqtddewjvsrmyqjrpycbmndhupmdqqabiuelacuvxnhxgtpvrtwfgzpcrbhhtikbcqpctlxszgpfbgcsbaaiapmtsucocmpecgixshrrnhyrpalralbccnxvjzjllarqhznzghswqsnfuyywmzbopyjyauknxddgdthlabjqtwxpxwljvoxkpjjpfvccyikbbrpdsyvlxscuoofkecwtnfkvcnzbxkeabtdusyhrqklhaqreupakxkfzxgawqfwsaboszvlshwzhosojjotgyagygguzntrouhiweuomqptfjjqsxlbylhwtpssdlltgubczxslqjgxuqnmpynnlwjgmebrpokxjnbiltvbebyytnnjlcwyzignmhedwqbfdepqakrelrdfesqrumptwwgifmmbepiktxavhuavlfaqxqhreznbvvlakzeoomykkzftthoemqwliednfsqcnbexbimrvkdhllcesrlhhjsspvfupxwdybablotibypmjutclgjurbmhztboqatrdwsomnxnmocvixxvfiqwmednahdqhxjkvcyhpxxdmzzuyyqdjibvmfkmonfxmohhshpkhmntnoplphqyprveyfsmsxjfosmicdsjrieeytpnbhlsziwxnpmgoxneqbnufhfwrjbqcsdfarybzwaplmxckkgclvwqdbpumsmqkswmjwnkuqbicykoisqwoootrdpdvcuiuswfqmrkctsgrevcxnyncmivsxbpbxzxpwchiwtkroqisnmrbmefbmatmdknaklpgpyqlsccgunaibsloyqpnsibwuowebomrmcegejozypjzjunjmeygozcjqbnrpakdermjcckartbcppmbtkhkmmtcngteigjnxxyzaibtdcwutkvpwezisskfaeljmxyjwykwglqlnofhycwuivdbnpintuyhtyqpwaoelgpbuwiuyeqhbvkqlsfgmeoheexbhnhutxvnvfjwlzfmvpcghiowocdsjcvqrdmkcizxnivbianfpsnzabxqecinhgfyjrjlbikrrgsbgfgyxtzzwwpayapfgueroncpxogouyrdgzdfucfrywtywjeefkvtzxlwmrniselyeodysirqflpduvibfdvedgcrzpzrunpadvawfsmmddqzaaahfxlifobffbyzqqbtlcpquedzjvykvarayfldvmkapjcfzfbmhscdwhciecsbdledspgpdtsteuafzbrjuvmsfrajtulwirzagiqjdiehefmfifocadxfuxrpsemavncdxuoaetjkavqicgndjkkfhbvbhjdcygfwcwyhpirrfjziqonbyxhibelinpllxsjzoiifscwzlyjdmwhnuovvugfhvquuleuzmehggdfubpzolgbhwyeqekzccuypaspozwuhbzbdqdtejuniuuyagackubauvriwneeqfhtwkocuipcelcfrcjcymcuktegiikyosumeioatfcxrheklookaqekljtvtdwhxsteajevpjviqzudnjnqbucnfvkybggaybebljwcstmktgnipdyrxbgewqczzkaxmeazpzbjsntltjwlmuclxirwytvxgvxscztryubtjweehapvxrguzzsatozzjytnamfyiitreyxmanhzeqwgpoikcjlokebksgkaqetverjegqgkicsyqcktmwjwakivtsxjwrgakphqincqrxqhzbcnxljzwturmsaklhnvyungjrxaonjqomdnxpnvihmwzphkyuhwqwdboabepmwgyatyrgtboiypxfavbjtrgwswyvcqhzwibpisydtmltbkydhznbsvxktyfxopwkxzbftzknnwipghuoijrbgqnzovxckvojvsqqraffwowfvqvfcmiicwitrhxdeombgesxexedlakitfovtydxunqnwqqdeeekiwjnwoshqcsljiicgobbbuqakjdonjawgjlezdnqhfdqnmsuavxdpnfzwipmspiabveaarshzwxmirgkmfncvtdrdvfxkpxlkdokxgtwcskmjryyymcthfnkasinihaunohkxaibtsqelockaefjmsuolebtnepauwmrxutspjwaxbmahsjtkfkxlnszribmeofbkyvbjscjtqjakuwvcgunvnonvqbbggfshauqsyznokqbhowjusypfnecffenojfvlblgzntqzlrgzprvhqnpfrrkzxznieiuivajivzijsqijigtatifmbplzqahuidegfoobpymkputzamzvweiyvvzlwihgmmmrcburbgbsdxrfjsbiylitghgcpqjbevvgypxcybubyoijijrhuzcdijfybqbfowlookqmlnplbxvjjosfqviygqyhgamuwzjklbyzopkrnhbywtfoqomweldmlrhjqswctubiknzzvcztyehouvnyiqnvkufaobehxhrjvtisxjlxoumipzjarwvbsaegdkpbsjmpevjbewzuqnfhoohhmdjgfpmjzdmtmykqvtucptwfidpwtwffzolffzqfdearclkyeecuzabjeqhxpmfodsvisnpxrqowdawheydfyhoexvcmihdlzavtqlshdhdgjzpozvvackebhgqppvcrvymljfvooauxcjnbejdivikcoaugxwzsulgfqdtefpehbrlhaoqxwcancuvbqutnfbuygoemditeagmcveatgaikwflozgdhkyfqmjcruyyuemwbqwxyyfiwnvlmbovlmccaoguieu",
+// t = "cjgamyzjwxrgwedhsexosmswogckohesskteksqgrjonnrwhywxqkqmywqjlxnfrayykqotkzhxmbwvzstrcjfchvluvbaobymlrcgbbqaprwlsqglsrqvynitklvzmvlamqipryqjpmwhdcsxtkutyfoiqljfhxftnnjgmbpdplnuphuksoestuckgopnlwiyltezuwdmhsgzzajtrpnkkswsglhrjprxlvwftbtdtacvclotdcepuahcootzfkwqhtydwrgqrilwvbpadvpzwybmowluikmsfkvbebrxletigjjlealczoqnnejvowptikumnokysfjyoskvsxztnqhcwsamopfzablnrxokdxktrwqjvqfjimneenqvdxufahsshiemfofwlyiionrybfchuucxtyctixlpfrbngiltgtbwivujcyrwutwnuajcxwtfowuuefpnzqljnitpgkobfkqzkzdkwwpksjgzqvoplbzzjuqqgetlojnblslhpatjlzkbuathcuilqzdwfyhwkwxvpicgkxrxweaqevziriwhjzdqanmkljfatjifgaccefukavvsfrbqshhswtchfjkausgaukeapanswimbznstubmswqadckewemzbwdbogogcysfxhzreafwxxwczigwpuvqtathgkpkijqiqrzwugtr";
+// System.out.println(new Solution2().minWindow(s, t));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/point/src/main/java/cn/cunchang/\347\216\257\345\275\242\351\223\276\350\241\250_II_142_\344\270\255\347\255\211/Solution1.java" "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\347\216\257\345\275\242\351\223\276\350\241\250_II_142_\344\270\255\347\255\211/Solution1.java"
new file mode 100644
index 00000000..1a28128c
--- /dev/null
+++ "b/algorithms/leetcode2/point/src/main/java/cn/cunchang/\347\216\257\345\275\242\351\223\276\350\241\250_II_142_\344\270\255\347\255\211/Solution1.java"
@@ -0,0 +1,42 @@
+package cn.cunchang.环形链表_II_142_中等;
+
+public class Solution1 {
+ /**
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ *
+ * -------------------------------------------------------------------
+ * 时间复杂度:
+ * 空间复杂度:
+ */
+ public ListNode detectCycle(ListNode head) {
+ // 先找到相遇点
+ ListNode fast = head, slow = head;
+ do {
+ // 说明不成环
+ if (fast == null || fast.next == null) {
+ return null;
+ }
+ fast = fast.next.next;
+ slow = slow.next;
+ } while (fast != slow);// 说明成环
+ // 再找成环点
+ ListNode p1 = head, p2 = slow;
+ while (p1 != p2) {
+ p1 = p1.next;
+ p2 = p2.next;
+ }
+ return p1;
+ }
+
+ class ListNode {
+ int val;
+ ListNode next;
+
+ ListNode(int x) {
+ val = x;
+ next = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/pom.xml b/algorithms/leetcode2/pom.xml
new file mode 100644
index 00000000..1f9885af
--- /dev/null
+++ b/algorithms/leetcode2/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+ cn.cucnhang
+ leetcode2
+ pom
+ 1.0-SNAPSHOT
+
+ leetcode2-common
+ sort
+ dynamic
+ backtracking
+ other-algo
+
+
+
+ 8
+ 8
+
+
+
+
+
+ junit
+ junit
+ 4.12
+
+
+
\ No newline at end of file
diff --git a/algorithms/leetcode2/sort/pom.xml b/algorithms/leetcode2/sort/pom.xml
new file mode 100644
index 00000000..b2516fa4
--- /dev/null
+++ b/algorithms/leetcode2/sort/pom.xml
@@ -0,0 +1,25 @@
+
+
+
+ leetcode2
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ sort
+
+
+ 8
+ 8
+
+
+
+ leetcode2-common
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/BucketSort.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/BucketSort.java
new file mode 100644
index 00000000..e08f47e1
--- /dev/null
+++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/BucketSort.java
@@ -0,0 +1,54 @@
+package cn.cunchang.sort;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+
+/**
+ * @author cunchang
+ * @date 2022/6/15 6:41 PM
+ */
+public class BucketSort {
+
+ public static double[] bucketSort(double[] array) {
+ //第一步:找出待排序的数组中最大和最小的元素
+ double max = array[0];
+ double min = array[0];
+ for (double i : array) {
+ if (i > max) {
+ max = i;
+ }
+ if (i < min) {
+ min = i;
+ }
+ }
+ double d = max - min;
+ //第二步:初始化桶
+ int bucketNum = array.length;
+ ArrayList> bucketList = new ArrayList>();
+ for (int i = 0; i < bucketNum; i++) {
+ bucketList.add(new LinkedList());
+ }
+ //第三步:遍历原始数组,将每个元素放入桶中
+ for (int i = 0; i < array.length; i++) {
+ // 定位元素属于第几个桶,是按照比例来定位:(array[i] - min) * (bucketNum-1) / d
+ int num = (int) ((array[i] - min) * (bucketNum - 1) / d);
+ bucketList.get(num).add(array[i]);
+ }
+ //第四步:对每个桶内的数据进行排序
+ for (int i = 0; i < bucketList.size(); i++) {
+ Collections.sort(bucketList.get(i));
+ }
+ //第五步:输入全部元素
+ double[] sortArray = new double[array.length];
+ int index = 0;
+ for (LinkedList list : bucketList) {
+ for (double element : list) {
+ sortArray[index] = element;
+ index++;
+ }
+ }
+ return sortArray;
+ }
+
+}
diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap1.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap1.java
new file mode 100644
index 00000000..c53463d0
--- /dev/null
+++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap1.java
@@ -0,0 +1,100 @@
+package cn.cunchang.sort;
+
+import java.util.Arrays;
+
+public class Heap1 {
+ private int[] a; // 数组,从下标 1 开始存储数据
+ private int n; // 堆可以存储的最大数据个数
+ private int count; // 堆中已经存储的数据个数
+
+ public Heap1(int capacity) {
+ a = new int[capacity + 1];
+ n = capacity;
+ count = 0;
+ }
+
+ /**
+ * 插入
+ */
+ public void insert(int data) {
+ if (count >= n) return; // 堆满了
+ ++count;
+ a[count] = data;
+ int i = count;
+ while (i / 2 > 0 && a[i] > a[i / 2]) { // 自下往上堆化
+ swap(a, i, i / 2); // swap() 函数作用:交换下标为 i 和 i/2 的两个元素
+ i = i / 2;
+ }
+ }
+
+ /**
+ * 删除堆顶
+ */
+ public void removeMax() {
+ if (count == 0) return; // 堆中没有数据
+ a[1] = a[count];
+ --count;
+ heapify(a, count, 1);
+ }
+
+ /**
+ * 堆化大顶堆
+ * 自上往下堆化
+ *
+ * @param arr 数组
+ * @param n 堆中元素个数
+ * @param i 待堆化的元素
+ */
+ private static void heapify(int[] arr, int n, int i) {
+ while (true) {
+ // 待堆化元素、左、右子树最大值的下标
+ int maxPos = i;
+ // 待堆化元素小于左子树
+ if (i * 2 <= n && arr[i] < arr[i * 2]) {
+ maxPos = i * 2;
+ }
+ // 待堆化元素左子树小于右子树,
+ if (i * 2 + 1 <= n && arr[maxPos] < arr[i * 2 + 1]) {
+ maxPos = i * 2 + 1;
+ }
+ // 最大元素是自己无需向下堆化
+ if (maxPos == i) break;
+ // 最大元素不是自己,交互值
+ swap(arr, i, maxPos);
+ // 将被交互的元素继续向下堆化
+ i = maxPos;
+ }
+ }
+
+ private static void buildHeap(int[] a, int n) {
+ // 对非叶子节点进行,自上往下堆化
+ for (int i = n / 2; i >= 1; --i) {
+ heapify(a, n, i);
+ }
+ }
+
+ // n 表示数据的个数,数组 a 中的数据从下标 1 到 n 的位置。
+ public static void sort(int[] a, int n) {
+ buildHeap(a, n);
+ int k = n;
+ while (k > 1) {
+ swap(a, 1, k);
+ --k;
+ heapify(a, k, 1);
+ }
+ }
+
+ private static void swap(int[] arr, int i, int j) {
+ int temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+
+ public static void main(String[] args) {
+ int[] arr = new int[]{-99999, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+ System.out.println(Arrays.toString(arr));
+ Heap1.sort(arr, arr.length - 1);
+ System.out.println(Arrays.toString(arr));
+ }
+
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap2.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap2.java
new file mode 100644
index 00000000..12fd37cb
--- /dev/null
+++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/Heap2.java
@@ -0,0 +1,69 @@
+package cn.cunchang.sort;
+
+import java.util.Arrays;
+
+public class Heap2 {
+
+
+ /**
+ * 堆化大顶堆
+ * 自上往下堆化
+ *
+ * @param arr 数组
+ * @param n 堆中元素个数
+ * @param i 待堆化的元素
+ */
+ private static void heapify(int[] arr, int n, int i) {
+ while (true) {
+ // 待堆化元素、左、右子树最大值的下标
+ int maxPos = i;
+ // 待堆化元素小于左子树
+ if (i * 2 + 1 <= n && arr[i] < arr[i * 2 + 1]) {
+ maxPos = i * 2 + 1;
+ }
+ // 待堆化元素左子树小于右子树,
+ if (i * 2 + 2 <= n && arr[maxPos] < arr[i * 2 + 2]) {
+ maxPos = i * 2 + 2;
+ }
+ // 最大元素是自己无需向下堆化
+ if (maxPos == i) break;
+ // 最大元素不是自己,交互值
+ swap(arr, i, maxPos);
+ // 将被交互的元素继续向下堆化
+ i = maxPos;
+ }
+ }
+
+ private static void buildHeap(int[] a, int n) {
+ // 对非叶子节点进行,自上往下堆化
+ for (int i = n / 2 - 1; i >= 0; --i) {
+ heapify(a, n, i);
+ }
+ }
+
+ public static void sort(int[] arr, int n) {
+ // 1. 构建大顶堆
+ buildHeap(arr, n);
+ int disorder = n;
+ // 2. 交换堆顶元素与末尾元素,调整堆结构
+ while (disorder > 0) {
+ swap(arr, 0, disorder);
+ disorder--;
+ heapify(arr, disorder, 0);
+ }
+ }
+
+ private static void swap(int[] arr, int i, int j) {
+ int temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+
+ public static void main(String[] args) {
+ int[] arr = new int[]{9, 10, 7, 6, 5, 4, 3, 2, 1};
+ System.out.println(Arrays.toString(arr));
+ Heap2.sort(arr, arr.length - 1);
+ System.out.println(Arrays.toString(arr));
+ }
+
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort1.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort1.java
new file mode 100644
index 00000000..3cc792b0
--- /dev/null
+++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort1.java
@@ -0,0 +1,65 @@
+package cn.cunchang.sort;
+
+import java.util.Arrays;
+
+/**
+ * @author lastwhisper
+ */
+public class QuickSort1 {
+ public static void main(String[] args) {
+// int[] arr = {2, 10, 8, 1000};
+// int[] arr = {-9, 78, 0, 23, -567, 70};
+// int[] arr = {-9, 78, 0, 23, 60, 70};
+// int[] arr = {9, 0, -567};
+ int[] arr = {49, 38, 65, 97, 76, 13, 27};
+ sort(arr, 0, arr.length - 1);
+ System.out.println(Arrays.toString(arr));
+ }
+
+ private static void sort(int[] arr, int left, int right) {
+ if (left >= right) return;
+ int pivotIdx = partition(arr, left, right);
+ // 此时分区pivotIdx左边值小于等于arr[pivotIdx],分区右边大于arr[pivotIdx]
+ // 对[left,pivotIdx - 1]再次分区
+ sort(arr, left, pivotIdx - 1);
+ // 对[pivotIdx + 1,right]再次分区
+ sort(arr, pivotIdx + 1, right);
+ }
+
+ /**
+ * @param nums 待分区数组
+ * @param left 待分区左边界
+ * @param right 待分区右边界
+ * @return pivotIdx 中轴索引
+ */
+ private static int partition(int[] nums, int left, int right) {
+ // 选最后一个值作为中轴
+ int pivot = nums[left];
+ // 所依right要减一
+ int start = left + 1, end = right;
+ while (start <= end) {
+ // 寻找左边大于pivot
+ while (start <= end && nums[start] <= pivot) {
+ start++;
+ }
+ // 寻找右边小于等于pivot
+ while (start <= end && nums[end] > pivot) {
+ end--;
+ }
+ if (start < end) {
+ swap(nums, start, end);
+ }
+ }
+ // 此时[left+1,start-1]的值一定小于pivot=nums[left]
+ // left一定大于等于start,所以将start-1与left交互
+ swap(nums, start - 1, left);
+ return start - 1;
+ }
+
+ private static void swap(int[] arr, int i, int j) {
+ int temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+
+}
diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort2.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort2.java
new file mode 100644
index 00000000..6dc4c247
--- /dev/null
+++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort2.java
@@ -0,0 +1,62 @@
+package cn.cunchang.sort;
+
+import java.util.Arrays;
+
+/**
+ * @author lastwhisper
+ */
+public class QuickSort2 {
+ public static void main(String[] args) {
+// int[] arr = {2, 10, 8, 1000};
+ int[] arr = {49, 38, 65, 97, 76, 13, 27};
+ sort(arr, 0, arr.length - 1);
+ System.out.println(Arrays.toString(arr));
+ }
+
+ private static void sort(int[] arr, int left, int right) {
+ if (left >= right) return;
+ int pivotIdx = partition(arr, left, right);
+ // 此时分区pivotIdx左边值小于等于arr[pivotIdx],分区右边大于arr[pivotIdx]
+ // 对[left,pivotIdx - 1]再次分区
+ sort(arr, left, pivotIdx - 1);
+ // 对[pivotIdx + 1,right]再次分区
+ sort(arr, pivotIdx + 1, right);
+ }
+
+ /**
+ * @param nums 待分区数组
+ * @param left 待分区左边界
+ * @param right 待分区右边界
+ * @return pivotIdx 中轴索引
+ */
+ private static int partition(int[] nums, int left, int right) {
+ // 选最后一个值作为中轴
+ int pivot = nums[right];
+ // 所依right要减一
+ int start = left, end = right - 1;
+ while (start <= end) {
+ // 寻找左边大于pivot
+ while (start <= end && nums[start] <= pivot) {
+ start++;
+ }
+ // 寻找右边小于等于pivot
+ while (start <= end && nums[end] > pivot) {
+ end--;
+ }
+ if (start < end) {
+ swap(nums, start, end);
+ }
+ }
+ // 此时[left,start-1]的值一定小于pivot=nums[right]
+ // start一定大于right,所以将start与right交互
+ swap(nums, start, right);
+ return start;
+ }
+
+ private static void swap(int[] arr, int i, int j) {
+ int temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+
+}
diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort3.java b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort3.java
new file mode 100644
index 00000000..5e850ecb
--- /dev/null
+++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/QuickSort3.java
@@ -0,0 +1,73 @@
+package cn.cunchang.sort;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * @author lastwhisper
+ */
+public class QuickSort3 {
+ private final static Random random = new Random(System.currentTimeMillis());
+
+ public static void main(String[] args) {
+// int[] arr = {2, 10, 8, 1000};
+// int[] arr = {-9, 78, 0, 23, -567, 70};
+// int[] arr = {-9, 78, 0, 23, 60, 70};
+// int[] arr = {9, 0, -567};
+ int[] arr = {49, 38, 65, 97, 76, 13, 27};
+ sort(arr, 0, arr.length - 1);
+ System.out.println(Arrays.toString(arr));
+ }
+
+ private static void sort(int[] arr, int left, int right) {
+ if (left >= right) return;
+ int pivotIdx = partition(arr, left, right);
+ // 此时分区pivotIdx左边值小于等于arr[pivotIdx],分区右边大于arr[pivotIdx]
+ // 对[left,pivotIdx - 1]再次分区
+ sort(arr, left, pivotIdx - 1);
+ // 对[pivotIdx + 1,right]再次分区
+ sort(arr, pivotIdx + 1, right);
+ }
+
+ /**
+ * @param nums 待分区数组
+ * @param left 待分区左边界
+ * @param right 待分区右边界
+ * @return pivotIdx 中轴索引
+ */
+ private static int partition(int[] nums, int left, int right) {
+ int randomIndex = left + random.nextInt(right - left + 1);
+ swap(nums, left, randomIndex);
+
+ // all in nums[left + 1..le) <= pivot;
+ // all in nums(ge..right] >= pivot;
+ int pivot = nums[left];
+ int start = left + 1;
+ int end = right;
+
+ while (true) {
+ while (start <= end && nums[start] < pivot) {
+ start++;
+ }
+ while (start <= end && nums[end] > pivot) {
+ end--;
+ }
+ if (start >= end) {
+ break;
+ }
+ swap(nums, start, end);
+ start++;
+ end--;
+ }
+
+ swap(nums, left, end);
+ return end;
+ }
+
+ private static void swap(int[] arr, int i, int j) {
+ int temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+
+}
diff --git a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/README.md b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/README.md
new file mode 100644
index 00000000..741b6e50
--- /dev/null
+++ b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/sort/README.md
@@ -0,0 +1,7 @@
+快排
+QuickSort1 第一个元素做分区
+QuickSort2 最后一个元素做分区
+QuickSort3 随机一个元素做分区
+堆排序
+Heap1 数组第一个元素空出
+Heap2 数组第一个元素不空出
\ No newline at end of file
diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240_347_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240_347_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..4864a528
--- /dev/null
+++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240_347_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,46 @@
+package cn.cunchang.前K个高频元素_347_中等;
+
+import cn.cunchang.array.ArrayUtil;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+class Solution {
+
+ public int[] topKFrequent(int[] nums, int k) {
+ // 记录数字出现的频率
+ Map freqMap = new HashMap<>();
+ for (int num : nums) {
+ Integer freq = freqMap.get(num);
+ if (freq == null) {
+ freqMap.put(num, 1);
+ } else {
+ freqMap.put(num, ++freq);
+ }
+ }
+ // 记录最大频率
+ int maxTime = 0;
+ for (Integer freq : freqMap.values()) {
+ if (freq > maxTime) {
+ maxTime = freq;
+ }
+ }
+
+ int[] res = new int[k];
+ while (k > 0) {
+ for (Map.Entry entry : freqMap.entrySet()) {
+ if (entry.getValue() == maxTime) {
+ res[--k] = entry.getKey();
+ }
+ }
+ maxTime--;
+ }
+ return res;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Arrays.toString(new Solution().
+ topKFrequent(ArrayUtil.createArrays(1, 1, 1, 2, 2, 3), 2)));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..691dc6f5
--- /dev/null
+++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,65 @@
+package cn.cunchang.数组中的第K个最大元素_215_中等;
+
+import cn.cunchang.array.ArrayUtil;
+
+class Solution {
+ public int findKthLargest(int[] nums, int k) {
+ // topk的分区的位置
+ int targetIdx = nums.length - k;
+ int left = 0, right = nums.length - 1;
+
+ while (left <= right) {
+ // 中轴索引值
+ int pivotIdx = partition(nums, left, right);
+ if (targetIdx > pivotIdx) {
+ // 说明要往右边分
+ left = pivotIdx + 1;
+ } else if (targetIdx < pivotIdx) {
+ // 说明要往左边分
+ right = pivotIdx - 1;
+ } else {
+ // 说明分区分到这个topk了
+ return nums[pivotIdx];
+ }
+
+ }
+ return -1;
+ }
+
+ private int partition(int[] nums, int left, int right) {
+ // 选最后一个值作为中轴
+ int pivot = nums[right];
+ // 所依right要减一
+ int start = left, end = right - 1;
+ while (start <= end) {
+ // 寻找左边大于pivot
+ while (start <= end && nums[start] <= pivot) {
+ start++;
+ }
+ // 寻找右边小于等于pivot
+ while (start <= end && nums[end] > pivot) {
+ end--;
+ }
+ if (start <= end) {
+ swap(nums, start, end);
+ }
+ }
+ // 此时[left,start-1]的值一定小于pivot=nums[right]
+ // start一定大于right,所以将start与right交互
+ swap(nums, start, right);
+
+ return start;
+ }
+
+ private void swap(int[] nums, int start, int end) {
+ int tmp = nums[start];
+ nums[start] = nums[end];
+ nums[end] = tmp;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().findKthLargest(ArrayUtil.createArrays(2,1), 1));
+// System.out.println(new Solution().findKthLargest(ArrayUtil.createArrays(3, 2, 1, 5, 6, 4), 2));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java"
new file mode 100644
index 00000000..a0c482e8
--- /dev/null
+++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254K\344\270\252\346\234\200\345\244\247\345\205\203\347\264\240_215_\344\270\255\347\255\211/Solution2.java"
@@ -0,0 +1,32 @@
+package cn.cunchang.数组中的第K个最大元素_215_中等;
+
+import cn.cunchang.array.ArrayUtil;
+
+import java.util.Comparator;
+import java.util.PriorityQueue;
+
+class Solution2 {
+ public int findKthLargest(int[] nums, int k) {
+ PriorityQueue heap = new PriorityQueue<>();
+ for (int num : nums) {
+ heap.add(num);
+ if (heap.size() > k) {
+ heap.poll();
+ }
+ }
+ return heap.peek();
+ }
+
+
+ private void swap(int[] nums, int start, int end) {
+ int tmp = nums[start];
+ nums[start] = nums[end];
+ nums[end] = tmp;
+ }
+
+ public static void main(String[] args) {
+// System.out.println(new Solution2().findKthLargest(ArrayUtil.createArrays(2, 1), 1));
+ System.out.println(new Solution2().findKthLargest(ArrayUtil.createArrays(3, 2, 1, 5, 6, 4), 2));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\255\227\347\254\246\345\207\272\347\216\260\351\242\221\347\216\207\346\216\222\345\272\217_451_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\255\227\347\254\246\345\207\272\347\216\260\351\242\221\347\216\207\346\216\222\345\272\217_451_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..d63dbf1a
--- /dev/null
+++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\255\227\347\254\246\345\207\272\347\216\260\351\242\221\347\216\207\346\216\222\345\272\217_451_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,51 @@
+package cn.cunchang.根据字符出现频率排序_451_中等;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class Solution {
+ public String frequencySort(String s) {
+ // 记录字母出现的频率
+ Map freqMap = new HashMap<>();
+ for (int i = 0; i < s.length(); i++) {
+ Integer freq = freqMap.get(s.charAt(i));
+ if (freq == null) {
+ freqMap.put(s.charAt(i), 1);
+ } else {
+ freqMap.put(s.charAt(i), ++freq);
+ }
+ }
+ // 记录最大频率
+ int maxTime = 0;
+ for (Integer freq : freqMap.values()) {
+ if (freq > maxTime) {
+ maxTime = freq;
+ }
+ }
+ // 倒序记录出现频率最大的字母
+ int size = freqMap.size();
+ char[] charFreqOrder = new char[freqMap.size()];
+ while (size > 0) {
+ for (Map.Entry entry : freqMap.entrySet()) {
+ if (entry.getValue() == maxTime) {
+ charFreqOrder[--size] = entry.getKey();
+ }
+ }
+ maxTime--;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = charFreqOrder.length - 1; i >= 0; i--) {
+ Integer freq = freqMap.get(charFreqOrder[i]);
+ for (int j = 0; j < freq; j++) {
+ sb.append(charFreqOrder[i]);
+ }
+ }
+ return sb.toString();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().frequencySort("tree"));
+ System.out.println(new Solution().frequencySort("cccaaa"));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..901ce539
--- /dev/null
+++ "b/algorithms/leetcode2/sort/src/main/java/cn/cunchang/\351\242\234\350\211\262\345\210\206\347\261\273_75_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,28 @@
+package cn.cunchang.颜色分类_75_中等;
+
+import cn.cunchang.array.ArrayUtil;
+
+import java.util.Arrays;
+
+class Solution {
+ public void sortColors(int[] nums) {
+ // 下标表示对应数字,值表示频率
+ int[] freq = new int[3];
+ for (int num : nums) {
+ freq[num]++;
+ }
+ int idx = 0;
+ for (int i = 0; i < freq.length; i++) {
+ while (freq[i]-- > 0) {
+ // freq[i]表i这个数字出现了freq[i]次;freq[0]=2,说明0出现了两次
+ nums[idx++] = i;
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ int[] arrays = ArrayUtil.createArrays(2, 0, 2, 1, 1, 0);
+ new Solution().sortColors(arrays);
+ System.out.println(Arrays.toString(arrays));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/README.md" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/README.md"
new file mode 100644
index 00000000..8a8ac1ea
--- /dev/null
+++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/README.md"
@@ -0,0 +1,5 @@
+
+Solution1;按照自己的思路写了一遍
+Solution2;精简代码;因为Solution1超时了,,,,
+Solution3;备忘录优化
+
diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution1.java" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution1.java"
new file mode 100644
index 00000000..90f9b691
--- /dev/null
+++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution1.java"
@@ -0,0 +1,78 @@
+package cn.cunchang.接雨水_42_困难;
+
+import org.junit.Assert;
+
+class Solution1 {
+ /**
+ * 题目地址:https://leetcode.cn/problems/container-with-most-water/
+ * -------------------------------------------------------------------
+ * 思考:只看局部柱子最多盛放水量
+ * -------------------------------------------------------------------
+ * 思路(磨刀不误砍柴工,先写思路,再写代码):
+ * 数组n个柱子,当前柱子i,每个柱子可
+ * 1、遍历每个柱子,找每个柱子左右最高层数
+ * 2、找i左右最高层数
+ * (1)i=0 or i=n,左最高和右最高=0;第一个柱子和最后一个柱子不管多高,自身都无法盛水
+ * (2)遍历[0,i),记录左最高层数
+ * (3)遍历(i,n-1],记录右最高层数
+ * 3、i可盛放水量计算
+ * (1)如果左最高或右最高=0,说明当前柱子无法盛水,当前柱子盛水量=0
+ * (2)i自身高度大于或等于左右高度,当前柱子盛水量=0
+ * (3)i最多盛放水量=左右最高里面最低的哪个层数-当前柱子层数
+ * 4、[0,n-1]对应盛水量汇总
+ * -------------------------------------------------------------------
+ * 时间复杂度:O(n^2)
+ * 空间复杂度:O(1)
+ */
+ public int trap(int[] height) {
+ if (height == null || height.length == 0) {
+ return 0;
+ }
+ int count = 0;
+ for (int i = 0; i < height.length; i++) {
+ KV kv = getMax(i, height);
+ if (kv.leftMax == 0 || kv.rightMax == 0) {
+ continue;
+ }
+ if (height[i] >= kv.leftMax || height[i] >= kv.rightMax) {
+ continue;
+ }
+ int low = kv.leftMax > kv.rightMax ? kv.rightMax : kv.leftMax;
+ // i最多盛放水量
+ count += low - height[i];
+ }
+ return count;
+ }
+
+ private KV getMax(int i, int[] height) {
+ int leftMax = 0;
+ for (int j = 0; j < i; j++) {
+ if (leftMax < height[j]) {
+ leftMax = height[j];
+ }
+ }
+ int rightMax = 0;
+ for (int j = height.length - 1; j > i; j--) {
+ if (rightMax < height[j]) {
+ rightMax = height[j];
+ }
+ }
+ return new KV(leftMax, rightMax);
+ }
+
+ class KV {
+ int leftMax;
+ int rightMax;
+
+ public KV(int leftMax, int rightMax) {
+ this.leftMax = leftMax;
+ this.rightMax = rightMax;
+ }
+ }
+
+ public static void main(String[] args) {
+// Assert.assertEquals(2, new Solution1().maxDistance(new int[][]{{1, 0, 1}, {0, 0, 0}, {1, 0, 1}}));
+ Solution1 solution1 = new Solution1();
+ Assert.assertEquals(6, solution1.trap(new int[]{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution2.java" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution2.java"
new file mode 100644
index 00000000..d2f834c4
--- /dev/null
+++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution2.java"
@@ -0,0 +1,39 @@
+package cn.cunchang.接雨水_42_困难;
+
+import org.junit.Assert;
+
+class Solution2 {
+ /**
+ * 题目地址:https://leetcode.cn/problems/container-with-most-water/
+ * -------------------------------------------------------------------
+ * 思考:只看局部柱子最多盛放水量
+ * -------------------------------------------------------------------
+ * 思路:基于solution1,精简代码
+ * -------------------------------------------------------------------
+ * 时间复杂度:O(n^2)
+ * 空间复杂度:O(1)
+ */
+ public int trap(int[] height) {
+ int count = 0;
+ for (int i = 1; i < height.length - 1; i++) {
+ int leftMax = 0, rightMax = 0;
+ // 左边最高,j <= i包含自己,后面不用判断小于的情况
+ for (int j = 0; j <= i; j++) {
+ leftMax = Math.max(leftMax, height[j]);
+ }
+ // 右边最高,j >= i 包含自己
+ for (int j = height.length - 1; j >= i; j--) {
+ rightMax = Math.max(rightMax, height[j]);
+ }
+ count += Math.min(leftMax, rightMax) - height[i];
+ }
+ return count;
+ }
+
+ public static void main(String[] args) {
+// Assert.assertEquals(2, new Solution1().maxDistance(new int[][]{{1, 0, 1}, {0, 0, 0}, {1, 0, 1}}));
+ Solution2 solution2 = new Solution2();
+ Assert.assertEquals(6, solution2.trap(new int[]{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}));
+
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution3.java" "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution3.java"
new file mode 100644
index 00000000..28b4370c
--- /dev/null
+++ "b/algorithms/leetcode2/src/main/java/cn/cunchang/\346\216\245\351\233\250\346\260\264_42_\345\233\260\351\232\276/Solution3.java"
@@ -0,0 +1,31 @@
+package cn.cunchang.接雨水_42_困难;
+
+import org.junit.Assert;
+
+class Solution3 {
+ /**
+ * 题目地址:https://leetcode.cn/problems/container-with-most-water/
+ * -------------------------------------------------------------------
+ * 思考:只看局部柱子最多盛放水量
+ * -------------------------------------------------------------------
+ * 思路:备忘录
+ *
+ * 之前的暴力解法,不是在每个位置 i 都要计算 r_max 和 l_max 吗?我们直接把结果都提前计算出来,别傻不拉几的每次都遍历,这时间复杂度不就降下来了嘛。
+ *
+ * 我们开两个数组 r_max 和 l_max 充当备忘录,l_max[i] 表示位置 i 左边最高的柱子高度,r_max[i] 表示位置 i 右边最高的柱子高度。预先把这两个数组计算好,避免重复计算:
+ *
+ * -------------------------------------------------------------------
+ * 时间复杂度:O(n)
+ * 空间复杂度:O(n)
+ */
+ public int trap(int[] height) {
+
+
+ return 0;
+ }
+
+ public static void main(String[] args) {
+ Solution3 solution = new Solution3();
+ Assert.assertEquals(6, solution.trap(new int[]{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}));
+ }
+}
\ No newline at end of file
diff --git a/algorithms/leetcode2/tree/pom.xml b/algorithms/leetcode2/tree/pom.xml
new file mode 100644
index 00000000..601f6b08
--- /dev/null
+++ b/algorithms/leetcode2/tree/pom.xml
@@ -0,0 +1,23 @@
+
+
+ 4.0.0
+
+ cn.cunchang
+ tree
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+
+
+
+
+ leetcode2-common
+ cn.cucnhang
+ 1.0-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\345\261\225\345\274\200\344\270\272\351\223\276\350\241\250_114_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\345\261\225\345\274\200\344\270\272\351\223\276\350\241\250_114_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..8ad66b91
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\345\261\225\345\274\200\344\270\272\351\223\276\350\241\250_114_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,40 @@
+package cn.cunchang.二叉树展开为链表_114_中等;
+
+import cn.cunchang.tree.TreeNode;
+import cn.cunchang.tree.TreeUtil;
+
+/**
+ * @author cunchang
+ * @date 2022/6/20 6:41 PM
+ */
+public class Solution {
+
+ public void flatten(TreeNode root) {
+ if (root == null) {
+ return;
+ }
+
+ flatten(root.left);
+ flatten(root.right);
+ // 原先左子树
+ TreeNode left = root.left;
+ // 原先右子树
+ TreeNode right = root.right;
+ // 将左子树作为当前节点的右子树
+ root.left = null;
+ root.right = left;
+ // 将当前右子树(原先的左子树)的末端指向原先的右子树
+ TreeNode p = root;//这里为什么是root?left行不行;left也可以,但是left可能为空需要判空
+ while (p.right!=null){
+ p = p.right;
+ }
+ //
+ p.right = right;
+ }
+
+ public static void main(String[] args) {
+ TreeNode node = TreeUtil.createTree(1, 2, 5, 3, 4, null, 6);
+ new Solution().flatten(node);
+ TreeUtil.printLevelOrder(node);
+ }
+}
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..e29285d9
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206_144_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,41 @@
+package cn.cunchang.二叉树的前序遍历_144_简单;
+
+import cn.cunchang.tree.TreeNode;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+class Solution {
+
+ public List preorderTraversal(TreeNode root) {
+ List preOrder = new ArrayList<>();
+ Stack stack = new Stack<>();
+ stack.push(root);
+ while (!stack.isEmpty()) {
+ TreeNode treeNode = stack.pop();
+ if (treeNode != null) {
+ preOrder.add(treeNode.val);
+ // 先进后出,保证left先执行
+ stack.push(treeNode.right);
+ stack.push(treeNode.left);
+ }
+ }
+ return preOrder;
+ }
+
+// public List preorderTraversal(TreeNode root) {
+// List preOrder = new ArrayList<>();
+// preorderTraversal(root, preOrder);
+// return preOrder;
+// }
+//
+// public void preorderTraversal(TreeNode root, List preOrder) {
+// if (root == null) {
+// return;
+// }
+// preOrder.add(root.val);
+// preorderTraversal(root.left, preOrder);
+// preorderTraversal(root.right, preOrder);
+// }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\271\263\345\235\207\345\200\274_637_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\271\263\345\235\207\345\200\274_637_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..558eacd0
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\345\271\263\345\235\207\345\200\274_637_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,38 @@
+package cn.cunchang.二叉树的层平均值_637_简单;
+
+import cn.cunchang.tree.TreeNode;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+class Solution {
+ public List averageOfLevels(TreeNode root) {
+ if (root == null) {
+ return new ArrayList<>();
+ }
+ List resultList = new ArrayList<>();
+
+ Queue queue = new LinkedList<>();
+ queue.offer(root);
+
+ while (!queue.isEmpty()) {
+ double result = 0.0;
+ int levelCount = queue.size();
+ for (int i = 0; i < levelCount; i++) {
+ TreeNode treeNode = queue.poll();
+ result += treeNode.val;
+ if (treeNode.left != null) {
+ queue.offer(treeNode.left);
+ }
+ if (treeNode.right != null) {
+ queue.offer(treeNode.right);
+ }
+ }
+ resultList.add(result/levelCount);
+ }
+ return resultList;
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..b6292a02
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,17 @@
+package cn.cunchang.二叉树的最大深度_104_简单;
+
+
+import cn.cunchang.tree.TreeNode;
+
+class Solution {
+ public int maxDepth(TreeNode root) {
+ if (root == null) {
+ return 0;
+ }
+
+ int leftDep = maxDepth(root.left);
+ int rightDep = maxDepth(root.right);
+
+ return Math.max(leftDep, rightDep) + 1;
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java"
new file mode 100644
index 00000000..f23e92a9
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246_104_\347\256\200\345\215\225/Solution2.java"
@@ -0,0 +1,31 @@
+package cn.cunchang.二叉树的最大深度_104_简单;
+
+
+import cn.cunchang.tree.TreeNode;
+
+class Solution2 {
+ int res = 0;
+ int depth = 0;
+
+ public int maxDepth(TreeNode root) {
+ maxDepth2(root);
+ return res;
+ }
+
+ public void maxDepth2(TreeNode root) {
+ if (root == null) {
+ return;
+ }
+
+ // 进入节点深度增加
+ depth++;
+ // 当前是最后一个节点了,记录一下最大位置
+ if (root.left == null && root.right == null) {
+ res = Math.max(res, depth);
+ }
+ maxDepth(root.left);
+ maxDepth(root.right);
+ // 离开当前节点,深度减少
+ depth--;
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..22fd643c
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\272\214\345\217\211\346\240\221\347\232\204\347\233\264\345\276\204_543_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,22 @@
+package cn.cunchang.二叉树的直径_543_简单;
+
+import cn.cunchang.tree.TreeNode;
+
+class Solution {
+ int res = 1;
+
+ public int diameterOfBinaryTree(TreeNode root) {
+ diameterOfBinaryTree0(root);
+ return res - 1;
+ }
+
+ public int diameterOfBinaryTree0(TreeNode root) {
+ if (root == null) {
+ return 0;
+ }
+ int leftDep = diameterOfBinaryTree0(root.left);
+ int rightDep = diameterOfBinaryTree0(root.right);
+ res = Math.max(leftDep + rightDep + 1, res);
+ return Math.max(leftDep, rightDep) + 1;
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..f82d684a
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,49 @@
+package cn.cunchang.从中序与后序遍历序列构造二叉树_106_中等;
+
+import cn.cunchang.array.ArrayUtil;
+import cn.cunchang.tree.TreeNode;
+import cn.cunchang.tree.TreeUtil;
+
+/**
+ * @author cunchang
+ * @date 2022/6/21 8:42 PM
+ */
+class Solution {
+ public TreeNode buildTree(int[] inorder, int[] postorder) {
+ return buildTree0(inorder, 0, inorder.length - 1,
+ postorder, 0, postorder.length - 1);
+ }
+
+ public TreeNode buildTree0(int[] inorder, int inLeft, int inRight,
+ int[] postorder, int postLeft, int postRight) {
+ if (postLeft > postRight) {
+ return null;
+ }
+ // 找到根节点postRight,并构造根节点
+ TreeNode treeNode = new TreeNode(postorder[postRight]);
+ // 找到根节点在inorder的下标index
+ int postOrderIndex = 0;
+ for (int i = inLeft; i <= inRight; i++) {
+ if (postorder[postRight] == inorder[i]) {
+ postOrderIndex = i;
+ break;
+ }
+ }
+ // 计算根节点右子树的节点数
+ int leftCount = inRight - postOrderIndex;
+ // 递归构造根节点的右子树
+ // 右子树在inorder[postOrderIndex+1,inRight],postorder[postRight-leftCount,postRight-1]
+ treeNode.right = buildTree0(inorder, postOrderIndex + 1, inRight,
+ postorder, postRight - leftCount , postRight-1);
+ // 递归构造根节点的左子树
+ // 左子树在inorder[inLeft,postOrderIndex-1],postorder[postLeft,leftCount-1]
+ treeNode.left = buildTree0(inorder, inLeft, postOrderIndex - 1,
+ postorder, postLeft, postRight - leftCount - 1);
+ return treeNode;
+ }
+
+ public static void main(String[] args) {
+ TreeUtil.printLevelOrder(new Solution().buildTree(
+ ArrayUtil.createArrays(9, 3, 15, 20, 7), ArrayUtil.createArrays(9, 15, 7, 20, 3)));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution2.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution2.java"
new file mode 100644
index 00000000..29350ce2
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\344\270\255\345\272\217\344\270\216\345\220\216\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_106_\344\270\255\347\255\211/Solution2.java"
@@ -0,0 +1,56 @@
+package cn.cunchang.从中序与后序遍历序列构造二叉树_106_中等;
+
+import cn.cunchang.array.ArrayUtil;
+import cn.cunchang.tree.TreeNode;
+import cn.cunchang.tree.TreeUtil;
+
+import java.util.HashMap;
+
+/**
+ * @author cunchang
+ * @date 2022/6/21 8:42 PM
+ */
+class Solution2 {
+
+ public TreeNode buildTree(int[] inorder, int[] postorder) {
+ HashMap inorderIndexMap = new HashMap<>();
+ for (int i = 0; i < inorder.length; i++) {
+ inorderIndexMap.put(inorder[i], i);
+ }
+ return buildTree0(inorder, 0, inorder.length - 1,
+ postorder, 0, postorder.length - 1, inorderIndexMap);
+ }
+
+ public TreeNode buildTree0(int[] inorder, int inLeft, int inRight,
+ int[] postorder, int postLeft, int postRight, HashMap inorderIndexMap) {
+ if (postLeft > postRight) {
+ return null;
+ }
+ // 找到根节点postRight,并构造根节点
+ TreeNode treeNode = new TreeNode(postorder[postRight]);
+ // 找到根节点在inorder的下标index
+ int postOrderIndex = inorderIndexMap.get(postorder[postRight]);
+// for (int i = inLeft; i <= inRight; i++) {
+// if (postorder[postRight] == inorder[i]) {
+// postOrderIndex = i;
+// break;
+// }
+// }
+ // 计算根节点右子树的节点数
+ int leftCount = inRight - postOrderIndex;
+ // 递归构造根节点的右子树
+ // 的右子树在在inorder[postOrderIndex+1,inRight],postorder[postRight-leftCount,postRight-1]
+ treeNode.right = buildTree0(inorder, postOrderIndex + 1, inRight,
+ postorder, postRight - leftCount, postRight - 1, inorderIndexMap);
+ // 递归构造根节点的左子树
+ // 左子树在在inorder[inLeft,postOrderIndex-1],postorder[postLeft,leftCount-1]
+ treeNode.left = buildTree0(inorder, inLeft, postOrderIndex - 1,
+ postorder, postLeft, postRight - leftCount - 1, inorderIndexMap);
+ return treeNode;
+ }
+
+ public static void main(String[] args) {
+ TreeUtil.printLevelOrder(new Solution2().buildTree(
+ ArrayUtil.createArrays(9, 3, 15, 20, 7), ArrayUtil.createArrays(9, 15, 7, 20, 3)));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_105_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_105_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..03f0a712
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\344\273\216\345\211\215\345\272\217\344\270\216\344\270\255\345\272\217\351\201\215\345\216\206\345\272\217\345\210\227\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_105_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,51 @@
+package cn.cunchang.从前序与中序遍历序列构造二叉树_105_中等;
+
+import cn.cunchang.array.ArrayUtil;
+import cn.cunchang.tree.TreeNode;
+import cn.cunchang.tree.TreeUtil;
+
+/**
+ * @author cunchang
+ * @date 2022/6/20 6:41 PM
+ */
+class Solution {
+
+ public TreeNode buildTree(int[] preorder, int[] inorder) {
+ return buildTree0(preorder, 0, preorder.length - 1,
+ inorder, 0, inorder.length - 1);
+ }
+
+ public TreeNode buildTree0(int[] preorder, int preLeft, int preRight,
+ int[] inorder, int inLeft, int inRight) {
+ // 递归终止
+ if (preLeft > preRight) {
+ return null;
+ }
+
+ // 1、preLeft是preorder的根节点,对根节点进行构造
+ TreeNode root = new TreeNode(preorder[preLeft]);
+ // 2、根节点在inorder的下标为index
+ int inOrderIndex = 0;
+ for (int i = inLeft; i <= inRight; i++) {
+ if (inorder[i] == preorder[preLeft]) {
+ inOrderIndex = i;
+ break;
+ }
+ }
+ // 3、根节点的左子树节点个数leftCount = index-inLeft,根节点左子树在preorder的范围[preLeft+1,preLeft+leftCount],
+ // 根节点已经构造过了,所以从preLeft+1开始,至左子树个数preLeft+leftCount结束;
+ // 在inorder的范围[inLeft,index-1]
+ int leftCount = inOrderIndex - inLeft;
+ root.left = buildTree0(preorder, preLeft + 1, preLeft + leftCount,
+ inorder, inLeft, inOrderIndex - 1);
+ // 4、根节点右子树在preorder的范围[preLeft+leftCount+1,preRight],在inorder的范围[index+1,inRight]
+ root.right = buildTree0(preorder, preLeft + leftCount + 1, preRight,
+ inorder, inOrderIndex + 1, inRight);
+ return root;
+ }
+
+ public static void main(String[] args) {
+ TreeUtil.printLevelOrder(new Solution().buildTree(
+ ArrayUtil.createArrays(3, 9, 20, 15, 7), ArrayUtil.createArrays(9, 3, 15, 20, 7)));
+ }
+}
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\210\240\347\202\271\346\210\220\346\236\227_1110_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\210\240\347\202\271\346\210\220\346\236\227_1110_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..7e88ddb3
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\210\240\347\202\271\346\210\220\346\236\227_1110_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,66 @@
+package cn.cunchang.删点成林_1110_简单;
+
+import cn.cunchang.array.ArrayUtil;
+import cn.cunchang.tree.TreeNode;
+import cn.cunchang.tree.TreeUtil;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+class Solution {
+ List result = new ArrayList<>();
+
+ public List delNodes(TreeNode root, int[] to_delete) {
+ Set deleteSet = new HashSet<>();
+ for (int deleteNum : to_delete) {
+ deleteSet.add(deleteNum);
+ }
+ // 根节点不需要删除,就加入到返回值,需要删除就不管了
+ if (!deleteSet.contains(root.val)) {
+ result.add(root);
+ }
+ delNodes0(root, deleteSet);
+ return result;
+ }
+
+ public boolean delNodes0(TreeNode root, Set deleteSet) {
+ if (root == null) {
+ return false;
+ }
+
+ boolean leftDelete = delNodes0(root.left, deleteSet);
+ if (leftDelete) {
+ root.left = null;
+ }
+ boolean rightDelete = delNodes0(root.right, deleteSet);
+ if (rightDelete) {
+ root.right = null;
+ }
+ if (deleteSet.contains(root.val)) {
+ // 当前节点是需要删除的节点
+ // 那么当前节点的左节点,不为空的话,就是一个单独的森林
+ if (root.left != null) {
+ result.add(root.left);
+ }
+ // 当前节点的右节点,不为空的话,就是一个单独的森林
+ if (root.right != null) {
+ result.add(root.right);
+ }
+ root.left = null;
+ root.right = null;
+ // 通知上层节点把自己删了
+ return true;
+ }
+ return false;
+ }
+
+ public static void main(String[] args) {
+ List treeNodeList = new Solution().delNodes(TreeUtil.createTree(1, 2, 3, 4, 5, 6, 7),
+ ArrayUtil.createArrays(3));
+ for (TreeNode treeNode : treeNodeList) {
+ TreeUtil.printLevelOrder(treeNode);
+ }
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\350\212\202\347\202\271\346\214\207\351\222\210_116_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\350\212\202\347\202\271\346\214\207\351\222\210_116_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..1fa42bfa
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\241\253\345\205\205\346\257\217\344\270\252\350\212\202\347\202\271\347\232\204\344\270\213\344\270\200\344\270\252\345\217\263\344\276\247\350\212\202\347\202\271\346\214\207\351\222\210_116_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,48 @@
+package cn.cunchang.填充每个节点的下一个右侧节点指针_116_中等;
+
+/**
+ * @author cunchang
+ * @date 2022/6/20 6:33 PM
+ */
+public class Solution {
+ public Node connect(Node root) {
+ if (root == null) {
+ return null;
+ }
+ connect2(root.left, root.right);
+ return root;
+ }
+
+ public void connect2(Node node1, Node node2) {
+ if (node1 == null || node2 == null) {
+ return;
+ }
+ node1.next = node2;
+
+ connect2(node1.left,node1.right);
+ connect2(node2.left,node2.right);
+ // 跨节点相连
+ connect2(node1.right,node2.left);
+ }
+
+ class Node {
+ public int val;
+ public Node left;
+ public Node right;
+ public Node next;
+
+ public Node() {
+ }
+
+ public Node(int _val) {
+ val = _val;
+ }
+
+ public Node(int _val, Node _left, Node _right, Node _next) {
+ val = _val;
+ left = _left;
+ right = _right;
+ next = _next;
+ }
+ }
+}
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..4372bf7b
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221_101_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,25 @@
+package cn.cunchang.对称二叉树_101_简单;
+
+import cn.cunchang.tree.TreeNode;
+
+class Solution {
+ public boolean isSymmetric(TreeNode root) {
+ if (root == null) {
+ return true;
+ }
+ return isSymmetric0(root.left, root.right);
+ }
+
+ public boolean isSymmetric0(TreeNode p1, TreeNode p2) {
+ if (p1 == null && p2 == null) {
+ return true;
+ }
+ if (p1 == null || p2 == null) {
+ return false;
+ }
+ if (p1.val != p2.val) {
+ return false;
+ }
+ return isSymmetric0(p1.left, p2.right) && isSymmetric0(p1.right, p2.left);
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..09ce8f7e
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221_110_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,21 @@
+package cn.cunchang.平衡二叉树_110_简单;
+
+import cn.cunchang.tree.TreeNode;
+
+class Solution {
+ public boolean isBalanced(TreeNode root) {
+ return isBalanced0(root) != -1;
+ }
+
+ public int isBalanced0(TreeNode root) {
+ if (root == null) {
+ return 0;
+ }
+ int leftDep = isBalanced0(root.left);
+ int rightDep = isBalanced0(root.right);
+ if (leftDep == -1 || rightDep == -1 || Math.abs(leftDep - rightDep) > 1) {
+ return -1;
+ }
+ return Math.max(leftDep, rightDep) + 1;
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221_654_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221_654_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..52cc6d44
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221_654_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,35 @@
+package cn.cunchang.最大二叉树_654_中等;
+
+import cn.cunchang.tree.TreeNode;
+
+/**
+ * @author cunchang
+ * @date 2022/6/20 7:50 PM
+ */
+class Solution {
+ public TreeNode constructMaximumBinaryTree(int[] nums) {
+ return constructMaximumBinaryTree0(nums, 0, nums.length - 1);
+ }
+
+ public TreeNode constructMaximumBinaryTree0(int[] nums, int left, int right) {
+ if (left > right) {
+ return null;
+ }
+ // 找到最大值构造根节点
+ int max = Integer.MIN_VALUE;
+ int index = -1;
+ for (int i = left; i <= right; i++) {
+ if (max < nums[i]) {
+ index = i;
+ max = nums[i];
+ }
+
+ }
+ TreeNode treeNode = new TreeNode(max);
+ // 再以最大值下标为界限,构造左右子树
+ treeNode.left = constructMaximumBinaryTree0(nums, left, index - 1);
+ treeNode.right = constructMaximumBinaryTree0(nums, index + 1, right);
+ return treeNode;
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\211\215\345\272\217\345\222\214\345\220\216\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_889_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\211\215\345\272\217\345\222\214\345\220\216\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_889_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..bdb765a0
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\346\240\271\346\215\256\345\211\215\345\272\217\345\222\214\345\220\216\345\272\217\351\201\215\345\216\206\346\236\204\351\200\240\344\272\214\345\217\211\346\240\221_889_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,25 @@
+package cn.cunchang.根据前序和后序遍历构造二叉树_889_中等;
+
+import cn.cunchang.tree.TreeNode;
+
+/**
+ * @author cunchang
+ * @date 2022/6/21 11:59 PM
+ */
+class Solution {
+ public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
+ return constructFromPrePost0(preorder, 0, preorder.length - 1, postorder, 0, postorder.length - 1);
+ }
+
+ private TreeNode constructFromPrePost0(int[] preorder, int preLeft, int preRight, int[] postorder, int postLeft, int postRight) {
+ if (preLeft > preRight) {
+ return null;
+ }
+ // 构造根节点
+ TreeNode root = new TreeNode(preorder[preLeft]);
+ // 把先序遍历的第二个值当做左子树
+
+
+ return null;
+ }
+}
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution.java"
new file mode 100644
index 00000000..212b213c
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution.java"
@@ -0,0 +1,42 @@
+package cn.cunchang.翻转二叉树_226_简单;
+
+import cn.cunchang.tree.TreeNode;
+
+/**
+ * @author cunchang
+ * @date 2022/6/20 6:28 PM
+ */
+class Solution {
+ public TreeNode invertTree(TreeNode root) {
+ invertTree2(root);
+ return root;
+ }
+
+ /**
+ * 通过遍历解决
+ */
+ public void invertTree2(TreeNode root) {
+ if (root == null) {
+ return;
+ }
+ // 前序交换
+ TreeNode tmp = root.left;
+ root.left = root.right;
+ root.right = tmp;
+
+ invertTree2(root.left);
+ invertTree2(root.right);
+ }
+
+// public void invertTree2(TreeNode root) {
+// if (root == null) {
+// return;
+// }
+// invertTree2(root.left);
+// invertTree2(root.right);
+// // 后序交换
+// TreeNode tmp = root.left;
+// root.left = root.right;
+// root.right = tmp;
+// }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java"
new file mode 100644
index 00000000..45ebe11a
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221_226_\347\256\200\345\215\225/Solution2.java"
@@ -0,0 +1,23 @@
+package cn.cunchang.翻转二叉树_226_简单;
+
+import cn.cunchang.tree.TreeNode;
+
+/**
+ * @author cunchang
+ * @date 2022/6/20 6:28 PM
+ */
+class Solution2 {
+ /**
+ * 通过分解解决
+ */
+ public TreeNode invertTree(TreeNode root) {
+ if (root == null) {
+ return null;
+ }
+ TreeNode left = invertTree(root.left);
+ TreeNode right = invertTree(root.right);
+ root.left = right;
+ root.right = left;
+ return root;
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\344\270\255\347\255\211/Solution.java" "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\344\270\255\347\255\211/Solution.java"
new file mode 100644
index 00000000..38ffe573
--- /dev/null
+++ "b/algorithms/leetcode2/tree/src/main/java/cn/cunchang/\350\267\257\345\276\204\346\200\273\345\222\214_III_437_\344\270\255\347\255\211/Solution.java"
@@ -0,0 +1,38 @@
+package cn.cunchang.路径总和_III_437_中等;
+
+import cn.cunchang.tree.TreeNode;
+import cn.cunchang.tree.TreeUtil;
+
+class Solution {
+
+ public int pathSum(TreeNode root, int sum) {
+ if (root == null) {
+ return 0;
+ }
+ int res = findPathSum(root, sum);
+ res += pathSum(root.left, sum);
+ res += pathSum(root.right, sum);
+ return res;
+ }
+
+ // 从node找到路径和等于sum的数量
+ public int findPathSum(TreeNode node, int sum) {
+ if (node == null) {
+ return 0;
+ }
+ int res = 0;
+ sum -= node.val;
+ if (sum == 0) {
+ res++;
+ }
+ res += findPathSum(node.left, sum);
+ res += findPathSum(node.right, sum);
+
+ return res;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().pathSum(
+ TreeUtil.createTree(10, 5, -3, 3, 2, null, 11, 3, -2, null, 1), 8));
+ }
+}
\ No newline at end of file
diff --git a/algorithms/niuke/pom.xml b/algorithms/niuke/pom.xml
new file mode 100644
index 00000000..4884603b
--- /dev/null
+++ b/algorithms/niuke/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ algorithms
+ cn.lastwhisper
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ cn.cunchang
+ niuke
+
+
+ 8
+ 8
+
+
+
\ No newline at end of file
diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain1.java b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain1.java
new file mode 100644
index 00000000..492077e0
--- /dev/null
+++ b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain1.java
@@ -0,0 +1,17 @@
+package cn.cunchang.od;
+
+// 本题为考试单行多行输入输出规范示例,无需提交,不计分。
+
+import java.math.BigDecimal;
+import java.util.Scanner;
+
+public class DemoMain1 {
+ public static void main(String[] args) {
+ Scanner in = new Scanner(System.in);
+ while (in.hasNextInt()) {// 注意,如果输入是多个测试用例,请通过while循环处理多个测试用例
+ BigDecimal a = in.nextBigDecimal();
+ BigDecimal b = in.nextBigDecimal();
+ System.out.println(a.add(b));
+ }
+ }
+}
\ No newline at end of file
diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain2.java b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain2.java
new file mode 100644
index 00000000..ea59823c
--- /dev/null
+++ b/algorithms/niuke/src/main/java/cn/cunchang/od/DemoMain2.java
@@ -0,0 +1,17 @@
+package cn.cunchang.od;// 本题为考试多行输入输出规范示例,无需提交,不计分。
+import java.util.Scanner;
+
+public class DemoMain2 {
+ public static void main(String[] args) {
+ Scanner sc = new Scanner(System.in);
+ int n = sc.nextInt();
+ int ans = 0, x;
+ for(int i = 0; i < n; i++){
+ for(int j = 0; j < n; j++){
+ x = sc.nextInt();
+ ans += x;
+ }
+ }
+ System.out.println(ans);
+ }
+}
\ No newline at end of file
diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/Main1.java b/algorithms/niuke/src/main/java/cn/cunchang/od/Main1.java
new file mode 100644
index 00000000..9ec563ab
--- /dev/null
+++ b/algorithms/niuke/src/main/java/cn/cunchang/od/Main1.java
@@ -0,0 +1,47 @@
+package cn.cunchang.od;
+
+
+import java.util.*;
+
+public class Main1 {
+ public static void main(String[] args) {
+ Scanner sc = new Scanner(System.in);
+ int xmH = sc.nextInt();//小明身高
+ int N = sc.nextInt();// 同学数量
+
+ // 同学身高
+ List hList = new ArrayList<>(N);
+ for (int i = 0; i < N; i++) {
+ hList.add(sc.nextInt());
+ }
+ // 计算各个同学的身高差,按差升序,放到TreeMapList<差,同学身高list>
+ Map> diffSortMapList = new TreeMap<>();
+ for (Integer height : hList) {
+ int subDiff = Math.abs(xmH - height);
+ List someList = diffSortMapList.get(subDiff);
+ if (someList == null || someList.isEmpty()) {
+ someList = new ArrayList<>();
+ diffSortMapList.put(subDiff, someList);
+ }
+ someList.add(height);
+ }
+
+ // 返回结果
+ List result = new ArrayList<>(N);
+
+ // 对同学身高list局部排序
+ for (Map.Entry> entry : diffSortMapList.entrySet()) {
+ List someList = entry.getValue();
+ Collections.sort(someList);
+ result.addAll(someList);
+ }
+ for (int i = 0; i < result.size(); i++) {
+ if (i == result.size() - 1) {
+ System.out.print(result.get(i));
+ } else {
+ System.out.print(result.get(i) + " ");
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/Main2.java b/algorithms/niuke/src/main/java/cn/cunchang/od/Main2.java
new file mode 100644
index 00000000..a514a449
--- /dev/null
+++ b/algorithms/niuke/src/main/java/cn/cunchang/od/Main2.java
@@ -0,0 +1,123 @@
+package cn.cunchang.od;
+
+
+import java.util.*;
+
+public class Main2 {
+ // 映射与反映射 j=11,q=12,k=13,a=14
+ static Map pokMap = new HashMap<>();
+ static Map codeMap = new HashMap<>();
+
+ static {
+ pokMap.put("3", 0);
+ pokMap.put("4", 1);
+ pokMap.put("5", 2);
+ pokMap.put("6", 3);
+ pokMap.put("7", 4);
+ pokMap.put("8", 5);
+ pokMap.put("9", 6);
+ pokMap.put("10", 7);
+ pokMap.put("J", 8);
+ pokMap.put("Q", 9);
+ pokMap.put("K", 10);
+ pokMap.put("A", 11);
+
+ codeMap.put(0, "3");
+ codeMap.put(1, "4");
+ codeMap.put(2, "5");
+ codeMap.put(3, "6");
+ codeMap.put(4, "7");
+ codeMap.put(5, "8");
+ codeMap.put(6, "9");
+ codeMap.put(7, "10");
+ codeMap.put(8, "J");
+ codeMap.put(9, "Q");
+ codeMap.put(10, "K");
+ codeMap.put(11, "A");
+ }
+
+ public static void main(String[] args) {
+ Scanner sc = new Scanner(System.in);
+ String my = sc.nextLine();//我的手牌
+ String show = sc.nextLine();//别人打了的
+
+ // 顺子【3,14】不能有 2、大小王
+
+ // 统计my和show里面的牌频率
+ String[] mySplit = my.split("-");
+ String[] showSplit = show.split("-");
+
+ int[] freqs = new int[12];//12种可以构成顺子的牌
+ for (String myPok : mySplit) {
+ Integer pokCode = pokMap.get(myPok);
+ freqs[pokCode]++;
+ }
+ for (String showPok : showSplit) {
+ Integer pokCode = pokMap.get(showPok);
+ freqs[pokCode]++;
+ }
+ // 找到四张牌
+ List fourIdxList = new ArrayList<>();
+ for (int i = 0; i < freqs.length; i++) {
+ if (freqs[i] == 4) {
+ fourIdxList.add(i);
+ }
+ }
+
+ fourIdxList.add(12);//保证结尾扑克也会被扫到,偷懒写法
+
+ List orderList = new ArrayList<>();
+
+ // 顺子12张:0,1,2,3,4,5,6,7,8,9,10,11
+ int preIdx = 0;
+ int orderMax = 0;//顺子最大个数
+
+ // 构成顺子的
+ for (Integer fourIdx : fourIdxList) {
+ // 0~fourIdx-1;fourIdx+1~fourIdx-1;
+ int subOrderCount = fourIdx - preIdx;
+ if (subOrderCount >= 5) {//构成顺子
+ orderList.add(new KV(preIdx, fourIdx - 1));
+ orderMax = Math.max(subOrderCount, orderMax);
+ }
+
+ preIdx = fourIdx + 1;
+ }
+
+ // 找到四张牌,在【3,14】的位置,没有直接返回【3,A】
+
+// if (fourIdxList.isEmpty()) {
+// orderList.add(new KV(0, 11));
+// orderMax = 11;
+// }
+
+ int start = -1, end = -1;
+ for (KV kv : orderList) {
+ if (kv.v - kv.k == orderMax-1) {//减1是因为这里的kv是两个闭区间
+ start = kv.k;
+ end = kv.v;
+ }
+ }
+ if (start == -1) {
+ System.out.println("NO-CHAIN");
+ } else {
+ for (int i = start; i <= end; i++) {
+ if (i == end) {
+ System.out.print(codeMap.get(i));
+ } else {
+ System.out.print(codeMap.get(i) + "-");
+ }
+ }
+ }
+ }
+
+ static class KV {
+ public int k;
+ public int v;
+
+ public KV(int k, int v) {
+ this.k = k;
+ this.v = v;
+ }
+ }
+}
\ No newline at end of file
diff --git a/algorithms/niuke/src/main/java/cn/cunchang/od/Main3.java b/algorithms/niuke/src/main/java/cn/cunchang/od/Main3.java
new file mode 100644
index 00000000..4eb9be04
--- /dev/null
+++ b/algorithms/niuke/src/main/java/cn/cunchang/od/Main3.java
@@ -0,0 +1,87 @@
+package cn.cunchang.od;
+
+
+import java.util.Scanner;
+
+public class Main3 {
+
+ static int n;
+ static int m;
+
+ public static void main(String[] args) {
+ Scanner sc = new Scanner(System.in);
+ n = sc.nextInt();
+ m = sc.nextInt();
+ // 邻接矩阵
+ int[][] arrs = new int[n][m];
+ boolean[][] visited = new boolean[n][m];
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < m; j++) {
+ arrs[i][j] = sc.nextInt();
+ }
+ }
+
+ int res = 0;
+
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < m; j++) {
+ if (!visited[i][j]) {
+ int subResult = helper(arrs, visited, i, j);
+ res = Math.max(subResult, res);
+ }
+ }
+ }
+ System.out.println(res);
+ }
+
+ private static int helper(int[][] arrs, boolean[][] visited, int i, int j) {
+ if (i < 0 || i >= n || j < 0 || j >= m) {
+ return 0;
+ }
+ if (visited[i][j] || arrs[i][j] != 1) {
+ return 0;
+ }
+ visited[i][j] = true;
+ int subRes = helper(arrs, visited, i + 1, j) //下
+ + helper(arrs, visited, i - 1, j) // 上
+ + helper(arrs, visited, i, j - 1) // 左
+ + helper(arrs, visited, i, j + 1); //右
+ return subRes + 1;
+ }
+
+
+// public static void main(String[] args) {
+// Scanner sc = new Scanner(System.in);
+// int n = sc.nextInt();
+// int m = sc.nextInt();
+// // 邻接矩阵
+// int[][] arrs = new int[n][m];
+// boolean[] visited = new boolean[n];
+// for (int i = 0; i < n; i++) {
+// for (int j = 0; j < m; j++) {
+// arrs[i][j] = sc.nextInt();
+// }
+// }
+// for (int i = 0; i < n; i++) {
+// if (!visited[i]) {
+// helper(arrs, visited, i);
+// res++;
+// }
+// }
+// System.out.println(res);
+// }
+//
+// public static void helper(int[][] arrs, boolean[] visited, int idx) {
+// if (idx >= arrs.length) {
+// return;
+// }
+// if (visited[idx]) {
+// return;
+// }
+// visited[idx] = true;
+// for (int i = 0; i < idx; i++) {
+// helper(arrs, visited, i);
+// }
+// }
+
+}
\ No newline at end of file
diff --git a/algorithms/niuke/src/main/java/cn/cunchang/scanner/Main.java b/algorithms/niuke/src/main/java/cn/cunchang/scanner/Main.java
new file mode 100644
index 00000000..3cab137d
--- /dev/null
+++ b/algorithms/niuke/src/main/java/cn/cunchang/scanner/Main.java
@@ -0,0 +1,18 @@
+package cn.cunchang.scanner;
+
+import java.util.Scanner;
+
+public class Main {
+ public static void main(String[] args) {
+ Scanner sc = new Scanner(System.in);
+ int n = sc.nextInt();
+ int ans = 0, x;
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ x = sc.nextInt();
+ ans += x;
+ }
+ }
+ System.out.println(ans);
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/niuke/src/main/java/cn/cunchang/\346\262\241\346\234\211\351\207\215\345\244\215\351\241\271\346\225\260\345\255\227\347\232\204\345\205\250\346\216\222\345\210\227_BM55/Solution.java" "b/algorithms/niuke/src/main/java/cn/cunchang/\346\262\241\346\234\211\351\207\215\345\244\215\351\241\271\346\225\260\345\255\227\347\232\204\345\205\250\346\216\222\345\210\227_BM55/Solution.java"
new file mode 100644
index 00000000..86cbd2b8
--- /dev/null
+++ "b/algorithms/niuke/src/main/java/cn/cunchang/\346\262\241\346\234\211\351\207\215\345\244\215\351\241\271\346\225\260\345\255\227\347\232\204\345\205\250\346\216\222\345\210\227_BM55/Solution.java"
@@ -0,0 +1,46 @@
+package cn.cunchang.没有重复项数字的全排列_BM55;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+/**
+ * @author cunchang
+ * @date 2022/6/29 6:47 PM
+ */
+public class Solution {
+ ArrayList> result = new ArrayList<>();
+
+ public ArrayList> permute(int[] num) {
+ // 记录「路径」
+ LinkedList subResult = new LinkedList<>();
+ // 「路径」中的元素会被标记为 true,避免重复使用
+ boolean[] visited = new boolean[num.length];
+ permute0(num, subResult, visited);
+ return result;
+ }
+
+ private void permute0(int[] num, LinkedList subResult, boolean[] visited) {
+ // 回溯结束,记录结果
+ if (num.length == subResult.size()) {
+ result.add(new ArrayList<>(subResult));
+ }
+ // 遍历选择列表
+ for (int i = 0; i < num.length; i++) {
+ if (visited[i]) {
+ continue;
+ }
+ // 选择值
+ subResult.add(num[i]);
+ visited[i] = true;
+ permute0(num, subResult, visited);
+ // 撤销选择
+ subResult.removeLast();
+ visited[i] = false;
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new Solution().permute(new int[]{1, 2, 3}));
+ }
+
+}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java"
index 41c01344..8bdbec40 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23007_\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221_\344\270\255\347\255\211/Solution1.java"
@@ -1,7 +1,7 @@
package cn.lastwhisper.offer.面试题07_重建二叉树_中等;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
class Solution1 {
/**
@@ -50,6 +50,6 @@ private TreeNode construct(int[] pre, int[] in, int pStart, int pEnd, int iStart
public static void main(String[] args) {
int[] preorder = {3, 9, 20, 15, 7}, inorder = {9, 3, 15, 20, 7};
- TreeUtils.printLevelOrder(new Solution1().buildTree(preorder, inorder));
+ TreeUtil.printLevelOrder(new Solution1().buildTree(preorder, inorder));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java"
index ebe32a67..5ba13063 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23012_\347\237\251\351\230\265\344\270\255\347\232\204\350\267\257\345\276\204_\344\270\255\347\255\211/Solution1.java"
@@ -1,6 +1,6 @@
package cn.lastwhisper.offer.面试题12_矩阵中的路径_中等;
-import cn.lastwhisper.leetcode.common.matrix.ArrayUtils;
+import cn.lastwhisper.leetcode.common.array.ArrayUtil;
class Solution1 {
@@ -90,6 +90,6 @@ public static void main(String[] args) {
//String word = "ABCCED";
String[][] board = new String[][]{{"a", "b"}, {"c", "d"}};
String word = "abcd";
- System.err.println(new Solution1().exist(ArrayUtils.createCharArrays(board), word));
+ System.err.println(new Solution1().exist(ArrayUtil.createCharArrays(board), word));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java"
index 75aa1f36..863b39a9 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23026_\346\240\221\347\232\204\345\255\220\347\273\223\346\236\204/Solution1.java"
@@ -1,7 +1,7 @@
package cn.lastwhisper.offer.面试题26_树的子结构;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
class Solution1 {
/**
@@ -49,8 +49,8 @@ private boolean compare(TreeNode root1, TreeNode root2) {
public static void main(String[] args) {
//TreeNode A = TreeUtils.createTree(1, 2, 3);
//TreeNode B = TreeUtils.createTree(3, 1);
- TreeNode A = TreeUtils.createTree(3, 4, 5, 1, 2);
- TreeNode B = TreeUtils.createTree(4, 1);
+ TreeNode A = TreeUtil.createTree(3, 4, 5, 1, 2);
+ TreeNode B = TreeUtil.createTree(4, 1);
System.out.println(new Solution1().isSubStructure(A, B));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java"
index 12a910e3..cf03f38d 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23027_\344\272\214\345\217\211\346\240\221\347\232\204\351\225\234\345\203\217/Solution1.java"
@@ -1,7 +1,7 @@
package cn.lastwhisper.offer.面试题27_二叉树的镜像;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
class Solution1 {
/**
@@ -27,7 +27,7 @@ public TreeNode mirrorTree(TreeNode root) {
}
public static void main(String[] args) {
- TreeNode tree = TreeUtils.createTree(4, 2, 7, 1, 3, 6, 9);
- TreeUtils.printLevelOrder(new Solution1().mirrorTree(tree));
+ TreeNode tree = TreeUtil.createTree(4, 2, 7, 1, 3, 6, 9);
+ TreeUtil.printLevelOrder(new Solution1().mirrorTree(tree));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java"
index d17e7cc7..e2d01313 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23028_\345\257\271\347\247\260\347\232\204\344\272\214\345\217\211\346\240\221/Solution1.java"
@@ -1,7 +1,7 @@
package cn.lastwhisper.offer.面试题28_对称的二叉树;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
class Solution1 {
/**
@@ -36,6 +36,6 @@ private boolean isSymmetric(TreeNode root1, TreeNode root2) {
}
public static void main(String[] args) {
- System.out.println(new Solution1().isSymmetric(TreeUtils.createTree(1, 2, 2, 3, 4, 4, 3)));
+ System.out.println(new Solution1().isSymmetric(TreeUtil.createTree(1, 2, 2, 3, 4, 4, 3)));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java"
index 66709343..d9cab9f4 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_III_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III/Solution1.java"
@@ -1,8 +1,8 @@
package cn.lastwhisper.offer.面试题32_III_从上到下打印二叉树III;
-import cn.lastwhisper.leetcode.common.print.PrintUtils;
+import cn.lastwhisper.leetcode.common.print.PrintUtil;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -47,6 +47,6 @@ public List> levelOrder(TreeNode root) {
}
public static void main(String[] args) {
- PrintUtils.printLists(new Solution1().levelOrder(TreeUtils.createTree(3, 9, 20, null, null, 15, 7)));
+ PrintUtil.printLists(new Solution1().levelOrder(TreeUtil.createTree(3, 9, 20, null, null, 15, 7)));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java"
index 3dd0f11f..bb031ef7 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_II_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221II/Solution1.java"
@@ -1,9 +1,8 @@
package cn.lastwhisper.offer.面试题32_II_从上到下打印二叉树II;
-import cn.lastwhisper.leetcode.common.linkedlist.LinkedListUtil;
-import cn.lastwhisper.leetcode.common.print.PrintUtils;
+import cn.lastwhisper.leetcode.common.print.PrintUtil;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -43,6 +42,6 @@ public List> levelOrder(TreeNode root) {
}
public static void main(String[] args) {
- PrintUtils.printLists(new Solution1().levelOrder(TreeUtils.createTree(3,9,20,null,null,15,7)));
+ PrintUtil.printLists(new Solution1().levelOrder(TreeUtil.createTree(3,9,20,null,null,15,7)));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java"
index 9deecdbf..af425ebb 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23032_I_\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221/Solution1.java"
@@ -1,7 +1,7 @@
package cn.lastwhisper.offer.面试题32_I_从上到下打印二叉树;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
import java.util.*;
@@ -37,6 +37,6 @@ public int[] levelOrder(TreeNode root) {
}
public static void main(String[] args) {
- System.out.println(Arrays.toString(new Solution1().levelOrder(TreeUtils.createTree(3, 9, 20, 15, 7))));
+ System.out.println(Arrays.toString(new Solution1().levelOrder(TreeUtil.createTree(3, 9, 20, 15, 7))));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java"
index b574fb09..901418e2 100644
--- "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java"
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23034_\344\272\214\345\217\211\346\240\221\344\270\255\345\222\214\344\270\272\346\237\220\344\270\200\345\200\274\347\232\204\350\267\257\345\276\204/Solution1.java"
@@ -1,8 +1,8 @@
package cn.lastwhisper.offer.面试题34_二叉树中和为某一值的路径;
-import cn.lastwhisper.leetcode.common.print.PrintUtils;
+import cn.lastwhisper.leetcode.common.print.PrintUtil;
import cn.lastwhisper.leetcode.common.tree.TreeNode;
-import cn.lastwhisper.leetcode.common.tree.TreeUtils;
+import cn.lastwhisper.leetcode.common.tree.TreeUtil;
import java.util.ArrayList;
import java.util.List;
@@ -45,8 +45,8 @@ public void pathSumHelper(TreeNode root, int sum, List list, List 0 && idx < k) {
+ res[idx++] = num;
+ }
+ if (idx == k) {
+ break;
+ }
+ }
+ return res;
}
public static void main(String[] args) {
-
+ Assert.assertArrayEquals(new int[]{1, 2}, new Solution1().getLeastNumbers(new int[]{3, 2, 1}, 2));
+ Assert.assertArrayEquals(new int[]{0}, new Solution1().getLeastNumbers(new int[]{0, 1, 2, 1}, 1));
}
}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23059_I_\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/Solution.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23059_I_\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/Solution.java"
new file mode 100644
index 00000000..c96621eb
--- /dev/null
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23059_I_\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274/Solution.java"
@@ -0,0 +1,34 @@
+package cn.lastwhisper.offer.面试题59_I_滑动窗口的最大值;
+
+import java.util.Arrays;
+
+class Solution {
+ /**
+ * 题目地址:https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/
+ * 编号:面试题59 - I
+ * -------------------------------------------------------------------
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:双指针(滑动窗口)
+ * (1)
+ * -------------------------------------------------------------------
+ * 时间复杂度:
+ * 空间复杂度:
+ */
+ public int[] maxSlidingWindow(int[] nums, int k) {
+ if (nums == null || nums.length < k)
+ return nums;
+
+
+
+
+ return null;
+ }
+
+
+ public static void main(String[] args) {
+ int[] nums = new int[]{1, 3, -1, -3, 5, 3, 6, 7};
+ int k = 3;
+ System.out.println(Arrays.toString(new Solution().maxSlidingWindow(nums, k)));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution1.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution1.java"
new file mode 100644
index 00000000..a196364e
--- /dev/null
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution1.java"
@@ -0,0 +1,39 @@
+package cn.lastwhisper.offer.面试题62_圆圈中最后剩下的数字;
+
+import org.junit.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class Solution1 {
+ /**
+ * 题目地址:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/
+ * -------------------------------------------------------------------
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ * 通过取模模拟环状
+ * -------------------------------------------------------------------
+ * 时间复杂度:O(mn)
+ * 空间复杂度:O(n)
+ */
+ public int lastRemaining(int n, int m) {
+ List list = new ArrayList<>();
+ for (int i = 0; i < n; i++) {
+ list.add(i);
+ }
+ int idx = 0;
+ while (n > 1) {
+ // 模拟环状,-1是因为移除一个数
+ idx = (idx + m - 1) % n;
+ list.remove(idx);
+ n--;
+ }
+
+ return list.get(0);
+ }
+
+ public static void main(String[] args) {
+ Assert.assertEquals(3, new Solution1().lastRemaining(5, 3));
+ }
+}
\ No newline at end of file
diff --git "a/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution2.java" "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution2.java"
new file mode 100644
index 00000000..6e87c9a2
--- /dev/null
+++ "b/algorithms/offer/src/main/java/cn/lastwhisper/offer/\351\235\242\350\257\225\351\242\23062_\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227/Solution2.java"
@@ -0,0 +1,42 @@
+package cn.lastwhisper.offer.面试题62_圆圈中最后剩下的数字;
+
+import org.junit.Assert;
+
+class Solution2 {
+ /**
+ * 题目地址:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/
+ * -------------------------------------------------------------------
+ * 思考:
+ * -------------------------------------------------------------------
+ * 思路:
+ * https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-by-lee/
+ * 将上述问题建模为函数 f(n, m),该函数的返回值为最终留下的元素的序号
+ * 长度为n的序列会先删除第m%n个元素,然后剩下一个长度为n-1的序列,递归地求解f(n-1,m),设x=f(n-1,m)
+ * f(n - 1, m) = (m % n + x) % n = (m + x) % n
+ * -------------------------------------------------------------------
+ * 时间复杂度:O(n)
+ * 空间复杂度:O(n)
+ */
+ public int lastRemaining(int n, int m) {
+ //int ans = 0;
+ //// 最后一轮剩下2个人,所以从2开始反推
+ //for (int i = 2; i <= n; i++) {
+ // ans = (ans + m) % i;
+ //}
+ //return ans;
+ return f(n, m);
+ }
+
+ private int f(int n, int m) {
+ // 当序列长度为 1 时,一定会留下唯一的那个元素,它的编号为 0
+ if (n == 1){
+ return 0;
+ }
+ int x = f(n - 1, m);
+ return (m + x) % n;
+ }
+
+ public static void main(String[] args) {
+ Assert.assertEquals(3, new Solution2().lastRemaining(5, 3));
+ }
+}
\ No newline at end of file
diff --git a/algorithms/pom.xml b/algorithms/pom.xml
index bc8c6ec3..c67bc1b0 100644
--- a/algorithms/pom.xml
+++ b/algorithms/pom.xml
@@ -14,7 +14,8 @@
interview
algorithm
leetcode
- thread
+ algorithm-common
+ niuke
diff --git a/algorithms/test/pom.xml b/algorithms/test/pom.xml
new file mode 100644
index 00000000..2b1eb3d3
--- /dev/null
+++ b/algorithms/test/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+ org.example
+ test
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+
+
+
\ No newline at end of file
diff --git a/algorithms/test/src/main/java/cn/cunchang/Main.java b/algorithms/test/src/main/java/cn/cunchang/Main.java
new file mode 100644
index 00000000..51de18e3
--- /dev/null
+++ b/algorithms/test/src/main/java/cn/cunchang/Main.java
@@ -0,0 +1,39 @@
+package cn.cunchang;
+
+import java.util.ArrayList;
+import java.util.Scanner;
+
+/**
+ * @author cunchang
+ * @date 2022/7/6 8:12 PM
+ */
+public class Main {
+
+ /**
+ * 有n个人围成一圈,顺序排号。
+ * 从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位,起始索引位置为0。
+ */
+ public static void main(String[] args) {
+ Scanner scanner = new Scanner(System.in);
+ int n = scanner.nextInt();
+ ArrayList list = new ArrayList<>(n);
+ for (int i = 0; i < n; i++) {
+ list.add(i + 1);
+ }
+ int idx = 0;
+ int count = 0;
+ while (list.size() >1) {
+ if (count == 2) {
+ list.remove(idx);
+ idx=-1;
+ count=0;
+ }
+ idx++;
+ count++;
+ }
+
+ // 还剩两个人
+ System.out.println(list);
+ }
+
+}
diff --git a/algorithms/test/src/main/java/cn/cunchang/Main2.java b/algorithms/test/src/main/java/cn/cunchang/Main2.java
new file mode 100644
index 00000000..8eda3417
--- /dev/null
+++ b/algorithms/test/src/main/java/cn/cunchang/Main2.java
@@ -0,0 +1,45 @@
+package cn.cunchang;
+
+import java.util.Scanner;
+
+/**
+ * @author cunchang
+ * @date 2022/7/6 8:12 PM
+ */
+public class Main2 {
+
+ /**
+ * 有n个人围成一圈,顺序排号。
+ * 从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位,起始索引位置为0。
+ */
+ public static void main(String[] args) {
+ Scanner scanner = new Scanner(System.in);
+ int n = scanner.nextInt();
+
+ boolean[] visited = new boolean[n];//true表示访问了
+
+ int outCount = n;
+ int idx = 0;// 访问下标
+ int outIdx = 1;// 剔除计数
+ while (outCount > 1) {
+ if (visited[idx % n]) {
+ idx++;
+ continue;
+ }
+ if (outIdx == 3) {
+ visited[idx % n] = true;
+ outCount--;
+ outIdx = 0;
+ }
+ idx++;
+ outIdx++;
+ }
+
+ for (int i = 0; i < visited.length; i++) {
+ if (!visited[i]) {
+ System.out.println(i + 1);
+ }
+ }
+ }
+
+}
diff --git a/algorithms/thread/pom.xml b/algorithms/thread/pom.xml
deleted file mode 100644
index 765558b2..00000000
--- a/algorithms/thread/pom.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- algorithms
- cn.lastwhisper
- 1.0-SNAPSHOT
-
- 4.0.0
-
- cn.lastwhisper
- thread
-
-
-
\ No newline at end of file
diff --git "a/algorithms/thread/src/main/java/cn/lastwhisper/thread/\346\214\211\345\272\217\346\211\223\345\215\2601114/Foo.java" "b/algorithms/thread/src/main/java/cn/lastwhisper/thread/\346\214\211\345\272\217\346\211\223\345\215\2601114/Foo.java"
deleted file mode 100644
index a075b4a2..00000000
--- "a/algorithms/thread/src/main/java/cn/lastwhisper/thread/\346\214\211\345\272\217\346\211\223\345\215\2601114/Foo.java"
+++ /dev/null
@@ -1,32 +0,0 @@
-package cn.lastwhisper.thread.按序打印1114;
-
-import java.util.concurrent.CountDownLatch;
-
-public class Foo {
- private CountDownLatch second = new CountDownLatch(1);
- private CountDownLatch third = new CountDownLatch(1);
-
- public Foo() {
-
- }
-
- public void first(Runnable printFirst) throws InterruptedException {
-
- // printFirst.run() outputs "first". Do not change or remove this line.
- printFirst.run();
- second.countDown();
- }
-
- public void second(Runnable printSecond) throws InterruptedException {
-
- // printSecond.run() outputs "second". Do not change or remove this line.
- printSecond.run();
- third.countDown();
- }
-
- public void third(Runnable printThird) throws InterruptedException {
- third.await();
- // printThird.run() outputs "third". Do not change or remove this line.
- printThird.run();
- }
-}
\ No newline at end of file
diff --git a/bigdata/flink-cdc/pom.xml b/bigdata/flink-cdc/pom.xml
new file mode 100644
index 00000000..041ae367
--- /dev/null
+++ b/bigdata/flink-cdc/pom.xml
@@ -0,0 +1,92 @@
+
+
+ 4.0.0
+
+ cn.cunchang
+ flink-cdc
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+ 1.13.2
+
+
+
+
+
+ org.apache.flink
+ flink-java
+ ${flink-version}
+
+
+
+ org.apache.flink
+ flink-streaming-java_2.12
+ ${flink-version}
+
+
+
+ org.apache.flink
+ flink-clients_2.12
+ ${flink-version}
+
+
+
+ org.apache.hadoop
+ hadoop-client
+ 3.1.3
+
+
+
+ mysql
+ mysql-connector-java
+ 5.1.49
+
+
+
+ org.apache.flink
+ flink-table-planner-blink_2.12
+ ${flink-version}
+
+
+
+ com.ververica
+ flink-connector-mysql-cdc
+ 2.0.0
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.75
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.0.0
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC.java
new file mode 100644
index 00000000..81ecaeb2
--- /dev/null
+++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC.java
@@ -0,0 +1,51 @@
+package cn.cunchang;
+
+import com.ververica.cdc.connectors.mysql.MySqlSource;
+import com.ververica.cdc.connectors.mysql.table.StartupOptions;
+import com.ververica.cdc.debezium.DebeziumSourceFunction;
+import com.ververica.cdc.debezium.StringDebeziumDeserializationSchema;
+import org.apache.flink.runtime.state.hashmap.HashMapStateBackend;
+import org.apache.flink.streaming.api.CheckpointingMode;
+import org.apache.flink.streaming.api.datastream.DataStreamSource;
+import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
+
+public class FlinkCDC {
+
+ public static void main(String[] args) throws Exception {
+
+ //1.获取Flink 执行环境
+ StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
+ env.setParallelism(1);
+
+ //1.1 开启Checkpoint,保存任务中断点,重启从中断点继续执行
+// env.enableCheckpointing(5000);
+// env.getCheckpointConfig().setCheckpointTimeout(10000);
+// env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
+// env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);
+ // 默认ck在内存里,也可以存到hdfs
+ env.setStateBackend(new HashMapStateBackend());
+ // env.setStateBackend(new FsStateBackend("hdfs://localhost:9000/cdc-test/ck")); //过时写法
+ // env.getCheckpointConfig().setCheckpointStorage("hdfs://localhost:9000/cdc-test/ck");
+
+ //2.通过FlinkCDC构建SourceFunction
+ DebeziumSourceFunction sourceFunction = MySqlSource.builder()
+ .hostname("localhost")
+ .port(3306)
+ .username("root")
+ .password("123456")
+ .databaseList("cdc_test")
+ .tableList("cdc_test.user_info")
+ .deserializer(new StringDebeziumDeserializationSchema())
+ .startupOptions(StartupOptions.initial())
+ .build();
+ DataStreamSource dataStreamSource = env.addSource(sourceFunction);
+
+ //3.数据打印
+ dataStreamSource.print();
+
+ //4.启动任务
+ env.execute("FlinkCDC");
+
+ }
+
+}
diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC2.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC2.java
new file mode 100644
index 00000000..5bbc1bef
--- /dev/null
+++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkCDC2.java
@@ -0,0 +1,43 @@
+package cn.cunchang;
+
+import cn.cunchang.func.CustomerDeserializationSchema;
+import com.ververica.cdc.connectors.mysql.MySqlSource;
+import com.ververica.cdc.connectors.mysql.table.StartupOptions;
+import com.ververica.cdc.debezium.DebeziumSourceFunction;
+import org.apache.flink.streaming.api.datastream.DataStreamSource;
+import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
+
+public class FlinkCDC2 {
+
+ /**
+ * @param args
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ //1.获取Flink 执行环境
+ StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
+ env.setParallelism(1);
+
+ //2.通过FlinkCDC构建SourceFunction
+ DebeziumSourceFunction sourceFunction = MySqlSource.builder()
+ .hostname("localhost")
+ .port(3306)
+ .username("root")
+ .password("123456")
+ .databaseList("cdc_test")
+ .tableList("cdc_test.user_info")
+ .deserializer(new CustomerDeserializationSchema())
+ .startupOptions(StartupOptions.initial())
+ .build();
+ DataStreamSource dataStreamSource = env.addSource(sourceFunction);
+
+ //3.数据打印
+ dataStreamSource.print();
+
+ //4.启动任务
+ env.execute("FlinkCDC2");
+
+ }
+
+}
diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkSQLCDC.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkSQLCDC.java
new file mode 100644
index 00000000..70ae914e
--- /dev/null
+++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/FlinkSQLCDC.java
@@ -0,0 +1,45 @@
+package cn.cunchang;
+
+import org.apache.flink.api.java.tuple.Tuple2;
+import org.apache.flink.streaming.api.datastream.DataStream;
+import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
+import org.apache.flink.table.api.Table;
+import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
+import org.apache.flink.types.Row;
+
+public class FlinkSQLCDC {
+
+ public static void main(String[] args) throws Exception {
+
+ //1.获取执行环境
+ StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
+ env.setParallelism(1);
+ StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);
+
+ //2.使用FLINKSQL DDL模式构建CDC 表
+ tableEnv.executeSql("CREATE TABLE user_info ( " +
+ " id STRING primary key, " +
+ " name STRING, " +
+ " sex STRING " +
+ ") WITH ( " +
+ " 'connector' = 'mysql-cdc', " +
+ " 'scan.startup.mode' = 'latest-offset', " +
+ " 'hostname' = 'localhost', " +
+ " 'port' = '3306', " +
+ " 'username' = 'root', " +
+ " 'password' = '123456', " +
+ " 'database-name' = 'cdc_test', " +
+ " 'table-name' = 'user_info' " +
+ ")");
+
+ //3.查询数据并转换为流输出
+ Table table = tableEnv.sqlQuery("select * from user_info");
+ DataStream> retractStream = tableEnv.toRetractStream(table, Row.class);
+ retractStream.print();
+
+ //4.启动
+ env.execute("FlinkSQLCDC");
+
+ }
+
+}
diff --git a/bigdata/flink-cdc/src/main/java/cn/cunchang/func/CustomerDeserializationSchema.java b/bigdata/flink-cdc/src/main/java/cn/cunchang/func/CustomerDeserializationSchema.java
new file mode 100644
index 00000000..99448140
--- /dev/null
+++ b/bigdata/flink-cdc/src/main/java/cn/cunchang/func/CustomerDeserializationSchema.java
@@ -0,0 +1,82 @@
+package cn.cunchang.func;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ververica.cdc.debezium.DebeziumDeserializationSchema;
+import io.debezium.data.Envelope;
+import org.apache.flink.api.common.typeinfo.BasicTypeInfo;
+import org.apache.flink.api.common.typeinfo.TypeInformation;
+import org.apache.flink.util.Collector;
+import org.apache.kafka.connect.data.Field;
+import org.apache.kafka.connect.data.Schema;
+import org.apache.kafka.connect.data.Struct;
+import org.apache.kafka.connect.source.SourceRecord;
+
+import java.util.List;
+
+public class CustomerDeserializationSchema implements DebeziumDeserializationSchema {
+
+
+ /**
+ * {
+ * "db":"",
+ * "tableName":"",
+ * "before":{"id":"1001","name":""...},
+ * "after":{"id":"1001","name":""...},
+ * "op":""
+ * }
+ */
+ @Override
+ public void deserialize(SourceRecord sourceRecord, Collector collector) throws Exception {
+
+ //创建JSON对象用于封装结果数据
+ JSONObject result = new JSONObject();
+
+ //获取库名&表名
+ String topic = sourceRecord.topic();
+ String[] fields = topic.split("\\.");
+ result.put("db", fields[1]);
+ result.put("tableName", fields[2]);
+
+ //获取before数据
+ Struct value = (Struct) sourceRecord.value();
+ Struct before = value.getStruct("before");
+ JSONObject beforeJson = new JSONObject();
+ if (before != null) {
+ //获取列信息
+ Schema schema = before.schema();
+ List fieldList = schema.fields();
+
+ for (Field field : fieldList) {
+ beforeJson.put(field.name(), before.get(field));
+ }
+ }
+ result.put("before", beforeJson);
+
+ //获取after数据
+ Struct after = value.getStruct("after");
+ JSONObject afterJson = new JSONObject();
+ if (after != null) {
+ //获取列信息
+ Schema schema = after.schema();
+ List fieldList = schema.fields();
+
+ for (Field field : fieldList) {
+ afterJson.put(field.name(), after.get(field));
+ }
+ }
+ result.put("after", afterJson);
+
+ //获取操作类型
+ Envelope.Operation operation = Envelope.operationFor(sourceRecord);
+ result.put("op", operation);
+
+ //输出数据
+ collector.collect(result.toJSONString());
+
+ }
+
+ @Override
+ public TypeInformation getProducedType() {
+ return BasicTypeInfo.STRING_TYPE_INFO;
+ }
+}
diff --git a/bigdata/flink/pom.xml b/bigdata/flink/pom.xml
new file mode 100644
index 00000000..30a11181
--- /dev/null
+++ b/bigdata/flink/pom.xml
@@ -0,0 +1,149 @@
+
+
+ 4.0.0
+
+ cn.cunchang
+ flink
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+
+
+
+
+ org.apache.flink
+ flink-java
+ 1.11.1
+
+
+
+ org.apache.flink
+ flink-streaming-java_2.12
+ 1.11.1
+
+
+
+
+ org.apache.flink
+ flink-streaming-scala_2.12
+ 1.11.0
+
+
+
+
+ org.apache.flink
+ flink-clients_2.12
+ 1.11.1
+
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.10
+
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.7.10
+
+
+
+ org.apache.hadoop
+ hadoop-client
+ 3.2.0
+
+
+
+ org.apache.bahir
+ flink-connector-redis_2.11
+ 1.0
+
+
+
+ org.apache.flink
+ flink-table-api-java-bridge_2.12
+ 1.11.0
+
+
+
+ org.apache.flink
+ flink-table-api-scala-bridge_2.12
+ 1.11.0
+
+
+
+
+ org.apache.flink
+ flink-table-planner-blink_2.12
+ 1.11.0
+
+
+
+
+ org.apache.flink
+ flink-table-planner_2.12
+ 1.11.1
+
+
+
+
+ org.apache.flink
+ flink-connector-kafka_2.12
+ 1.11.1
+
+
+ org.apache.flink
+ flink-statebackend-rocksdb_2.12
+ 1.11.1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.4.1
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bigdata/flink/src/main/java/cn/cunchang/README.txt b/bigdata/flink/src/main/java/cn/cunchang/README.txt
new file mode 100644
index 00000000..3449dfb0
--- /dev/null
+++ b/bigdata/flink/src/main/java/cn/cunchang/README.txt
@@ -0,0 +1,57 @@
+
+# 入门
+# 一、流处理和批处理程序开发
+stream.SocketWindowWordCountJava 实时处理
+batch.BatchWordCountJava 批处理
+
+# 二、Flink核心API之DataStream API
+## DataStreamAPI之DataSource
+- stream.source.StreamCollectionSourceJava
+
+## DataStreamAPI之Transformation
+- stream.transformation
+- 算子
+ - union 合并多个流,多个流的数据类型必须一致
+ - connect 只能连接两个流,两个流的数据类型可以不同
+ - split 根据规则把一个数据流切分为多个流;代码:StreamSplitJava、StreamSideOutputJava
+- 算子分区
+ - shuffle 随机分区
+ - rebalance 对数据集进行再平衡(顺序),重分区,消除数据倾斜
+ - rescale 重分区(局部顺序)
+ - partitionCustom 自定义分区;代码:StreamPartitionOpJava
+
+## DataStreamAPI之DataSink
+- stream.sink.StreamRedisSinkJava
+
+# 三、Flink核心API之DataSetAPI
+## DataSetAPI之Transformation
+- batch.transformation
+- 算子
+ - mapPartition 类似map,一次处理一个分区的数据;代码:BatchMapPartitionJava
+ - distinct 返回数据集中去重之后的元素
+ - join 内连接;代码:BatchJoinJava
+ - outerJoin 外连接;代码:BatchOuterJoinJava
+ - cross 获取两个数据集的笛卡尔积;BatchCrossJava
+ - union 返回多个数据集的总和,数据类型需要一致
+ - first-n 获取集合中的前N个元素;BatchFirstNJava
+
+# 四、Flink核心API之TableAPI和SQL
+tablesql
+
+## Table API 和SQL的使用
+- CreateTableEnvironmentJava 创建一个TableEnvironment对象
+- TableAPIAndSQLOpJava
+- DataStreamToTableJava DataStream、DataSet和Table之间的互相转换
+
+# 进阶
+# 一、Window
+- TimeWindowOpJava
+- CountWindowOpJava
+- MyTimeWindowJava
+
+
+
+
+
+
+
diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/BatchWordCountJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/BatchWordCountJava.java
new file mode 100644
index 00000000..53a727b9
--- /dev/null
+++ b/bigdata/flink/src/main/java/cn/cunchang/batch/BatchWordCountJava.java
@@ -0,0 +1,44 @@
+package cn.cunchang.batch;
+
+import org.apache.flink.api.common.functions.FlatMapFunction;
+import org.apache.flink.api.java.ExecutionEnvironment;
+import org.apache.flink.api.java.operators.AggregateOperator;
+import org.apache.flink.api.java.operators.DataSource;
+import org.apache.flink.api.java.tuple.Tuple2;
+import org.apache.flink.util.Collector;
+
+/**
+ * 需求:统计指定文件中单词出现的总次数
+ * Created by xuwei
+ */
+public class BatchWordCountJava {
+ public static void main(String[] args) throws Exception{
+ //获取执行环境
+ ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
+
+ String inputPath = "hdfs://localhost:9000/hello.txt";
+ String outPath = "hdfs://localhost:9000/out2";
+
+ //读取文件中的数据
+ DataSource text = env.readTextFile(inputPath);
+
+ //处理数据
+ AggregateOperator> wordCount = text.flatMap(new FlatMapFunction>() {
+ public void flatMap(String line, Collector> out)
+ throws Exception {
+ String[] words = line.split(" ");
+ for (String word : words) {
+ out.collect(new Tuple2(word, 1));
+ }
+ }
+ }).groupBy(0)
+ .sum(1)
+ .setParallelism(1);
+
+ //将结果数据保存到文件中
+ wordCount.writeAsCsv(outPath,"\n"," ");
+
+ //执行程序
+ env.execute("BatchWordCountJava");
+ }
+}
diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchCrossJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchCrossJava.java
new file mode 100644
index 00000000..1994477c
--- /dev/null
+++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchCrossJava.java
@@ -0,0 +1,24 @@
+package cn.cunchang.batch.transformation;
+
+import org.apache.flink.api.java.ExecutionEnvironment;
+import org.apache.flink.api.java.operators.DataSource;
+
+import java.util.Arrays;
+
+/**
+ * cross:获取两个数据集的笛卡尔积
+ * Created by xuwei
+ */
+public class BatchCrossJava {
+ public static void main(String[] args) throws Exception{
+ ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
+
+ //初始化第一份数据
+ DataSource text1 = env.fromCollection(Arrays.asList(1, 2));
+ //初始化第二份数据
+ DataSource text2 = env.fromCollection(Arrays.asList("a", "b"));
+
+ //执行cross操作
+ text1.cross(text2).print();
+ }
+}
diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchFirstNJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchFirstNJava.java
new file mode 100644
index 00000000..47b1959e
--- /dev/null
+++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchFirstNJava.java
@@ -0,0 +1,43 @@
+package cn.cunchang.batch.transformation;
+
+import org.apache.flink.api.common.operators.Order;
+import org.apache.flink.api.java.ExecutionEnvironment;
+import org.apache.flink.api.java.operators.DataSource;
+import org.apache.flink.api.java.tuple.Tuple2;
+
+import java.util.ArrayList;
+
+/**
+ * first-n:获取集合中的前N个元素
+ * Created by xuwei
+ */
+public class BatchFirstNJava {
+ public static void main(String[] args) throws Exception{
+ ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
+
+ ArrayList> data = new ArrayList<>();
+ data.add(new Tuple2(2,"zs"));
+ data.add(new Tuple2(4,"ls"));
+ data.add(new Tuple2(3,"ww"));
+ data.add(new Tuple2(1,"aw"));
+ data.add(new Tuple2(1,"xw"));
+ data.add(new Tuple2(1,"mw"));
+
+ //初始化数据
+ DataSource> text = env.fromCollection(data);
+
+ //获取前3条数据,按照数据插入的顺序
+ text.first(3).print();
+ System.out.println("============================================");
+
+
+ //根据数据中的第一列进行分组,获取每组的前2个元素
+ text.groupBy(0).first(2).print();
+ System.out.println("============================================");
+
+ //根据数据中的第一列分组,再根据第二列进行组内排序[倒序],获取每组的前2个元素
+ //分组排序取TopN
+ text.groupBy(0).sortGroup(1, Order.DESCENDING).first(2).print();
+ System.out.println("============================================");
+ }
+}
diff --git a/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchJoinJava.java b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchJoinJava.java
new file mode 100644
index 00000000..34a2b1c6
--- /dev/null
+++ b/bigdata/flink/src/main/java/cn/cunchang/batch/transformation/BatchJoinJava.java
@@ -0,0 +1,52 @@
+package cn.cunchang.batch.transformation;
+
+import org.apache.flink.api.common.functions.JoinFunction;
+import org.apache.flink.api.java.ExecutionEnvironment;
+import org.apache.flink.api.java.operators.DataSource;
+import org.apache.flink.api.java.tuple.Tuple2;
+import org.apache.flink.api.java.tuple.Tuple3;
+
+import java.util.ArrayList;
+
+/**
+ * join:内连接
+ * Created by xuwei
+ */
+public class BatchJoinJava {
+ public static void main(String[] args) throws Exception{
+ ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
+
+ //初始化第一份数据 Tuple2<用户id,用户姓名>
+ ArrayList> data1 = new ArrayList<>();
+ data1.add(new Tuple2(1,"jack"));
+ data1.add(new Tuple2(2,"tom"));
+ data1.add(new Tuple2(3,"mick"));
+ DataSource> text1 = env.fromCollection(data1);
+
+ //初始化第二份数据 Tuple2<用户id,用户所在城市>
+ ArrayList> data2 = new ArrayList<>();
+ data2.add(new Tuple2(1,"bj"));
+ data2.add(new Tuple2(2,"sh"));
+ data2.add(new Tuple2(4,"gz"));
+ DataSource> text2 = env.fromCollection(data2);
+
+ //对两份数据集执行join操作
+ text1.join(text2)
+ //注意:这里的where和equalTo实现了类似于on fieldA=fieldB的效果
+ //where:指定左边数据集中参与比较的元素角标
+ .where(0)
+ .equalTo(0)
+ //三个输入参数:
+ //第一个tuple2是左边数据集的类型,
+ //第二个tuple2是右边数据集的类型,
+ //第三个tuple3是此函数返回的数据集类型
+ .with(new JoinFunction, Tuple2