diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/AbsoluteBeiBao.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/AbsoluteBeiBao.java new file mode 100644 index 0000000..60b03f4 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/AbsoluteBeiBao.java @@ -0,0 +1,69 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/26 13:30 + * @注释 + */ +public class AbsoluteBeiBao { + + @Test + public void test() { + int[] weight = {1, 3, 4}; + int[] value = {15, 20, 30}; + int capacity = 4; + System.out.println(absoluteBeiBaoOneD(weight, value, capacity)); + } + + /** + * 使用动态规划解决背包问题,求解在给定背包容量下,能够获得的最大价值。 + * @param weight 物品的重量数组 + * @param value 物品的价值数组 + * @param capacity 背包的容量 + */ + public int absoluteBeiBao(int[] weight, int[] value,int capacity) { + + int length = weight.length; + int[][] dp = new int[length + 1][capacity + 1]; + + // 初始化动态规划数组 + // dp[i][j] 表示在前 i 个物品【0-(i-1)】中,背包容量为 j 的情况下的最大价值。 + for (int i = 1; i <= length; i++) { // + for (int j = 1; j <= capacity; j++) { + if (j >= weight[i-1]) { + // 当前物品重量小于等于背包容量时,考虑放入当前物品 + // 完全背包二维数组的代码跟一维只有下面一个下标不同, + // 那就是“放i”这个选择,因为是可以重复放的,所以是dp[i] + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i-1]] + value[i-1]); + }else { + // 当前物品重量大于背包容量,无法放入,维持前一个状态 + dp[i][j] = dp[i - 1][j]; + } + } + } + + return dp[length][capacity]; + } + + public int absoluteBeiBaoOneD(int[] weight, int[] value,int capacity) { + + int length = weight.length; + int[] dp = new int[capacity + 1]; + + // 初始化动态规划数组 + // dp[i][j] 表示在前 i 个物品【0-(i-1)】中,背包容量为 j 的情况下的最大价值。 + // dp[j] 表示前i个物品中,背包容量为j的最大价值 + for (int i = 1; i <= length; i++) { // + for (int j = weight[i - 1]; j <= capacity; j++) { + dp[j] = Math.max(dp[j], dp[j - weight[i - 1]] + value[i - 1]); + } + } + return dp[capacity]; + } + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/BeiBao.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/BeiBao.java new file mode 100644 index 0000000..2c69c94 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/BeiBao.java @@ -0,0 +1,205 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/12 16:53 + * @注释 + */ +public class BeiBao { + + @Test + public void main() { +// +// new Thread(() -> { +// try { +// Thread.sleep(1000); +// } catch (InterruptedException e) { +// throw new RuntimeException(e); +// } +// }).start(); +// +// new Thread(() -> { +// +// }).start(); +// +// +// String a = "a"; +// +// String b = new String("a"); +// +// System.out.println(a == b); + int[] weight = {1,3,4}; + int[] value = {15,20,30}; + int bagSize = 4; + new Solution2().packageProblem(weight, value, bagSize); + } + + class Solution{ + + /** + * + * + *
+ * + * + * @param weights 每个物品的重量 + * @param values 每个物品的价值 + * @param carryNumber 允许携带的数量 + * @return 价值 + */ + public int packageProblem(int[] weights, int[] values, int carryNumber) { + /** + * 重量 价值 + * 物品0 1 15 + * 物品1 3 20 + * 物品2 4 30 + */ + // dp[i][j] i表示携带的产品,j表示容量为j的背包 dp[i][j]为从0-i个产品里取,最大的价值 + // 1. 不放物品i的最大价值,dp[i][j] = dp[i-1][j] 不放物品i,所以i不占重量,所以不用-weight[i] + // 2. 放物品i的最大价值 dp[i-1][j-weight[i]] + value[i] 如果放了物品i,那最大价值就 不放物品i的最大价值+物品i的价值(j-weight[i] 表示放i需要腾出来空间) + // dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,注意是不放物品i,所以要减去weight[i] + // dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 不放物品的价值 加上i物品的价值 + + // 初始化:如果容量为0,最大价值都为0;如果容量为1、2、3,只能放物品0的时候,最大价值都是15 + int goodsNumber = weights.length; + int[][] dp = new int[goodsNumber][carryNumber + 1]; + // 把第0个物品进行初始化,前提是能够放入第0个物品 + for (int i = weights[0]; i < carryNumber + 1; i++) { + dp[0][i] = values[0]; + } + + /** + * 先遍历物品,再遍历背包 + */ + for (int i = 1; i < goodsNumber; i++) { + for (int j = 1; j < carryNumber + 1; j++) { + if (weights[i] > j) { + // 物品i放不进背包容量为j的背包 + dp[i][j] = dp[i - 1][j]; + }else { + // 能放进去 + dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]); + } + } + } + + + + // 打印dp数组 + for (int i = 0; i < goodsNumber; i++) { + for (int j = 0; j <= carryNumber; j++) { + System.out.print(dp[i][j] + "\t"); + } + System.out.println("\n"); + } + + return dp[weights.length - 1][carryNumber]; + } + + } + + + class Solution1{ + + /** + * dp[i][j] i表示商品,j表示空间 dp[i][j]表示 容量为j为包裹,从0-i个商品中取得最大值 + * + * 初始化 + * 0 1 2 3 4 5 包容量 + * 物品0 0 0 2 2 2 2 + * 物品1 0 + * 物品2 0 + * + * dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。 + * + * @param weights 物品的重量 + * @param values 物品的价值 + * @param carryNumber 可以携带的数量 + * @return + */ + public int packageProblem(int[] weights, int[] values, int carryNumber) { + int length = weights.length; + int[][] dp = new int[length][carryNumber + 1]; + for (int i = 0; i < length; i++) { + dp[i][0] = 0; + } + for (int i = weights[0]; i <= carryNumber; i++) { + dp[0][i] = values[0]; + } + + // 如果i 不放东西 dp[i][j] = dp[i-1][j] + // 如果i 放东西 dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]-value[i]) + + // i为商品;j为容量。 + for (int i = 1; i < length; i++) { + for (int j = 1; j <= carryNumber; j++) { + if (weights[i] > j) { + // 重量太大,放不进去 + dp[i][j] = dp[i - 1][j]; + }else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]); + } + } + } + + + return dp[length - 1][carryNumber]; + + } + } + + class Solution2{ + + /** + * + * dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。 + * dp[j] 表示容量为j的背包的最大价值总和 + * + * 初始化 + * 0 1 2 3 4 5 包容量 + * 物品0 0 0 2 2 2 2 + * 物品1 0 + * 物品2 0 + * + * 不放这个商品 那价值不变,还是dp[j] + * dp[j] = max(dp[j] , dp[j-weight[i]]+value[i]]) + * + * @param weights 物品的重量 + * @param values 物品的价值 + * @param carryNumber 可以携带的数量 + * @return + */ + public int packageProblem(int[] weights, int[] values, int carryNumber) { + int length = weights.length; + int[] dp = new int[carryNumber + 1]; + + // 不放这个商品 那价值不变,还是dp[j] + // dp[j] = max(dp[j] , dp[j-weight[i]]+value[i]]) + + // i为商品;j为容量。 + for(int i = 0; i < length; i++) { // 遍历物品 + for(int j = carryNumber ;j >= weights[i]; j--) { // 遍历背包容量 + dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]); + } + /** + * 倒序遍历是为了保证物品i只被放入一次!。但如果一旦正序遍历了,那么物品0就会被重复加入多次! + * + * 举一个例子:物品0的重量weight[0] = 1,价值value[0] = 15 + * 如果正序遍历 + * dp[1] = dp[1 - weight[0]] + value[0] = 15 + * dp[2] = dp[2 - weight[0]] + value[0] = 30 + * + * 此时dp[2]就已经是30了,意味着物品0,被放入了两次,所以不能正序遍历。 + */ + } + + + return dp[carryNumber]; + + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/KaMa47.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/KaMa47.java new file mode 100644 index 0000000..50b1cfb --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/KaMa47.java @@ -0,0 +1,56 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/27 12:45 + * @注释 + */ +public class KaMa47 { + + @Test + public void test() + { + + int i = new Solution().plt(3, 2); + System.out.println(i); + } + + /* https://kamacoder.com/problempage.php?pid=1067 + */ + class Solution{ + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int capacity = scanner.nextInt(); + int m = scanner.nextInt(); + System.out.println(plt(capacity, m)); + } + + /** + * @param capacity 需要n阶 + * @param m 每一步可以走几个 + * @return + */ + public static int plt(int capacity, int m) { + + // 排列 + int[] dp = new int[capacity + 1]; + + dp[0] = 1; + for (int j = 0; j <= capacity; j++) { + for (int i = 1; i <= m; i++) { + if (j >= i) { + dp[j] += dp[j - i]; + } + } + } + return dp[capacity]; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama100.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama100.java new file mode 100644 index 0000000..5a400ca --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama100.java @@ -0,0 +1,67 @@ +package cn.whaifree.leetCode.Graph; + +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/23 11:29 + * @注释 + */ +public class Kama100 { + + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int a = scanner.nextInt(); + int b = scanner.nextInt(); + int[][] input = new int[a][b]; + boolean[][] visited = new boolean[a][b]; + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + input[i][j] = scanner.nextInt(); + } + } + + int max = 0; + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + if (!visited[i][j] && input[i][j] == 1) { + visited[i][j] = true; + int in = in(input, visited, i, j) + 1; // 注意这里也是一小块陆地 + max = Math.max(max, in); + } + } + } + System.out.println(max); + + + } + + static int[][] direct = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + /** + * 广度有限 用队列 + * - 深入搜索 用地柜 + * @param input + * @param visited + * @param x + * @param y + */ + public static int in(int[][] input, boolean[][] visited, int x, int y) { + int res = 0; + for (int i = 0; i < direct.length; i++) { + int nx = x + direct[i][0]; + int ny = y + direct[i][1]; + if (nx >= 0 && nx < input.length && ny >= 0 && ny < input[0].length + && !visited[nx][ny]) { + if (input[nx][ny] == 1) { + visited[nx][ny] = true; + res += 1; + res += in(input, visited, nx, ny); + } + } + } + return res; + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama101.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama101.java new file mode 100644 index 0000000..b82f538 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama101.java @@ -0,0 +1,85 @@ +package cn.whaifree.leetCode.Graph; + +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/23 12:00 + * @注释 + */ +public class Kama101 { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int a = scanner.nextInt(); + int b = scanner.nextInt(); + int[][] input = new int[a][b]; + boolean[][] visited = new boolean[a][b]; + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + input[i][j] = scanner.nextInt(); + } + } + + // 在边缘处进入,一旦为1才进入,边缘陆地全部进入 + for (int i = 0; i < a; i++) { + if (input[i][0] == 1) { + in(input, i, 0); + } + if (input[i][b - 1] == 1) { + in(input, i, b - 1); + } + } + + for (int j = 0; j < b; j++) { + if (input[0][j] == 1) { + in(input, 0, j); + } + if (input[a - 1][j] == 1) { + in(input, a - 1, j); + } + } + res = 0;// 重新开始计数 + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + if (input[i][j] == 1) { + in(input, i, j); + } + } + } + System.out.println(res); + } + + static int res = 0; + static int[][] direct = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + /** + * 广度有限 用队列 + * - 深入搜索 用地柜 + * + * + * 孤岛 所有单元格都不接触边缘的岛屿 + * + * 从周边找到陆地然后 通过 dfs或者bfs + * 将周边靠陆地且相邻的陆地都变成海洋, + * 然后再去重新遍历地图 统计此时还剩下的陆地就可以了。 + * @param input + + * @param x + * @param y + */ + public static void in(int[][] input, int x, int y) { + input[x][y] = 0; + res++; + for (int i = 0; i < direct.length; i++) { + int nx = x + direct[i][0]; + int ny = y + direct[i][1]; + if (nx >= 0 && nx < input.length && ny >= 0 && ny < input[0].length) { + if (input[nx][ny] == 1) { + in(input, nx, ny); + } + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama102.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama102.java new file mode 100644 index 0000000..3e0ca81 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama102.java @@ -0,0 +1,99 @@ +package cn.whaifree.leetCode.Graph; + +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/23 12:52 + * @注释 + */ +public class Kama102 { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int a = scanner.nextInt(); + int b = scanner.nextInt(); + int[][] input = new int[a][b]; + boolean[][] visited = new boolean[a][b]; + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + input[i][j] = scanner.nextInt(); + } + } + + // 在边缘处进入,一旦为1才进入,边缘陆地全部进入 + for (int i = 0; i < a; i++) { + if (input[i][0] == 1) { + in(input, i, 0); + } + if (input[i][b - 1] == 1) { + in(input, i, b - 1); + } + } + + for (int j = 0; j < b; j++) { + if (input[0][j] == 1) { + in(input, 0, j); + } + if (input[a - 1][j] == 1) { + in(input, a - 1, j); + } + } + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + if (input[i][j] == 1) { + input[i][j] = 0; // 孤岛沉没 + } else if (input[i][j] == 2) { + input[i][j] = 1; + } + } + } + for (int i = 0; i < input.length; i++) { + for (int j = 0; j < input[0].length; j++) { + System.out.print(input[i][j] + " "); + } + System.out.println(); + } + } + + /** + * 步骤一:深搜或者广搜将地图周边的 1 (陆地)全部改成 2 (特殊标记) + * + * 步骤二:将水域中间 1 (陆地)全部改成 水域(0) + * + * 步骤三:将之前标记的 2 改为 1 (陆地) + */ + + static int res = 0; + static int[][] direct = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + /** + * 广度有限 用队列 + * - 深入搜索 用地柜 + * + * + * 孤岛 所有单元格都不接触边缘的岛屿 + * + * 从周边找到陆地然后 通过 dfs或者bfs + * 将周边靠陆地且相邻的陆地都变成海洋, + * 然后再去重新遍历地图 统计此时还剩下的陆地就可以了。 + * @param input + + * @param x + * @param y + */ + public static void in(int[][] input, int x, int y) { + input[x][y] = 2; + res++; + for (int i = 0; i < direct.length; i++) { + int nx = x + direct[i][0]; + int ny = y + direct[i][1]; + if (nx >= 0 && nx < input.length && ny >= 0 && ny < input[0].length) { + if (input[nx][ny] == 1) { + in(input, nx, ny); + } + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama55.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama55.java new file mode 100644 index 0000000..3c7f93f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama55.java @@ -0,0 +1,57 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * 字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。 + * + * 例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。 + * + * 输入:输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。 + * + * 输出:输出共一行,为进行了右旋转操作后的字符串。 + */ +public class Kama55 { + + @Test + public void test() { + String s = "abcdefg"; + int k = 2; + String result = new Solution().reverse(s, k); + System.out.println(result); + } + + public static void main(String[] args) { + + } + + class Solution{ + + /** + * 逆转 + * abcde 2 + * cbaed 两个区间分别逆转 + * deabc 整体逆转 + * @param s + * @param target + * @return + */ + public String reverse(String s, int target) { + StringBuilder stringBuilder = new StringBuilder(s); + reverseString(stringBuilder, 0, target - 1); + reverseString(stringBuilder, target, stringBuilder.length() - 1); + reverseString(stringBuilder, 0, stringBuilder.length() - 1); + return stringBuilder.toString(); + } + + public void reverseString(StringBuilder stringBuilder,int start, int end) { + while (start < end) { + char tmp = stringBuilder.charAt(start); + stringBuilder.setCharAt(start, stringBuilder.charAt(end)); + stringBuilder.setCharAt(end, tmp); + start++; + end--; + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama99.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama99.java new file mode 100644 index 0000000..193effe --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama99.java @@ -0,0 +1,65 @@ +package cn.whaifree.leetCode.Graph; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/17 16:26 + * @注释 + */ +public class Kama99 { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int a = scanner.nextInt(); + int b = scanner.nextInt(); + int[][] input = new int[a][b]; + boolean[][] visited = new boolean[a][b]; + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + input[i][j] = scanner.nextInt(); + } + } + + int res = 0; + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + if (!visited[i][j] && input[i][j] == 1) { + // 没有走过的节点+为陆地(1) + res++; + method(input, visited, i, j); + } + } + } + System.out.println(res); + } + public static int method(int[][] input, boolean[][] looking, int x, int y) { + int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 表示四个方向 + + int res = 0; + int[] item = new int[]{x, y}; + looking[x][y] = true; + Deque queue = new LinkedList<>(); + queue.add(item); + while (!queue.isEmpty()) { + int[] pop = queue.pop(); + int x1 = pop[0]; + int y1 = pop[1]; + for (int i = 0; i < 4; i++) { + int nextX = x1 + dir[i][0]; + int nextY = y1 + dir[i][1]; + if (nextX >= 0 && nextX < input.length && nextY >= 0 && nextY < input[0].length) { + if (!looking[nextX][nextY] && input[nextX][nextY] == 1) { // 只有1才遍历,这样就可以保证只在小岛屿内 + // (下一次的节点)没有遍历过,并且为1, + queue.add(new int[]{nextX, nextY}); + looking[nextX][nextY] = true; // 进入队列就标志看过了 + } + } + } + } + return res; + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama99_2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama99_2.java new file mode 100644 index 0000000..c99b1e5 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/Kama99_2.java @@ -0,0 +1,62 @@ +package cn.whaifree.leetCode.Graph; + +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/19 16:44 + * @注释 + */ +public class Kama99_2 { + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + int m = sc.nextInt(); + int n = sc.nextInt(); + int[][] grid = new int[m][n]; + boolean[][] visited = new boolean[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + grid[i][j] = sc.nextInt(); + } + } + + int res = 0; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (!visited[i][j] && grid[i][j] == 1) { + res++; + visited[i][j] = true; + depth(grid, visited, i, j); + } + } + } + System.out.println(res); + } + + static int[][] direct = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; + public static void depth(int[][] map, boolean[][] visited, int x, int y) { + + // 深度优先 + for (int i = 0; i < 4; i++) { + int[] ints = direct[i]; + int nextX = x + ints[0]; + int nextY = y + ints[1]; + if (nextX < 0 || nextX >= map.length || nextY < 0 || nextY >= map[0].length) { + continue; + } + if (visited[nextX][nextY]) { // 访问过的不再访问 + continue; + } + if (map[nextX][nextY] == 1) { + visited[nextX][nextY] = true; + depth(map, visited, nextX, nextY); + } + } + } + + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/LCR/LCR001.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR001.java similarity index 100% rename from ForJdk17/src/main/java/cn/whaifree/LCR/LCR001.java rename to ForJdk17/src/main/java/cn/whaifree/leetCode/LCR001.java diff --git a/ForJdk17/src/main/java/cn/whaifree/LCR/LCR031.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR031.java similarity index 100% rename from ForJdk17/src/main/java/cn/whaifree/LCR/LCR031.java rename to ForJdk17/src/main/java/cn/whaifree/leetCode/LCR031.java diff --git a/ForJdk17/src/main/java/cn/whaifree/LCR/LCR089.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR089.java similarity index 100% rename from ForJdk17/src/main/java/cn/whaifree/LCR/LCR089.java rename to ForJdk17/src/main/java/cn/whaifree/leetCode/LCR089.java diff --git a/ForJdk17/src/main/java/cn/whaifree/LCR/LCR090.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR090.java similarity index 100% rename from ForJdk17/src/main/java/cn/whaifree/LCR/LCR090.java rename to ForJdk17/src/main/java/cn/whaifree/leetCode/LCR090.java diff --git a/ForJdk17/src/main/java/cn/whaifree/LCR/LCR106.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR106.java similarity index 100% rename from ForJdk17/src/main/java/cn/whaifree/LCR/LCR106.java rename to ForJdk17/src/main/java/cn/whaifree/leetCode/LCR106.java diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR119.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR119.java new file mode 100644 index 0000000..bfc63df --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR119.java @@ -0,0 +1,49 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.HashSet; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/15 16:37 + * @注释 + */ +public class LCR119 { + @Test + public void test() { + int[] nums = {100, 4, 200, 1, 3, 2}; + System.out.println(new Solution().longestConsecutive(nums)); + } + + class Solution { + public int longestConsecutive(int[] nums) { + HashSet set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + + int max = 0; + for (int num : nums) { + if (set.contains(num- 1)) { // 1 2 3 4 只要保证set里没有0 + continue; + } +// int base = num; +// int tmp = 0; +// while (set.contains(base++)) { +// tmp++; +// } +// max = Math.max(max, tmp); + + int maxnum = num; + while (set.contains(maxnum + 1)) { + maxnum++; + } + max = Math.max(max, maxnum - num + 1); + } + return max; + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/LCR/LCR155.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR155.java similarity index 100% rename from ForJdk17/src/main/java/cn/whaifree/LCR/LCR155.java rename to ForJdk17/src/main/java/cn/whaifree/leetCode/LCR155.java diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR181.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR181.java new file mode 100644 index 0000000..76fc207 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LCR181.java @@ -0,0 +1,46 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +public class LCR181 { + + + @Test + public void main() + { + Solution solution = new Solution(); + String s = solution.reverseMessage(" abx "); + System.out.println(s); + } + + class Solution { + public String reverseMessage(String message) { + String trim = message.trim(); + String[] split = trim.split("\s+"); + reverse(split); + StringBuilder stringBuilder = new StringBuilder(); + for (String s : split) { + if (s.isEmpty()) { + continue; + } + stringBuilder.append(s).append(" "); + } + if (!stringBuilder.isEmpty()) stringBuilder.deleteCharAt(stringBuilder.length() - 1); + return stringBuilder.toString(); + } + + public void reverse(String[] strings) { + int start = 0; + int end = strings.length - 1; + while (start < end) { + swap(strings, start++, end--); + } + } + + public void swap(String[] strings, int start, int end) { + String temp = strings[start]; + strings[start] = strings[end]; + strings[end] = temp; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode10.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode10.java new file mode 100644 index 0000000..28d1c84 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode10.java @@ -0,0 +1,39 @@ +package cn.whaifree.leetCode.String; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/5 11:36 + * @注释 + */ +public class LeetCode10 { + + class Solution { + public boolean isMatch(String s, String p) { + + char[] sChar = s.toCharArray(); + char[] pChar = p.toCharArray(); + /** + * dp[sIndex][pIndex]表示s字符串的前sIndex个字符是否和p字符串的前pIndex个字符完成正则表达式的匹配 + * + * 当p字符串的第pIndex个字符不为*时 + * if p第pIndex个字符与s的第sIndex个字符匹配 + * dp[sIndex][pIndex] = + * f[sIndex - 1][pIndex - 1](即:s的前sIndex - 1个字符和p的前pIndex-1个字符的匹配结果)。 + * 如果p第pIndex个字符与s的第sIndex个字符不匹配, + * 则结果为false; + * 当p字符串的第pIndex个字符为*时 + * 此时*前面的符号可以出现0次或任意次 + * - x出现0次 + * 此时结果为f[sIndex][pIndex - 2]。此时相当于删除了*以及x + * - x出现非0的任意次, 此时的结果为f[sIndex - 1][pIndex] && (p.charAt(pIndex - 2) == '.' || p.charAt(pIndex - 2) == s.charAt(sIndex - 1)); + * + */ + + + return false; + + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode100.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode100.java new file mode 100644 index 0000000..0f51758 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode100.java @@ -0,0 +1,81 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/23 19:56 + * @注释 + */ +public class LeetCode100 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1,2,1}); + TreeNode treeNode1 = TreeNode.constructTree(new Integer[]{1,1,2}); + treeNode1.printTree(); + treeNode.printTree(); + System.out.println(new Solution1().isSameTree(treeNode, treeNode1)); + + } + + class Solution { + public boolean isSameTree(TreeNode p, TreeNode q) { + if (p == null && q == null) { + return true; + } else if (p == null || q == null) { + return false; + } + // LinkedList能存null + Deque deque = new LinkedList<>(); + deque.add(p); + deque.add(q); + while (!deque.isEmpty()) { + // 防止只剩下一个元素,如果只剩下一个元素,那么一定是false + TreeNode BPop = deque.pop(); + TreeNode APop = deque.pop(); + if (BPop == null && APop == null) { + // 叶子节点,不需要加入左右子节点 + continue; + } else if (BPop != null && APop == null) { + return false; + } else if (BPop == null && APop != null) { + return false; + } else if (BPop.val != APop.val) { + return false; + } + + deque.add(BPop.right); + deque.add(APop.right); + deque.add(BPop.left); + deque.add(APop.left); + } + return true; + } + + } + class Solution1 { + public boolean isSameTree(TreeNode p, TreeNode q) { + + if (p == null && q == null) { + return true; + } else if (p == null && q != null) { + return false; + } else if (p != null && q == null) { + return false; + } else if (p.val != q.val) { + return false; + } + boolean sameTreeRight = isSameTree(p.right, q.right); + boolean sameTreeLeft = isSameTree(p.left, q.left); + return sameTreeLeft && sameTreeRight; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1005.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1005.java new file mode 100644 index 0000000..ad4bbba --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1005.java @@ -0,0 +1,113 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.stream.IntStream; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/27 11:42 + * @注释 + */ +public class LeetCode1005 { + + @Test + public void test() { + System.out.println(new Solution().largestSumAfterKNegations(new int[]{-2,5,0,2,-2}, 3)); + System.out.println(new Solution().largestSumAfterKNegations(new int[]{4,2,3}, 1)) + ; + + System.out.println(new Solution1().largestSumAfterKNegations(new int[]{-2,5,0,2,-2}, 3)); + System.out.println(new Solution1().largestSumAfterKNegations(new int[]{4,2,3}, 1)); + } + + + class Solution { + + /** + * 注意几个例子 + * 1. nums = [3,-1,0,2], k = 3 选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2] + * + * -2,5,1,2,-2 + * 按绝对值逆转 5 -2 2 -2 1 + * 每次遇到负数,变为相反数 + * // 剩下的k如果是奇数,就把最后一个逆转 + * + * @param nums + * @param k + * @return + */ + public int largestSumAfterKNegations(int[] nums, int k) { + // 按绝对值从大到小排序,对前k个负数进行相反数 + nums = IntStream.of(nums) + .boxed() + .sorted((o1, o2) -> Math.abs(o2) - Math.abs(o1)) + .mapToInt(Integer::intValue).toArray(); + + + for (int i = 0; i < nums.length; i++) { + if (k > 0 && nums[i] < 0) { + nums[i] = -nums[i]; + k--; + } + } + + // 此时还有k个没减去,k为偶数则不管,k为奇数就把最小那个变为正数 + if (k % 2 == 1) { + nums[nums.length-1] = -nums[nums.length-1]; + } + + + return Arrays.stream(nums).sum(); + } + } + + class Solution1 { + + /** + * 注意几个例子 + * 1. nums = [3,-1,0,2], k = 3 选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2] + * + * -2,5,1,2,-2 + * 排序 + * -2 -2 1 2 5 + * 逆转 + * 2 2 1 2 5 + * 将最下的数逆转,sum-min-min + * 2 2 -1 2 5 + * + * @param nums + * @param k + * @return + */ + public int largestSumAfterKNegations(int[] nums, int k) { + // 按绝对值从大到小排序,对前k个负数进行相反数 + Arrays.sort(nums); + + + int sum = 0; + int minValue = Integer.MAX_VALUE; + for (int i = 0; i < nums.length; i++) { + if (k > 0 && nums[i] < 0) { + nums[i] = -nums[i]; + k--; + } + sum += nums[i]; + minValue = Math.min(minValue, nums[i]); + } + + // 此时还有k个没减去,k为偶数则不管,k为奇数就把最小那个变为正数 + if (k % 2 == 1) { + // 减去在遍历过程中加的minValue部分和通过变换负数的部分 + return sum - minValue - minValue; + }else { + return sum; + } + + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode101.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode101.java new file mode 100644 index 0000000..47c3b53 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode101.java @@ -0,0 +1,91 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海104 + * @Date 2024/1/21 19:19 + * @注释 + */ +public class LeetCode101 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 2, 3, null,null, 3}); + treeNode.printTree(); + System.out.println(new Solution1().isSymmetric(treeNode)); + + } + + class Solution { + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + return compare(root.left, root.right); + } + + public boolean compare(TreeNode left, TreeNode right) { + // left.left 与 right.right递归 + // left.right 与 right.left递归 + if (left == null && right == null) { + return true; + } else if (left != null && right == null) { + return false; + } else if (left == null && right != null) { + return false; + } else if (left.val != right.val) { + return false; + } + + boolean outSite = compare(left.left, right.right); + boolean inSite = compare(left.right, right.left); + return outSite && inSite; + } + } + + class Solution1 { + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + + Deque deque = new LinkedList<>(); + deque.add(root.left); + deque.add(root.right); + while (!deque.isEmpty()) { + TreeNode left = deque.pop(); + TreeNode right = deque.pop(); + if (left == null && right == null) { + continue; + } +// else if (left == null && right != null) { +// return false; +// } else if (left != null && right == null) { +// return false; +// } else if (left.val != right.val) { +// return false; +// } + if (left == null || right == null || left.val != right.val) { + return false; + } + + deque.add(left.left); + deque.add(right.right); + deque.add(left.right); + deque.add(right.left); + + } + return true; + } + + + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode102.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode102.java new file mode 100644 index 0000000..0530400 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode102.java @@ -0,0 +1,90 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/16 20:37 + * @注释 + */ +public class LeetCode102 { + + + @Test + public void test() { + TreeNode root = TreeNode.constructTree(new Integer[]{3, 9, 20, null, null, 15, 7}); + root.printTree(); + System.out.println(new Solution1().levelOrder(root)); + } + + class Solution { + public List> levelOrder(TreeNode root) { + + List> res = new LinkedList<>(); + if (root == null) { + return res; + } + Deque queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + // 遍历本层的个数 + List e = new ArrayList<>(); + int size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode pop = queue.pop(); + e.add(pop.val); + if(pop.left!=null) queue.add(pop.left); + if(pop.right!=null) queue.add(pop.right); + } + res.add(e); + } + + return res; + } + } + + class Solution1 { + + List> res = new LinkedList<>(); + + /** + * 二叉树递归层次遍历 + * @param root + * @return + */ + public List> levelOrder(TreeNode root) { + + if (root == null) { + return res; + } + level(root, 0); + + return res; + } + + public void level(TreeNode root, int level) { + if (root == null) { + return; + } + List i = null; + if (res.size() <= level) { + i = new ArrayList<>(); + res.add(level, i); + } else { + i = res.get(level); + } + i.add(root.val); + + level(root.left, level + 1); + level(root.right, level + 1); + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode103.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode103.java new file mode 100644 index 0000000..ef75317 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode103.java @@ -0,0 +1,54 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 23:06 + * @注释 + */ +public class LeetCode103 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{3, 9, 20, 88, 99, 15, 7, 10, 5, 1}); + + List> lists = + new Solution().zigzagLevelOrder(treeNode); + for (List list : lists) { + System.out.println(list); + } + } + + class Solution { + List> res = new ArrayList<>(); + public List> zigzagLevelOrder(TreeNode root) { + if (root == null) { + return res; + } + level(root, 0, true); + return res; + } + + public void level(TreeNode root, int level, boolean leftIn) { + if (root == null) { + return; + } + if (level == res.size()) { + res.add(level, new ArrayList<>()); + } + if (leftIn) { + res.get(level).add(root.val); + } else { + res.get(level).add(0, root.val); + } + level(root.left, level + 1, !leftIn); + level(root.right, level + 1, !leftIn); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1035.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1035.java new file mode 100644 index 0000000..b0074d3 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1035.java @@ -0,0 +1,61 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/25 11:28 + * @注释 + */ +public class LeetCode1035 { + + @Test + public void test() + { + int[] nums1 = new int[]{1,3,7,1,7,5}; + int[] nums2 = new int[]{1,9,2,5,1}; + System.out.println(new Solution().maxUncrossedLines(nums1, nums2)); + } + + class Solution { + /** + * 不相交,就是挨个求nums1的子序列在nums中出现的次数 + * - 不用连续 + * - 子序列 + * + * dp[i][j] 表示 nums1从0-i-1,nums2从0-j-1,有几个相同的子序列 + * + * if nums1[i] == nums2[j] + * dp[i][j] = dp[i-1][j-1]+1 + * else + * dp[i][j] = dp[i-1][j-1] + * + * + * @param nums1 短的 + * @param nums2 长的 + * @return + */ + public int maxUncrossedLines(int[] nums1, int[] nums2) { + if (nums1.length > nums2.length) { + return maxUncrossedLines(nums2, nums1); + } + int[][] dp = new int[nums1.length + 1][nums2.length + 1]; + + for (int i = 1; i <= nums1.length; i++) { + for (int j = 1; j <= nums2.length; j++) { + if (nums1[i - 1] == nums2[j - 1]) { + // 对应位置相等,则从i-1 j-1的值+1 + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + // 对应的值不相等,则获取前面已经匹配的最大值 + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + return dp[nums1.length][nums2.length]; + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode104.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode104.java new file mode 100644 index 0000000..e29b14e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode104.java @@ -0,0 +1,99 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/21 20:05 + * @注释 + */ +public class LeetCode104 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 2, 3, null,null,null}); + treeNode.printTree(); + System.out.println(new Solution2().maxDepth(treeNode)); + } + + class Solution { + + int depth = 0; + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + level(root, 1); + return depth; + } + + public void level(TreeNode treeNode, int level) { + if (treeNode == null) { + return; + } + if (level > depth) { + depth = level; + } + if (treeNode.right != null) { + level(treeNode.right, level + 1); + } + if (treeNode.left != null) { + level(treeNode.left, level + 1); + } + + } + } + + class Solution2{ + + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + return level(root); + } + + public int level(TreeNode treeNode) { + if (treeNode == null) { + return 0; + } + int left = level(treeNode.left) + 1; + int right = level(treeNode.right) + 1; + return Math.max(left, right); + } + } + + class Solution1 { + + + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + int depth = 0; + // 右视图 + Deque deque = new ArrayDeque<>(); + deque.add(root); + while (!deque.isEmpty()) { + int size = deque.size(); + for (int i = 0; i < size; i++) { + TreeNode pop = deque.pop(); + if (pop.left != null) { + deque.add(pop.left); + } + if (pop.right != null) { + deque.add(pop.right); + } + } + depth++; + } + return depth; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1047.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1047.java new file mode 100644 index 0000000..63a180b --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1047.java @@ -0,0 +1,64 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.LinkedList; +import java.util.function.Consumer; + +public class LeetCode1047 { + + @Test + public void test() { + System.out.println(new Solution1().removeDuplicates("adff")); + } + + class Solution { + public String removeDuplicates(String s) { + Deque stack = new ArrayDeque<>(); + char[] chars = s.toCharArray(); + for (char aChar : chars) { + // 入栈前判断第一个是不是相同的 + if (!stack.isEmpty() && stack.peek() == aChar) { + stack.pop(); + }else { + stack.push(aChar); + } + + } + + char[] ans = new char[stack.size()]; + for (int i = stack.size() - 1; i >=0; i--) { + ans[i] = stack.pop(); + } + + return new String(ans); + } + } + + class Solution1 { + /** + * stringBuilder也能作为栈使用 + */ + public String removeDuplicates(String s) { + // 将StringBuilder作为栈 abbacd + StringBuilder res = new StringBuilder(); + + int top = -1; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (res.length() != 0 && c == res.charAt(top)) { + res.deleteCharAt(top); + top--; + } else { + res.append(c); + top++; + } + } + + return res.toString(); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1049.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1049.java new file mode 100644 index 0000000..7967f09 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1049.java @@ -0,0 +1,114 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/18 14:31 + * @注释 + */ +public class LeetCode1049 { + + @Test + public void test() { + int[] stones = {1,2}; + int result = new Solution1().lastStoneWeightII(stones); + System.out.println(result); + } + + class Solution { + /** + * 背包容量为half,让其尽可能装满,除非装不下了。到装不下了,这一部分已经装入的就是拿来碰撞的。剩下就是sum-dp[half]-dp[half] + * + * 目标就是让石头的总价值分为两部分 + * + * 转换为背包问题 + * + * dp[j] 表示 容量为j的背包最多能够容纳多少价值的物品 + * - 物品i的价值 为 stones[i] + * - 物品i的重量 为 stones[i] + * + * 1 <= stones.length <= 30 + * 1 <= stones[i] <= 100 + * 初始化为store[half] + * + * + * 递推公式 dp[j] = Math.max(dp[j],dp[j-weight[i]]+value[i]) + * 分成两堆石头,一堆石头的总重量是dp[half],另一堆就是sum - dp[half]。 + * + * @param stones + * @return + */ + public int lastStoneWeightII(int[] stones) { + int sum = 0; + for (int stone : stones) { + sum += stone; + } + + int half = sum / 2; + int[] dp = new int[half + 1]; + for (int i = 0; i < stones.length; i++) { + for (int j = half; j >= stones[i]; j--) { // 确保背包能够放下 + dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]); + } + } + + // dp[half] 是要被消灭的,那两个部分的消灭就*2 + return sum - dp[half] * 2; + } + } + + class Solution1 { + /** + * half = sum/2 + * + * + * dp[i][j] 表示 放入i后,容量为j的背包的最大价值 + * + * 1. 放入i dp[i][j] = dp[i-1][j-weight[i]]+value[i] + * 2. 不放入i dp[i][j] = dp[i-1][j] + * + * 2 4 1 1 target=4 + * + * 0 1 2 3 4 + * 0 0 0 2 2 2 + * 1 0 0 2 2 2 + * 2 0 1 3 3 3 + * 3 0 1 4 4 4 + * + * @param stones + * @return + */ + public int lastStoneWeightII(int[] stones) { + int sum = 0; + for (int stone : stones) { + sum += stone; + } + // 计算所有石头的总重量,并将其的一半作为目标重量 + int half = sum / 2; + + int length = stones.length; + int[][] dp = new int[length][half + 1]; + + for (int i = stones[0]; i <= half; i++) { + dp[0][i] = stones[0]; + } + for (int i = 1; i < length; i++) { + for (int j = 1; j <= half ; j++) { + if (j < stones[i]) { + // 放不下 就不放了,价值为i-1物品的最大价值 + // 当前石头重量大于目标重量,无法放入,价值等于前i-1个石头的最大价值 + dp[i][j] = dp[i - 1][j]; + }else { + // 取放入和不放入当前石头两种情况中的最大价值 + dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - stones[i]] + stones[i]); + } + } + } + + // 返回石头总重量减去最接近目标重量的那堆石头的两倍重量 + return sum - dp[length - 1][half] * 2; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode105.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode105.java new file mode 100644 index 0000000..2cbd55a --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode105.java @@ -0,0 +1,87 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/27 13:34 + * @注释 + */ +public class LeetCode105 { + + @Test + public void test() { + TreeNode.constructTree(new Integer[]{3,9,20,1,null,15,7}); + // 9 3 20 7 15 + // 20 3 7 9 15 + // 20 7 3 15 9 + + + new Solution().buildTree(new int[]{3,9,1,20,15,7}, new int[]{1,9,3,15,20,7}).printTree(); + + } + + class Solution { + Map map = new HashMap<>(); + public TreeNode buildTree(int[] preorder, int[] inorder) { + for (int i = 0; i < inorder.length; i++) { + map.put(inorder[i], i); + } + return build(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1); + } + + public TreeNode build( + int[] preorder, + int preorderStart, + int preorderEnd, + int[] inorder, + int inorderStart, + int inorderEnd + ) { + if (preorderStart > preorderEnd || inorderStart > inorderEnd) { + return null; + } + int value = preorder[preorderStart]; + Integer indexInInorder = map.get(value); + TreeNode node = new TreeNode(value); + // 左边的个数就是index的InInorderNumber + + //只要有左边节点数量,其他都好算 + int leftChildNumber = indexInInorder - inorderStart; + + // 前序 start的下一个 ~ start+左边的数量 + // 中序 start ~ start+左边的数量-1(不包含index) + node.left = build( + preorder, + preorderStart + 1, + preorderStart + leftChildNumber, + inorder, + inorderStart, + inorderStart + leftChildNumber - 1 + ); + + //3 9 1 20 15 7 + //1 9 3 15 20 7 + + // 前序 start+左边的数量+1(index) ~ end + // 中序 左边的数量+1(index) ~ end + node.right = build( + preorder, + preorderStart + leftChildNumber + 1, + preorderEnd, + inorder, + indexInInorder + 1, + inorderEnd); + + return node; + + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode106.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode106.java new file mode 100644 index 0000000..1066ae4 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode106.java @@ -0,0 +1,90 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/25 21:29 + * @注释 + */ +public class LeetCode106 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{3,9,20,null,null,15,7}); + // 9 3 20 7 15 + // 20 3 7 9 15 + // 20 7 3 15 9 + + //9,3,15,20,7 + //9,15,7,20,3 + new Solution().buildTree(new int[]{9,3,15,20,7}, new int[]{9,15,7,20,3}).printTree(); + + } + + class Solution { + Map map = new HashMap(); + public TreeNode buildTree(int[] inorder, int[] postorder) { + if (inorder.length == 0) { + return null; + } + for (int i = 0; i < inorder.length; i++) { + map.put(inorder[i], i); + } + return circle(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1); + + } + + public TreeNode circle( + int[] inorder, + int inorderStart, + int inorderEnd, + int[] postorder, + int posterStart, + int posterEnd + ) { + if (posterEnd < posterStart || inorderStart > inorderEnd) { + return null; + } + int lastValue = postorder[posterEnd]; + TreeNode root = new TreeNode(lastValue); + + // 中序中的下标 + Integer index = map.get(lastValue); + + // 左字树的个数 + + int leftChileNumber = index - inorderStart; + // 中序 start ~ start+leftnumber(即index) + // 后序 start ~ start+左边的树 + root.left = circle( + inorder, + inorderStart, + index - 1, + postorder, + posterStart, + posterStart + leftChileNumber - 1); + // 中序 index+1 ~ end + // 后序 start+left ~ end-1(中序节点) + root.right = circle( + inorder, + index + 1, + inorderEnd, postorder, + posterStart + leftChileNumber, + posterEnd - 1); + return root; + } + } + + + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode107.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode107.java new file mode 100644 index 0000000..22019ca --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode107.java @@ -0,0 +1,86 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/17 14:50 + * @注释 + */ +public class LeetCode107 { + + @Test + public void test() { + TreeNode root = TreeNode.constructTree(new Integer[]{3,9,20,null,null,15,7}); + root.printTree(); + + System.out.println(new Solution1().levelOrderBottom(root)); + } + class Solution { + public List> levelOrderBottom(TreeNode root) { + List> res = new LinkedList<>(); + if (root == null) { + return res; + } + Deque queue = new LinkedList<>(); + + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + List e = new LinkedList<>(); + for (int i = 0; i < size; i++) { + TreeNode pop = queue.pop(); + e.add(pop.val); + if (pop.left != null) { + queue.add(pop.left); + } + if (pop.right != null) { + queue.add(pop.right); + } + } + // 每次都采用头插法 + res.add(0,e); + } + return res; + } + } + + class Solution1 { + + List> res = new LinkedList<>(); + + /** + * 二叉树递归层次遍历 + * @param root + * @return + */ + public List> levelOrderBottom(TreeNode root) { + + if (root == null) { + return res; + } + level(root, 0); + Collections.reverse(res); + return res; + } + + public void level(TreeNode root, int level) { + if (root == null) { + return; + } + int size = res.size(); + if (size <= level) { + res.add(new ArrayList<>()); + } + res.get(level).add(root.val); + level(root.left, level + 1); + level(root.right, level + 1); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode108.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode108.java new file mode 100644 index 0000000..b7c73c2 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode108.java @@ -0,0 +1,40 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/31 18:56 + * @注释 + */ +public class LeetCode108 { + + @Test + public void test() { + new Solution().sortedArrayToBST(new int[]{1, 2, 3, 4, 5, 6, 7, 8}).printTree(); + } + + class Solution { + public TreeNode sortedArrayToBST(int[] nums) { + return construct(nums, 0, nums.length - 1); + } + + public TreeNode construct(int[] nums, int start, int end) { + if (start > end) { + return null; + } + int middle = (end + start) / 2; + int num = nums[middle]; + TreeNode root = new TreeNode(num); + root.left = construct(nums, start, middle - 1); + root.right = construct(nums, middle + 1, end); + return root; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode110.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode110.java new file mode 100644 index 0000000..bcfb6ae --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode110.java @@ -0,0 +1,48 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/21 20:36 + * @注释 + */ +public class LeetCode110 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1,2,2,3,null,null,3,4,null,null,4}); + treeNode.printTree(); + System.out.println(new Solution().isBalanced(treeNode)); + } + + class Solution { + public boolean isBalanced(TreeNode root) { + return level(root)!=-1; + } + + public int level(TreeNode root) { + if (root == null) { + return 0; + } + int leftHeight = level(root.left); + if (leftHeight == -1) { + return -1; + } + int rightDepth = level(root.right); + if (rightDepth == -1) { + return -1; + } + if (Math.abs(leftHeight - rightDepth) > 1) { + return -1; + } + return Math.max(leftHeight, rightDepth) + 1; +// return Math.abs(leftHeight - rightDepth) > 1 ? -1 : Math.max(leftHeight, rightDepth) + 1; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode111.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode111.java new file mode 100644 index 0000000..aa927ef --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode111.java @@ -0,0 +1,107 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/21 20:36 + * @注释 + */ +public class LeetCode111 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 2, 3, null,null,null,3}); + treeNode.printTree(); + System.out.println(new Solution2().minDepth(treeNode)); + } + + class Solution { + int minDepth = Integer.MAX_VALUE; + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + getDepth(root, 1); + return minDepth; + } + + void getDepth(TreeNode root, int level) { + if (root == null) { + return; + } + if (root.left != null) { + getDepth(root.left, level + 1); + } + if (root.right != null) { + getDepth(root.right, level + 1); + } + // 左右子树都为空,才表明已经到底部了 + if (root.left == null && root.right == null && level < minDepth) { + minDepth = level; + } + } + } + + class Solution1 { + public int minDepth(TreeNode root) { + return getDepth(root); + } + + int getDepth(TreeNode root) { + if (root == null) { + return 0; + } + int right = getDepth(root.right) ; + int left = getDepth(root.left) ; + if (root.left == null && root.right != null) { + return right + 1; + } + if (root.right == null && root.left != null) { + return left + 1; + } + + return 1 + Math.min(right, left); + } + } + + + class Solution2 { + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + int depth = 0; + + // 右视图 + Deque deque = new ArrayDeque<>(); + deque.add(root); + while (!deque.isEmpty()) { + int size = deque.size(); + depth++; + for (int i = 0; i < size; i++) { + TreeNode pop = deque.pop(); + if (pop.left != null) { + deque.add(pop.left); + } + if (pop.right != null) { + deque.add(pop.right); + } + if (pop.right == null && pop.left == null) { + // 从上到下第一个双节点非空就是输出 + return depth; + } + } + + } + return 0; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode112.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode112.java new file mode 100644 index 0000000..bdb65e1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode112.java @@ -0,0 +1,79 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/24 20:59 + * @注释 + */ +public class LeetCode112 { + + @Test + public void test( + ) { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{5,4,8,11,null,13,4,7,2,null,null,null,1}); + treeNode.printTree(); + System.out.println(new Solution1().hasPathSum(treeNode, 22)); + } + + class Solution { + public boolean hasPathSum(TreeNode root, int targetSum) { + return level(root, 0, targetSum); + } + + public boolean level(TreeNode treeNode,int sum,int targetSum) { + if (treeNode == null) { + return false; + } + sum += treeNode.val; + // 最后一个必须是叶子节点 + if (treeNode.left == null && treeNode.right == null && sum == targetSum) { + return true; + } + boolean left = level(treeNode.left, sum, targetSum); + boolean right = level(treeNode.right, sum, targetSum); + return left || right; + } + } + + class Solution1 { + + /** + * 使用队列 + * @param root + * @param targetSum + * @return + */ + public boolean hasPathSum(TreeNode root, int targetSum) { + if (root == null) { + return false; + } + + Deque queue = new java.util.ArrayDeque<>(); + queue.add(root); + queue.add(root.val); + while (!queue.isEmpty()) { + TreeNode pop = (TreeNode) queue.pop(); + Integer value = (Integer) queue.pop(); + if (pop.right == null && pop.left == null && value == targetSum) { + return true; + } + if (pop.right != null) { + queue.add(pop.right); + queue.add(value + pop.right.val); + } + if (pop.left != null) { + queue.add(pop.left); + queue.add(value + pop.left.val); + } + } + return false; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode113.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode113.java new file mode 100644 index 0000000..78761f3 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode113.java @@ -0,0 +1,62 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/24 21:30 + * @注释 + */ +public class LeetCode113 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{5,4,8,null,4}); + treeNode.printTree(); + System.out.println(new Solution().pathSum(treeNode, 13)); + } + + class Solution { + List> res = new ArrayList<>(); + public List> pathSum(TreeNode root, int targetSum) { + if (root == null) { + return res; + } + level(root, targetSum, new ArrayList<>()); + return res; + } + + + /** + * + * @param root 节点 + * @param needSum 还需要的数 + * @param nowHasPath 记录已经走过的路,也用于回退 + */ + public void level(TreeNode root, int needSum,ArrayList nowHasPath) { + if (root == null) { + return; + } + nowHasPath.add(root.val); + if (root.left == null && root.right == null && root.val == needSum) { + res.add(new ArrayList<>(nowHasPath)); + // 回退全部交给上一次递归 + } + if (root.left != null) { + level(root.left, needSum - root.val, nowHasPath); + nowHasPath.remove(nowHasPath.size() - 1); + } + if (root.right != null) { + level(root.right, needSum - root.val, nowHasPath); + nowHasPath.remove(nowHasPath.size() - 1); + } + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode114.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode114.java new file mode 100644 index 0000000..76a57fc --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode114.java @@ -0,0 +1,92 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/23 17:31 + * @注释 + */ +public class LeetCode114 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{0, 1, 2, 3, 4, 5, 6}); + new Solution().flatten(treeNode); + treeNode.printTree(); + } + + + class Solution { + public void flatten(TreeNode root) { + if (root == null) { + return; + } + + Deque deque = new LinkedList<>(); + deque.push(root); + TreeNode tmp = root; + while (!deque.isEmpty()) { + TreeNode pop = deque.pop(); + if (pop != null) { + if (pop.right != null) { + deque.push(pop.right); + } + if (pop.left != null) { + deque.push(pop.left); + } + deque.push(pop); + deque.push(null); + }else { + TreeNode nextPop = deque.pop(); + if (nextPop != tmp) { + tmp.right = nextPop; + tmp.left = null; + tmp = tmp.right; + } + } + } + } + } + + @Test + public void test2() { + TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{0, 1, 2, 3, 4, 5, 6}); + new Solution2().flatten(treeNode); + treeNode.printTree(); + } + + class Solution2 { + public void flatten(TreeNode root) { + + + + if (root == null) { + return; + } + subFlatten(root); + } + + public TreeNode subFlatten(TreeNode root) { + TreeNode left = root.left; + TreeNode right = root.right; + TreeNode tmp = root; + root.left = null; + if (left != null) { + root.right = left; + tmp = subFlatten(left); // tmp会返回一节的最后一个尾巴节点 + } + if (right != null) { + tmp.right = right; // 把前面的right拿过来再往下 + tmp = subFlatten(right); + } + return tmp; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1143.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1143.java new file mode 100644 index 0000000..942e279 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode1143.java @@ -0,0 +1,52 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/24 12:00 + * @注释 + */ +public class LeetCode1143 { + + @Test + public void test() { + Solution solution = new Solution(); + int res = solution.longestCommonSubsequence("bsbininm","jmjkbkjkv" ); + System.out.println(res); + } + + class Solution { + public int longestCommonSubsequence(String text1, String text2) { + + // 公共子序列 dp[len1+1][len2+1] + // dp[i][j] 表示 text1的前i-1与text2的前j-1中有多长的公共子序列长度 + // dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j] + // if text1[i]==text2[i] + // + // + int len1 = text1.length(); + int len2 = text2.length(); + + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 1; i <= len1; i++) { + for (int j = 1; j <= len2; j++) { + // 如果相等 + if (text1.charAt(i - 1) == text2.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1] + 1; + //dp[i][j] = Math.max(dp[i][j - 1] + 1, dp[i][j]); + } else { + dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]); + // dp[i][j] = Math.max(dp[i - 1][j - 1], Math.max(dp[i - 1][j], dp[i][j - 1])); + } + + } + } + + return dp[len1][len2]; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode115.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode115.java new file mode 100644 index 0000000..0f96c8d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode115.java @@ -0,0 +1,67 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/26 11:44 + * @注释 + */ +public class LeetCode115 { + @Test + public void test() + { + Solution solution = new Solution(); + System.out.println(solution.numDistinct("babgbag", "bag")); + } + + class Solution { + public int numDistinct(String s, String t) { + /** + * dp[i][j] 以i-1为 结尾的 s子序列 中出现以j-1为 结尾的 t的个数为dp[i][j] + * + * '' b a g + * '' 1 0 0 0 + * b 1 1 0 0 + * a 1 1 1 0 + * e 1 1 1 0 + * g 1 1 1 1 + * g 1 1 1 2 + * + * if s[i]==t[j] + * 1. 用s[i - 1]来匹配 dp[i - 1][j - 1] bagg和bag t匹配到s的第二个g时,使用第一个g + * 2. 不用第s[i - 1]来匹配 dp[i - 1][j] bagg和bag t匹配到s的第二个g时,不使用第一个g + * dp[i][j] = dp[i-1][j-1]+dp[i - 1][j]; + * else + * 不用s[i - 1]来匹配,模拟s中删除了这个元素 + * dp[i][j] = dp[i - 1][j]; + * + */ + + char[] sChar = s.toCharArray(); + char[] tChar = t.toCharArray(); + int[][] dp = new int[sChar.length + 1][tChar.length + 1]; + for (int i = 0; i < sChar.length; i++) { + dp[i][0] = 1; + } + for (int i = 1; i <= sChar.length; i++) { + for (int j = 1; j <= tChar.length; j++) { + if (sChar[i - 1] == tChar[j - 1]) { + // 如果相同 + // 使用i-1进行匹配 dp[i - 1][j - 1] bagg和bag t匹配到s的第二个g时,使用第一个g + // 不用第s[i - 1]来匹配 dp[i - 1][j] bagg和bag t匹配到s的第二个g时,不使用第一个g + dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; + } else { + // 不用s[i - 1]来匹配 + dp[i][j] = dp[i - 1][j]; + } + } + } + return dp[sChar.length][tChar.length]; + } + } + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode116.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode116.java new file mode 100644 index 0000000..156b393 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode116.java @@ -0,0 +1,115 @@ +package cn.whaifree.leetCode.Tree; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.Queue; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/18 16:11 + * @注释 + */ +public class LeetCode116 { + + 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; + } + + public void setLeft(Node left) { + this.left = left; + } + + public void setRight(Node right) { + this.right = right; + } + }; + + @Test + public void test() { + Node node = new Node(1); + node.left = new Node(2); + node.right = new Node(3); + node.left.left = new Node(4); + node.left.right = new Node(5); + node.right.left = new Node(6); + node.right.right = new Node(7); + System.out.println(new Solution1().connect(node)); + } + + class Solution { + + public Node connect(Node root) { + if (root == null) { + return null; + } + + Deque queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + + int size = queue.size(); + for (int i = 0; i < size; i++) { + Node pop = queue.pop(); + + // 防止把下一层的节点赋值为next + if (i < size - 1) { + pop.next = queue.peek(); + } + + if (pop.left != null) { + queue.add(pop.left); + } + if (pop.right != null) { + queue.add(pop.right); + } + } + } + return root; + + } + } + + class Solution1 { + + /** + * 递归方法 + * @param root + * @return + */ + public Node connect(Node root) { + if (root == null) { + return null; + } + circle(root); + return root; + } + + void circle(Node root) { + if (root == null) { + return; + } + if (root.left!=null) root.left.next = root.right == null ? null : root.right; + if (root.right!=null) root.right.next = root.next == null ? null : root.next.left; + circle(root.left); + circle(root.right); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode117.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode117.java new file mode 100644 index 0000000..7c7ce78 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode117.java @@ -0,0 +1,103 @@ +package cn.whaifree.leetCode.Tree; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/15 11:16 + * @注释 + */ +public class LeetCode117 { + + 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; + } + } + + @Test + public void test() { + Node root = new Node(1); + root.left = new Node(2); + root.right = new Node(3); + root.left.left = new Node(4); + root.left.right = new Node(5); + root.right.right = new Node(7); + root = new Solution1().connect(root); + System.out.println(root); + } + + class Solution { + + List levelHead = new ArrayList<>(); + + public Node connect(Node root) { + level(root, 0); + return root; + } + + public void level(Node root, int level) { + if (root == null) { + return; + } + + if (levelHead.size() > level) { + root.next = levelHead.get(level); + levelHead.set(level, root); + }else { + levelHead.add(level, root); + } + level(root.right, level + 1); + level(root.left, level + 1); + } + } + + + class Solution1 { + public Node connect(Node root) { + + if (root == null) { + return null; + } + Deque queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + Node nodeIndex = null; + // 遍历这一层 + for (int i = 0; i < size; i++) { + Node pop = queue.pop(); + pop.next = nodeIndex; + nodeIndex = pop; + if (pop.right != null) { + queue.add(pop.right); + } + if (pop.left != null) { + queue.add(pop.left); + } + } + } + return root; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode12.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode12.java new file mode 100644 index 0000000..c1090ed --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode12.java @@ -0,0 +1,92 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/18 21:43 + * @注释 + */ +public class LeetCode12 { + class Solution1 { + int[] nums = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + String[] romans = new String[]{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; + public String intToRoman(int num) { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < nums.length; i++) { + int v = nums[i]; + String c = romans[i]; + while (num >= v) { + num -= v; + stringBuilder.append(c); + } + if (num == 0) { // 效率 + break; + } + } + return stringBuilder.toString(); + } + } + class Solution { + static Map map = new HashMap<>(); + + static { + map.put(1,"I"); + map.put(2,"II"); + map.put(3,"III"); + map.put(4,"IV"); + map.put(5,"V"); + map.put(6,"VI"); + map.put(7,"VII"); + map.put(8,"VIII"); + map.put(9,"IX"); + map.put(10,"X"); + map.put(20,"XX"); + map.put(30,"XXX"); + map.put(40,"XL"); + map.put(50,"L"); + map.put(60,"LX"); + map.put(70,"LXX"); + map.put(80,"LXXX"); + map.put(90,"XC"); + map.put(100,"C"); + map.put(200,"CC"); + map.put(300,"CCC"); + map.put(400,"CD"); + map.put(500,"D"); + map.put(600,"DC"); + map.put(700,"DCC"); + map.put(800,"DCCC"); + map.put(900,"CM"); + map.put(1000,"M"); + map.put(2000,"MM"); + map.put(3000,"MMM"); + } + public String intToRoman(int num) { + + + StringBuilder sb = new StringBuilder(); + String x = String.valueOf(num); + for (int i = 0; i < x.length(); i++) { + char c = x.charAt(i); + if (c == '0') { + continue; + } + int v = (int) ((c - '0') * Math.pow(10, x.length() - i - 1)); + sb.append(map.get(v)); + } + return sb.toString(); + } + + } + + @Test + public void test() { + Solution solution = new Solution(); + System.out.println(solution.intToRoman(1994)); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode121.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode121.java new file mode 100644 index 0000000..638adf6 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode121.java @@ -0,0 +1,88 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/3 14:38 + * @注释 + */ +public class LeetCode121 { + + @Test + public void test() + { + + int[] prices = {7,1,5,3,6,4}; + System.out.println(new Solution1().maxProfit(prices)); + } + + + + class Solution { + + /** + * + * 只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。 + * + * dp[i][1]表示i天不持有股票的持有现金 + * dp[i][0]表示i天持有股票所有的现金 + * 第i天买入股票现金就是 -prices[i] + * + * 第i天有股票 1. 刚刚买入、2. 第i-1天就有 + * 第i天没有股票 2. 第i天卖出 2. 第i-1天就没有股票 + * + * dp[i][0] 持有股票 + * - i-1就持有股票,今天不卖 dp[i-1][0] + * - 买入股票 -今天的股价 -prices[i] + * - max + * dp[i][1] 无持有 + * - i-1 保持现状dp[i-1][1] + * - 卖出 prices[i] + dp[i-1][0] 价格+[i-1]天加持有的现金 + * - max + * dp[0][0] = -price[0] + * dp[0][1] = 0 + * + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + + if (prices.length == 1) { + return 0; + } + + int[] dp = new int[2]; + + dp[0] = -prices[0]; + dp[1] = 0; + for (int i = 0; i < prices.length; i++) { + // 持有股票 1. i-1就有 2. 刚刚买入 + dp[0] = Math.max(dp[0], -prices[i]); + // 无股票 2. i-1就无,2 刚刚卖出 + dp[1] = Math.max(dp[1], dp[0] + prices[i]); + } + return dp[1]; // 最后一天一定没有股票才能有最大利润 + } + } + class Solution1 { + /** + * 贪心 + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + + int min = Integer.MAX_VALUE; + int res = 0; + for (int i = 0; i < prices.length; i++) { + min = Math.min(min, prices[i]); + res = Math.max(res, prices[i] - min); + } + return res; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode122.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode122.java new file mode 100644 index 0000000..9f508ed --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode122.java @@ -0,0 +1,70 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/25 22:21 + * @注释 + */ +public class LeetCode122 { + + + @Test + public void test() { + + System.out.println(new Solution1().maxProfit(new int[]{7, 1, 5, 3, 6, 4})); + + System.out.println(new Solution1().maxProfit(new int[]{1})); + + + } + + class Solution { + + + /** + * 随时可以买卖,那么只要有跌的我都不要。 + * 上帝视角:只要涨我就全要 + * + * 7跌 1涨5 跌 4涨6 跌4 + * + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + + int maxProfit = 0; + for (int i = 0; i < prices.length; i++) { + if (i > 0 && prices[i] - prices[i - 1] > 0) { + maxProfit += prices[i] - prices[i - 1]; + } + } + return maxProfit; + } + + } + + class Solution1 { + + /** + * dp[i] 表示当天可获得的收益 + * dp[i] = dp[i-1] + if(prices[i-1] < price[i]){prices[i] - price[i-1]} + * + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + int[] dp = new int[prices.length]; + for (int i = 1; i < prices.length; i++) { + dp[i] = dp[i - 1]; + if (prices[i - 1] < prices[i]) { + // 挣钱 + dp[i] += prices[i] - prices[i - 1]; + } + } + return dp[prices.length - 1]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode124.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode124.java new file mode 100644 index 0000000..4b9aeb5 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode124.java @@ -0,0 +1,56 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/16 15:05 + * @注释 + */ +public class LeetCode124 { + @Test + public void test() + { + + TreeNode treeNode = TreeNode.constructTreeByArray(1, 2, 3); + System.out.println(new Solution().maxPathSum(treeNode)); + } + + class Solution { + /** + * f + * a + * b c + *

+ * a有可能的路径 + * 1. f a c + * 2. f a b + * 3. b a c 不包含父亲节点 用b+a+c与max判断 + * + * @param root + * @return + */ + int max = Integer.MIN_VALUE; + public int maxPathSum(TreeNode root) { + maxPath(root); + return max; + } + public int maxPath(TreeNode root) { + if (root == null) { + return 0; + } + int left = maxPath(root.left); + int right = maxPath(root.right); + if (left < 0) { + left = 0; + } + if (right < 0) { + right = 0; + } + max = Math.max(max, left + right + root.val); // 如果是 b a c 既没有用父亲节点 + return Math.max(left, right) + root.val; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode125.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode125.java new file mode 100644 index 0000000..2f561cc --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode125.java @@ -0,0 +1,49 @@ +package cn.whaifree.leetCode.String; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/18 23:28 + * @注释 + */ +public class LeetCode125 { + public static void main(String[] args) { + System.out.println((int) 'A'); + System.out.println((int) 'Z'); + System.out.println((int) 'a'); + System.out.println((int) 'z'); + System.out.println(new Solution().isPalindrome("A man, a plan, a canal: Panama")); + + } + + static class Solution { + public boolean isPalindrome(String s) { + StringBuilder sb = new StringBuilder(); + for (char c : s.toCharArray()) { + // 大写字符转换为小写字符、并移除所有非字母数字字符 +// if (c >= 'A' && c <= 'Z') { +// sb.append((char) (c + 32)); +// } else if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { +// sb.append(c); +// } + if (Character.isLetterOrDigit(c)) { + sb.append(Character.toLowerCase(c)); + } + + } + return isHuiWen(sb.toString()); + } + public boolean isHuiWen(String s) { + int left = 0; + int right = s.length() - 1; + while (left < right) { + if (s.charAt(left) != s.charAt(right)) { + return false; + } + left++; + right--; + } + return true; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode129.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode129.java new file mode 100644 index 0000000..80c9da2 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode129.java @@ -0,0 +1,38 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 22:27 + * @注释 + */ +public class LeetCode129 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{4, 9, 0, 5, 1}); + int sum = new Solution().sumNumbers(treeNode); + System.out.println(sum); + } + + class Solution { + public int sumNumbers(TreeNode root) { + return sumNumbers(root, 0); + } + public int sumNumbers(TreeNode root,int pre) { + if (root == null) { + return 0; + } + if (root.left == null && root.right == null) { + return pre * 10 + root.val; + } + int now = pre * 10 + root.val; + int left = sumNumbers(root.left, now); + int right = sumNumbers(root.right, now); + return left + right; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode129_2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode129_2.java new file mode 100644 index 0000000..8c5e678 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode129_2.java @@ -0,0 +1,38 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/15 12:34 + * @注释 + */ + + +public class LeetCode129_2 { + + + /** + * 向下遍历,从前往后获取值 + */ + class Solution { + + public int sumNumbers(TreeNode root) { + return level(root, 0); + } + + public int level(TreeNode root,int preV) { + if (root == null) { + return 0; + } + int sum = root.val + preV * 10; + if (root.left == null && root.right == null) { + return sum; + } + int right = level(root.right,sum); + int left = level(root.left, sum); + return right + left; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode13.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode13.java new file mode 100644 index 0000000..62f43b6 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode13.java @@ -0,0 +1,123 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/18 0:11 + * @注释 + */ +public class LeetCode13 { + + @Test + public void test() + { + Solution1 solution = new Solution1(); + int i = solution.romanToInt("MCMXCIV"); + System.out.println(i); + } + + class Solution { + public int romanToInt(String s) { + char[] charArray = s.toCharArray(); + int res = 0; + for (int i = 0; i < charArray.length; i++) { + if (i < charArray.length - 1 && charArray[i] == 'I' && charArray[i + 1] == 'V') { + res += 4; + i++; + } + else if (i < charArray.length - 1 && charArray[i] == 'I' && charArray[i + 1] == 'X') { + res += 9; + i++; + } + else if (i < charArray.length - 1 && charArray[i] == 'X' && charArray[i + 1] == 'L') { + res += 40; + i++; + } + else if (i < charArray.length - 1 && charArray[i] == 'X' && charArray[i + 1] == 'C') { + res += 90; + i++; + } + else if (i < charArray.length - 1 && charArray[i] == 'C' && charArray[i + 1] == 'D') { + res += 400; + i++; + } + else if (i < charArray.length - 1 && charArray[i] == 'C' && charArray[i + 1] == 'M') { + res += 900; + i++; + } + else if (charArray[i] == 'I') { + res += 1; + } + else if (charArray[i] == 'V') { + res += 5; + } + else if (charArray[i] == 'X') { + res += 10; + } + else if (charArray[i] == 'L') { + res += 50; + } + else if (charArray[i] == 'C') { + res += 100; + } + else if (charArray[i] == 'D') { + res += 500; + } + else if (charArray[i] == 'M') { + res += 1000; + } + } + return res; + } + } + + class Solution1 { + + + /** + * 当前位置的元素比下个位置的元素小,就减去当前值,否则加上当前值 + * 输入: s = "MCMXCIV" + * 输出: 1994 + * 解释: M = 1000, CM = 900, XC = 90, IV = 4. + * @param s + * @return + */ + public int romanToInt(String s) { + int res = 0; + int preV = getV(s.charAt(0)); + for (int i = 1; i < s.length(); i++) { + int nums = getV(s.charAt(i)); + if (preV < nums) { + res -= preV; + }else { + res += preV; + } + preV = nums; + } + res += preV; + return res; + } + + public int getV(char c) { + switch (c) { + case 'I': + return 1; + case 'V': + return 5; + case 'X': + return 10; + case 'L': + return 50; + case 'C': + return 100; + case 'D': + return 500; + case 'M': + return 1000; + } + return 0; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode131.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode131.java new file mode 100644 index 0000000..84f0c12 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode131.java @@ -0,0 +1,71 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/10 15:12 + * @注释 + */ +public class LeetCode131 { + + @Test + public void test() { + String abbc = "aaab"; + new Solution().partition(abbc).forEach( + list -> { + System.out.println(list); + } + ); + } + + class Solution { + + List> res = new ArrayList<>(); + List path = new ArrayList<>(); + public List> partition(String s) { + backTracking(s, 0); + return res; + } + + /** + * 1. 判断回文字符串函数
+ * 2. 从start开始切割,到i i++
+ * 递归 + * + * + * @param s + * @param start + */ + public void backTracking(String s, int start) { + if (start >= s.length()) { + res.add(new ArrayList<>(path)); + return; + } + for (int i = start; i < s.length(); i++) { + if (isPalindrome(s, start, i)) { + String substring = s.substring(start, i + 1); + path.add(substring); + backTracking(s, i + 1); + path.remove(path.size() - 1); + } + } + + } + + //判断是否是回文串 + private boolean isPalindrome(String s, int startIndex, int end) { + for (int i = startIndex, j = end; i < j; i++, j--) { + if (s.charAt(i) != s.charAt(j)) { + return false; + } + } + return true; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode134.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode134.java new file mode 100644 index 0000000..a36b9c5 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode134.java @@ -0,0 +1,120 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/27 20:02 + * @注释 + */ +public class LeetCode134 { + + @Test + public void test() throws InterruptedException { + + System.out.println("初始化内存 -Xms"); + System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024 + "m"); + + System.out.println("最大可使用内存 :"); + System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024 + "m"); + + System.out.println("最大堆内存:-Xmx"); + System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024 + "m"); + + // -XX+PrintGCDetails + + int[] ints = new int[10000]; +// Thread.sleep(1000000); + +// System.out.println(new Solution().canCompleteCircuit( +// new int[]{5,1,2,3,4}, +// new int[]{4,4,1,5,1} +// )); + + } + + class Solution { + /** + * + * @param gas 加油站有的油 + * @param cost 行驶代价 + * @return + */ + public int canCompleteCircuit(int[] gas, int[] cost) { + + int[] rent = new int[gas.length]; + int total = 0; + for (int i = 0; i < gas.length; i++) { + rent[i] = gas[i] - cost[i]; + total += rent[i]; + } + // 如果全部剩余<0 则必然跑不了一圈 + if (total < 0) { + return -1; + } + + + // 以下为必然可以跑一圈的 + // 如果当前剩余不够用,则让指针指向i+1 + int curSum = 0; + int index = 0; + for (int i = 0; i < rent.length; i++) { + curSum += rent[i]; + if (curSum < 0) { + index = (i + 1) % gas.length ; + curSum = 0; + } + } + // 1. 前提,必然能跑一圈 + // 2. 没有进入某个i之后都没有curSum<0 那么就是正确的i + return index; + } + + } +// class Solution { +// /** +// * +// * @param gas 加油站有的油 +// * @param cost 行驶代价 +// * @return +// */ +// public int canCompleteCircuit(int[] gas, int[] cost) { +// int needSum = 0; +// for (int i : cost) { +// needSum += i; +// } +// +// int iHave = 0; +// int sumAdd = 0; +// int start = 0; +// for (int i = 0; i < gas.length; i++) { +// iHave += gas[i]; +// sumAdd += gas[i]; +// if (iHave < cost[i]) { +// iHave = 0; +// i = start; +// start = start + 1; +// sumAdd = 0; +// continue; +// } +// iHave -= cost[i]; +// if (sumAdd >= needSum) { +// return start; +// } +// +// if (i == gas.length - 1) { +// i = -1; +// } +// +// if (start == gas.length - 1 && start != i) { +// break; +// } +// } +// +// return -1; +// } +// +// } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode135.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode135.java new file mode 100644 index 0000000..32fa45e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode135.java @@ -0,0 +1,63 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Vector; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/28 12:44 + * @注释 + */ +public class LeetCode135 { + + @Test + public void tesr() { + System.out.println(new Solution().candy(new int[]{1, 2, 2, 5, 4, 3, 2})); + } + + + class Solution { + public int candy(int[] ratings) { + // 从前往后遍历,遇到ratings[i]>ratings[i-1] score[i]+1 + int length = ratings.length; + + int[] scores = new int[length]; + scores[0] = 1; + + for (int i = 1; i < length; i++) { + if (ratings[i] > ratings[i - 1]) { + scores[i] = scores[i - 1] + 1; + }else { + scores[i] = 1; + } + } + + // 从后往前 + for (int i = length -1; i > 0; i--) { + /** + * 如果 ratings[i] < ratings[i - 1],此时candyVec[i-1](第i-1个小孩的糖果数量)就有两个选择了, + * - 一个是candyVec[i] + 1(从右边这个加1得到的糖果数量), + * - 一个是candyVec[i-1](之前比较右孩子大于左孩子得到的糖果数量)。 + * 如 5 3 + * 从右边向左边,i-1可选择为 3+1 或者原来的 5,从左往右已经处理过的, + * 同时要满足同时保证i小孩既大于左也大于右边,那么取最大值。 + * 同时保证i小孩既大于左也大于右边 + */ + if (ratings[i] < ratings[i - 1]) { + scores[i - 1] = Math.max(scores[i] + 1, scores[i - 1]); + } + } + + int scoreSum = 0; + for (int score : scores) { + scoreSum += score; + } + + return scoreSum; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode138.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode138.java new file mode 100644 index 0000000..21dd4ce --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode138.java @@ -0,0 +1,86 @@ +package cn.whaifree.leetCode.LinkedList; + +import org.junit.Test; + +public class LeetCode138 { + + static class Node { + int val; + Node next; + Node random; + + public Node(int val) { + this.val = val; + this.next = null; + this.random = null; + } + } + + @Test + public void test() { + + // 1 2 3 + // 1 3 + // 2 1 + +// Node node1 = new Node(1); +// Node node2 = new Node(2); +// Node node3 = new Node(3); +// node1.next = node2; +// node2.next = node3; +// node1.random = node3; +// node2.random = node1; +// Node node = copyRandomList(node1); +// System.out.println(node); + + +// [[7,null],[13,0],[11,4],[10,2],[1,0]] + Node node1 = new Node(7); + Node node2 = new Node(13); + Node node3 = new Node(11); + Node node4 = new Node(10); + Node node5 = new Node(1); + node1.next = node2; + node2.next = node3; + node3.next = node4; + node4.next = node5; + node2.random = node1; + node3.random = node5; + node4.random = node3; + node5.random = node1; + Node node = copyRandomList(node1); + System.out.println(node); + } + + public Node copyRandomList(Node head) { + Node index = head; + while (index != null) { + Node tmp = index.next; + index.next = new Node(index.val); + index.next.next = tmp; + index = index.next.next; + } + + index = head; + while (index != null) { + if (index.random != null) { + index.next.random = index.random.next; + } + index = index.next.next; + } + + + Node newHead = head.next; + index = newHead; + Node tmpPreIndex = head; + while (index.next != null) { + tmpPreIndex.next = tmpPreIndex.next.next; + tmpPreIndex = tmpPreIndex.next; + index.next = index.next.next; + index = index.next; + } + tmpPreIndex.next = null; + return newHead; + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode139.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode139.java new file mode 100644 index 0000000..447d4dd --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode139.java @@ -0,0 +1,84 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 13:15 + * @注释 + */ +public class LeetCode139 { + + @Test + public void test() { +// System.out.println(new Solution().wordBreak("leetcode", List.of("leet", "code"))); +// System.out.println(new Solution().wordBreak("leetcode", List.of("leet", "cod", "e"))); + // ["apple","pen"] + System.out.println(new Solution().wordBreak("applepenapple", List.of("apple", "pen"))); + + } + + class Solution { + + /** + * + * dp[i][j] 表示s中前j个字母能否被0-i中任意元素组合出来 + * + * 定义 dp[i] 表示字符串 s 前 i 个字符组成的字符串 s[0..i−1] 是否能被空格拆分成若干个字典中出现的单词 + * + * c a t s a n d o g + * cats 0 0 0 1 0 + * dog + * sand + * and + * cat + * '' l e e t c o d e + * '' 1 0 0 0 0 0 0 0 0 + * leet 1 0 0 0 1 0 0 0 0 + * code 1 0 0 0 0 0 0 0 1 + * + * a p p l e p e n a p p l e + * apple 1 0 0 0 0 1 0 0 0 0 0 0 0 1 + * pen 1 0 0 0 0 1 0 0 1 0 0 0 0 0 + * + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak(String s, List wordDict) { + // 完全背包,先便利字符串再遍历背包,确保重会重复选择背包 + int len = s.length(); + boolean[] dp = new boolean[len + 1]; + dp[0] = true; + for (int j = 1; j <= len; j++) { + for (int i = 0; i < wordDict.size(); i++) { + String str = wordDict.get(i); + int index = j - str.length(); + if (index >= 0 && dp[index] && check(s, j - 1, str)) { + dp[j] = true; + } + } + } + return dp[len]; + } + + + + public boolean check(String s, int start, String word) { + for (int i = word.length() - 1; i >= 0; i--) { + if (word.charAt(i) != s.charAt(start)) { + return false; + } + start--; + } + return true; + } + } + @Test + public void main() { + System.out.println(new Solution().check("leetcode", 7, "code")); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode14.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode14.java new file mode 100644 index 0000000..99e50fa --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode14.java @@ -0,0 +1,73 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/18 22:09 + * @注释 + */ +public class LeetCode14 { + @Test + public void test() { + Solution solution = new Solution(); + String[] strs = {"d", "c"}; + String s = solution.longestCommonPrefix(strs); + System.out.println(s); + } + + class Solution { + public String longestCommonPrefix(String[] strs) { + + String min = strs[0]; + for (String s : strs) { + if (s.length() < min.length()) { + min = s; + } + } + + int index = 0; + + while (index < min.length()) { + char c = strs[0].charAt(index); + for (int i = 1; i < strs.length; i++) { + if (strs[i].charAt(index) != c) { + return strs[0].substring(0, index); + } + } + index++; + } + + return min; + } + } + + @Test + public void test2() { + Solution2 solution = new Solution2(); + String[] strs = {"flower","flow","flight"}; + String s = solution.longestCommonPrefix(strs); + System.out.println(s); + } + + class Solution2 { + public String longestCommonPrefix(String[] strs) { + String str = strs[0]; + for (int i = 1; i < strs.length; i++) { + str = common(str, strs[i]); + } + return str; + } + + public String common(String a, String b) { + int len = Math.min(a.length(), b.length()); + for (int i = 0; i < len; i++) { + if (a.charAt(i) != b.charAt(i)) { + return a.substring(0, i); + } + } + return a.substring(0, len); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode141.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode141.java new file mode 100644 index 0000000..f97761b --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode141.java @@ -0,0 +1,42 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/23 12:54 + * @注释 + */ +public class LeetCode141 { + @Test + public void test() { + ListNode listNode = ListNode.listNodeFromArray(new int[]{1}); +// listNode.next.next.next = listNode; + System.out.println(new Solution().hasCycle(listNode)); + } + + public class Solution { + public boolean hasCycle(ListNode head) { + if (head == null) { + return false; + } + if (head.next == null) { + return false; // 只有一个节点 + } + ListNode slow = head; + ListNode fast = head.next; + while (slow != fast) { + if (fast == null || fast.next == null) { + return false; + } + slow = slow.next; + fast = fast.next.next; + } + return true; + + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode142.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode142.java new file mode 100644 index 0000000..404c609 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode142.java @@ -0,0 +1,104 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.HashSet; +import java.util.Objects; +import java.util.Stack; + +public class LeetCode142 { + + @Test + public void test() { + + + + Solution solution = new Solution(); + ListNode listNode1= new ListNode(1); + ListNode listNode2= new ListNode(2,listNode1); + ListNode listNode3= new ListNode(3,listNode2); + ListNode listNode4= new ListNode(4,listNode3); + listNode1.next = listNode3; + +// ListNode.printList(listNode4); + + ListNode listNode = solution.detectCycle(listNode4); + if (listNode == null) { + System.out.println("null"); + } else { + System.out.println(listNode.val); + } + } + + /** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ + public class Solution { + /** + * 快慢指针 + * 时间复杂度:O(N),其中 N 为链表中节点的数目。我们恰好需要访问链表中的每一个节点。 + * 空间复杂度:O(1) + * + * @param head + * @return + */ + public ListNode detectCycle(ListNode head) { + + ListNode slow = head; + ListNode fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + // 相遇了,有环。 + if (slow == fast) { + break; + } + } + + if (Objects.isNull(fast) || Objects.isNull(fast.next)) { + return null; + } + + // 此时相遇 fast,slow + // x = (n-1)(y-z)+z + slow = head; + while (slow != fast) { + slow = slow.next; + fast = fast.next; + } + return slow; + } + } + + + /** + * 时间复杂度:O(N),其中 N 为链表中节点的数目。我们恰好需要访问链表中的每一个节点。 + * 空间复杂度:O(N),其中 N 为链表中节点的数目。我们需要将链表中的每个节点都保存在哈希表当中。 + */ + public class Solution1 { + /** + * 快慢指针 + * @param head + * @return + */ + public ListNode detectCycle(ListNode head) { + HashSet listNodes = new HashSet<>(); + ListNode index = head; + while (index != null && !listNodes.contains(index)) { + listNodes.add(index); + index = index.next; + } + return index; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode144.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode144.java new file mode 100644 index 0000000..49247a3 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode144.java @@ -0,0 +1,81 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Consumer; + +/** + * 前序遍历 + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/14 15:12 + * @注释 + */ +public class LeetCode144 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{}); + TreeNode.printTree(treeNode); + new Solution1().preorderTraversal(treeNode).forEach( + integer -> System.out.println(integer) + ); + } + + + class Solution { + + List res = new LinkedList(); + public List preorderTraversal(TreeNode root) { + + if (root == null) { + return res; + } + return pre(root); + } + + public List pre(TreeNode root) { + if (root == null) { + return null; + } + res.add(root.val); + pre(root.left); + pre(root.right); + return res; + } + } + + class Solution1 { + public List preorderTraversal(TreeNode root) { + List res = new LinkedList(); + if (root == null) { + return res; + } + // 基于指针 + Deque queue = new LinkedList<>(); + // 加入根节点 + TreeNode index = root; + queue.push(index); + while (!queue.isEmpty()) { + index = queue.pop(); + res.add(index.val); + // 先加入右子树,因为是栈,后出右边 + if (index.right != null) { + queue.push(index.right); + } + // 后加入左子树 + if (index.left != null) { + queue.push(index.left); + } + } + return res; + } + + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode145.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode145.java new file mode 100644 index 0000000..c968c3d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode145.java @@ -0,0 +1,77 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/15 20:11 + * @注释 + */ +public class LeetCode145 { + + @Test + public void test() { + TreeNode root = TreeNode.constructTree(new Integer[]{1, 2, 3, 4, 5}); + + root.printTree(); + new Solution1().postorderTraversal(root).forEach( + System.out::println + ); + } + + class Solution { + List res = new LinkedList<>(); + + public List postorderTraversal(TreeNode root) { + if (root == null) { + return res; + } + postorder(root); + return res; + } + + public void postorder(TreeNode root) { + if (root==null) return; + + postorder(root.left); + postorder(root.right); + res.add(root.val); + + } + } + + + class Solution1 { + public List postorderTraversal(TreeNode root) { + + List res = new LinkedList(); + if (root == null) { + return res; + } + Deque stack = new ArrayDeque<>(); + + stack.push(root); + while (!stack.isEmpty()) { + + TreeNode pop = stack.pop(); + res.add(pop.val); + if (pop.left != null) { + stack.push(pop.left); + } + if (pop.right != null) { + stack.push(pop.right); + } + } + + Collections.reverse(res); + + return res; + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode150.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode150.java new file mode 100644 index 0000000..2f05a53 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode150.java @@ -0,0 +1,90 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * 逆转波兰表达式 + */ +public class LeetCode150 { + + @Test + public void test() { + System.out.println(new Solution1().evalRPN(new String[]{"2", "1", "+", "3", "*"})); + System.out.println(new Solution1().evalRPN(new String[]{"4", "13", "5", "/", "+"})); + } + + + class Solution { + public int evalRPN(String[] tokens) { + + Deque stack = new LinkedList<>(); + + int index = 0; + while (index < tokens.length) { + String token = tokens[index]; + if (token.equals("+")) { + Integer pop1 = Integer.parseInt(stack.pop()); + Integer pop2 = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(pop1 + pop2)); + } else if (token.equals("-")) { //避免多次判断 + Integer pop1 = Integer.parseInt(stack.pop()); + Integer pop2 = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(pop2 - pop1)); + } else if (token.equals("*")) { + Integer pop1 = Integer.parseInt(stack.pop()); + Integer pop2 = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(pop2 * pop1)); + } else if (token.equals("/")) { + Integer pop1 = Integer.parseInt(stack.pop()); + Integer pop2 = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(pop2 / pop1)); + } else { + stack.push(token); + } + index++; + } + return Integer.parseInt(stack.pop()); + + } + } + + class Solution1 { + public int evalRPN(String[] tokens) { + + Deque stack = new LinkedList<>(); + + for (String token : tokens) { + switch (token) { + case "+": + int i = Integer.parseInt(stack.pop()); + int j = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(i + j)); + break; + case "-": + int k = Integer.parseInt(stack.pop()); + int l = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(l - k)); + break; + case "*": + int m = Integer.parseInt(stack.pop()); + int n = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(n * m)); + break; + case "/": + int o = Integer.parseInt(stack.pop()); + int p = Integer.parseInt(stack.pop()); + stack.push(String.valueOf(p / o)); + break; + default: + stack.push(token); + break; + } + } + return Integer.parseInt(stack.pop()); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode151.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode151.java new file mode 100644 index 0000000..d08ff27 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode151.java @@ -0,0 +1,123 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +import java.util.*; + + +public class LeetCode151 { + + + // todo + @Test + public void test() { + String s = " a b cd ef g "; + System.out.println(new Solution2().reverseWords(s)); + + + } + + class Solution { + public String reverseWords(String s) { + List list = new LinkedList<>(); + String[] split = s.split(" "); + for (String s1 : split) { + if (!(s1.equals("") || s1.equals(" "))) { + list.add(s1); + } + } + StringBuilder buffer = new StringBuilder(); + int index = list.size() - 1; + while (index > 0) { + buffer.append(list.get(index--)+" "); + } + buffer.append(list.get(0)); + return buffer.toString(); + } + + } + + // 不要使用辅助空间,空间复杂度要求为O(1) + class Solution1 { + public String reverseWords(String s) { + StringBuilder stringBuilder = deleteSpace(s, ' '); + reverse(stringBuilder, 0, stringBuilder.length() - 1); + reverseWord(stringBuilder); + // 移除多余空格 + // 反转char + // 反转每个字符 + return stringBuilder.toString(); + } + + public void reverseWord(StringBuilder stringBuilder) { + int start = 0; + int index = 0; + while (index < stringBuilder.length() + 1) { + if (index == stringBuilder.length() || stringBuilder.charAt(index) == ' ') { + reverse(stringBuilder, start, index - 1); + start = index + 1; + } + index++; + } + } + public void reverse(StringBuilder str, int start, int end) { + while (start < end) { + char tmp = str.charAt(start); + str.setCharAt(start, str.charAt(end)); + str.setCharAt(end, tmp); + end--; + start++; + } + } + + + /** + * 双指针移动元素,移除target + * - 参考LeetCode 27 + + * @param target + * @return + */ + public StringBuilder deleteSpace(String s,char target) { + + // 前后指针 + int start = 0; + int end = s.length() - 1; + while (s.charAt(start) == target) start++; + while (s.charAt(end) == target) end--; + // 1. 删除首尾空格 + + StringBuilder stringBuilder = new StringBuilder(); + while (start <= end) { + if (s.charAt(start) !=target){ + stringBuilder.append(s.charAt(start) ); + }else if (s.charAt(start) == target && stringBuilder.charAt(stringBuilder.length() - 1) != target) { + stringBuilder.append(s.charAt(start) ); + } + start++; + } + // 2. 如果遇到空格,判断上一个是不是空格 + // - 不是,入String + // - 是,跳过 + + + return stringBuilder; + } + + } + + + class Solution2{ + + public String reverseWords(String s) { + // 删除前后空白 + String trim = s.trim(); + String[] split = trim.split("\\s+"); + List list = Arrays.asList(split); + Collections.reverse(list); + return String.join(" ", list); + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode155.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode155.java new file mode 100644 index 0000000..e81aec1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode155.java @@ -0,0 +1,104 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/1 0:52 + * @注释 + */ +public class LeetCode155 { + + @Test + public void test2() { + MinStack minStack = new MinStack(); + // ["MinStack","push","push","push","getMin","pop","top","getMin"] + minStack.push(-2); + minStack.push(0); + minStack.push(-3); + System.out.println(minStack.getMin()); + minStack.pop(); + System.out.println(minStack.top()); + System.out.println(minStack.getMin()); + } + + class MinStack { + + static class Item{ + Integer item; + Integer minV; + + public Item(Integer item, Integer minV) { + this.item = item; + this.minV = minV; + } + } + + Deque itemStack = null; + + public MinStack() { + itemStack = new ArrayDeque<>(); + } + + public void push(int val) { + // 找到当前最小值 + Integer minNow = Math.min(getMin(), val); + + Item item = new Item(val, minNow); + itemStack.push(item); + } + + public void pop() { + itemStack.pop(); + } + + public int top() { + if (itemStack.isEmpty()) { + return Integer.MAX_VALUE; + } + return itemStack.peek().item; + } + + public int getMin() { + if (itemStack.isEmpty()) { + return Integer.MAX_VALUE; + } + return itemStack.peek().minV; + } + } + + /** + * Your MinStack object will be instantiated and called as such: + * MinStack obj = new MinStack(); + * obj.push(val); + * obj.pop(); + * int param_3 = obj.top(); + * int param_4 = obj.getMin(); + */ + @Test + public void test() { + MinStack minStack = new MinStack(); + // ["MinStack","push","push","push","getMin","pop","top","getMin"] + minStack.push(-2); + minStack.push(0); + minStack.push(-3); + System.out.println(minStack.getMin()); + minStack.pop(); + System.out.println(minStack.top()); + System.out.println(minStack.getMin()); + } + + + +/** + * Your MinStack object will be instantiated and called as such: + * MinStack obj = new MinStack(); + * obj.push(val); + * obj.pop(); + * int param_3 = obj.top(); + * int param_4 = obj.getMin(); + */ +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode160.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode160.java new file mode 100644 index 0000000..85664cf --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode160.java @@ -0,0 +1,30 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/13 11:06 + * @注释 + */ +public class LeetCode160 { + + @Test + public void test() + { + + } + + class Solution { + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + ListNode A = headA, B = headB; + while (A != B) { + A = A == null ? headB : A.next; + B = B == null ? headA : B.next; + } + return A; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode165.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode165.java new file mode 100644 index 0000000..a96ee48 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode165.java @@ -0,0 +1,103 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/8/31 14:57 + * @注释 + */ +public class LeetCode165 { + + @Test + public void test() { + Solution2 solution = new Solution2(); + int result = solution.compareVersion("1.01.2", "1.001"); + System.out.println(result); + } + + class Solution2 { + /** + * 双指针,不断计算有效长度 + * @param version1 + * @param version2 + * @return + */ + public int compareVersion(String version1, String version2) { + + int v1Index = 0; + int v2Index = 0; + while (v1Index < version1.length() || v2Index < version2.length()) { + int tmpV1Sum = 0; + while (v1Index < version1.length() && version1.charAt(v1Index) != '.') { + tmpV1Sum += tmpV1Sum * 10 + version1.charAt(v1Index) - '0'; + v1Index++; + } + v1Index++; // 跳过. + + int tmpV2Sum = 0; + while (v2Index < version2.length() && version2.charAt(v2Index) != '.') { + tmpV2Sum += tmpV2Sum * 10 + version2.charAt(v2Index) - '0'; + v2Index++; + } + v2Index++; // 跳过. + if (tmpV1Sum < tmpV2Sum) { + return -1; + } else if (tmpV1Sum > tmpV2Sum) { + return 1; + } + } + return 0; + } + } + + class Solution { + /** + * 1.2 1.10 + * 1.01 1.001 + * 1.0.0.0 + * + * + * @param version1 + * @param version2 + * @return + */ + public int compareVersion(String version1, String version2) { + String[] splitV1 = version1.split("\\."); + String[] splitV2 = version2.split("\\."); + if (splitV1.length < splitV2.length) { + splitV1 = fill(splitV1, splitV2.length); + }else { + splitV2 = fill(splitV2, splitV1.length); + } + // 现在两边一样长了 + + for (int i = 0; i < splitV1.length; i++) { + Integer v1 = Integer.valueOf(splitV1[i]); + Integer v2 = Integer.valueOf(splitV2[i]); + if (v1 > v2) { + return 1; + } else if (v1 < v2) { + return -1; + } + } + + return 0; + + + } + + public String[] fill(String[] split, int newLen) { + String[] tmp = new String[newLen]; + int i = 0; + for (; i < split.length; i++) { + tmp[i] = split[i]; + } + for (; i < tmp.length; i++) { + tmp[i] = "0"; + } + return tmp; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode167.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode167.java new file mode 100644 index 0000000..7bd91cd --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode167.java @@ -0,0 +1,68 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/19 23:02 + * @注释 + */ +public class LeetCode167 { + + @Test + public void test() { + + Solution1 solution = new Solution1(); + int[] ints = solution.twoSum(new int[]{2,7,11,15}, 9); + System.out.println(ints[0] + " " + ints[1]); + } + + class Solution { + public int[] twoSum(int[] numbers, int target) { + + for (int i = 0; i < numbers.length; i++) { + int tar = target - numbers[i]; + int j = binarySearch(numbers, tar); + if (j != -1 && i != j) { + return i < j ? new int[]{i + 1, j + 1} : new int[]{j + 1, i + 1}; + } + } + return null; + } + + public int binarySearch(int[] nums, int target) { + int left = 0; + int right = nums.length - 1; + while (left <= right) { + int mid = (left + right) / 2; + if (nums[mid] == target) { + return mid; + } else if (nums[mid] < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + return -1; + } + } + + class Solution1 { + public int[] twoSum(int[] numbers, int target) { + int left = 0; + int right = numbers.length - 1; + while (left < right) { + int sum = numbers[left] + numbers[right]; + if (sum == target) { + return new int[]{left + 1, right + 1}; + } else if (sum < target) { + left++; + }else { + right--; + } + } + return null; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode169.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode169.java new file mode 100644 index 0000000..5fe0bf3 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode169.java @@ -0,0 +1,57 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/1 2:21 + * @注释 + */ +public class LeetCode169 +{ + @Test + public void test() + { + + int[] nums = {2,2,1,1,1,2,2}; + Solution solution = new Solution(); + int i = solution.majorityElement(nums); + System.out.println(i); + } + class Solution { + /** + * 遍历每个元素 + * count 为现在出现最多的数 + * - 如果count = 0 (表示发生了是和不是的变化) + * - 这个元素出现的次数>=之前元素出现的个数 + * 所以基准变为这个元素 + * count = item == base : 1:-1 + * + * 如果是这个元素+1,不是这个元素-1 + * + * cge5 cge5 cge7 + * 1 2 1 2 1 0 1 0 1 2 1 0 1 2 3 4 + * [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7] + * 在遍历到数组中的第一个元素以及每个在 | 之后的元素时,candidate 都会因为 count 的值变为 0 而发生改变。最后一次 candidate 的值从 5 变为 7,也就是这个数组中的众数。 + * + * + * @param nums + * @return + */ + public int majorityElement(int[] nums) { + int count = 0; + Integer candidate = null; + + for (int num : nums) { + if (count == 0) { + candidate = num; + System.out.println("基准元素:" + candidate); + } + count += (num == candidate) ? 1 : -1; + } + + return candidate; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode17.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode17.java new file mode 100644 index 0000000..c829ace --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode17.java @@ -0,0 +1,119 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/2 10:31 + * @注释 + */ +public class LeetCode17 { + + @Test + public void test() { + String digits = "23"; + new Solution().letterCombinations(digits).forEach(s -> System.out.println(s)); + } + + class Solution { + List map = new ArrayList<>(); + List result = new ArrayList<>(); + // 记录 路径 + StringBuilder s = new StringBuilder(); + + public List letterCombinations(String digits) { + if (digits.length() == 0) { + return result; + } + map.add(0, null); + map.add(1, null); + map.add(2, "abc"); + map.add(3, "def"); + map.add(4, "ghi"); + map.add(5, "jkl"); + map.add(6, "mno"); + map.add(7, "pqrs"); + map.add(8, "tuv"); + map.add(9, "wxyz"); + backTracking(digits, 0, digits.length()); + return result; + } + + /** + * + * @param digits 原始字符 23 + * @param number 使用到第几个字符 + * @param needLength 需要几个字符,等价于digits.length + */ + void backTracking(String digits, int number,int needLength) { + if (s.length() == needLength) { + result.add(new String(s.toString())); + return; + } + + int c = digits.charAt(number) - 48; + String sValue = map.get(c); + int length = sValue.length(); + // 对每个字符处理 + for (int i = 0; i < length; i++) { + char c1 = sValue.charAt(i); + s.append(c1); + backTracking(digits, number + 1, needLength); + s.deleteCharAt(s.length() - 1); + } + } + } + + class Solution1 { + List map = new ArrayList<>(); + List result = new ArrayList<>(); + // 记录 路径 + StringBuilder s = new StringBuilder(); + + public List letterCombinations(String digits) { + if (digits.length() == 0) { + return result; + } + map.add(0, null); + map.add(1, null); + map.add(2, "abc"); + map.add(3, "def"); + map.add(4, "ghi"); + map.add(5, "jkl"); + map.add(6, "mno"); + map.add(7, "pqrs"); + map.add(8, "tuv"); + map.add(9, "wxyz"); + + backTracking(digits, 0); + return result; + } + + /** + * + * @param digits 原始字符 23 + * @param number 使用到第几个字符 + */ + void backTracking(String digits, int number) { + if (s.length() == digits.length()) { + result.add(new String(s.toString())); + return; + } + + int c = digits.charAt(number) - 48; + String sValue = map.get(c); + int length = sValue.length(); + // 对每个字符处理 + for (int i = 0; i < length; i++) { + char c1 = sValue.charAt(i); + s.append(c1); + backTracking(digits, number + 1); + s.deleteCharAt(s.length() - 1); + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode173.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode173.java new file mode 100644 index 0000000..042089e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode173.java @@ -0,0 +1,128 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 22:42 + * @注释 + */ +public class LeetCode173 { + + class BSTIterator1 { + + List list; + Integer index = -1; + + public BSTIterator1(TreeNode root) { + list = new ArrayList<>(); + inOrderTraversal(root); + } + + public int next() { + index++; + return list.get(index); + } + + public boolean hasNext() { + return index < list.size() - 1; + } + + public void inOrderTraversal(TreeNode root) { + if (root == null) { + return; + } + inOrderTraversal(root.left); + list.add(root.val); + inOrderTraversal(root.right); + } + } + + @Test + public void test1() { + TreeNode root = TreeNode.constructTree(new Integer[]{7, 3, 15, null, null, 9, 20}); + BSTIterator bstIterator = new BSTIterator(root); + while (bstIterator.hasNext()) { + System.out.println(bstIterator.next()); + } + } + + class BSTIterator { + /** + * next访问到某个节点,就让他右边入栈 + */ + + Deque stack; + public BSTIterator(TreeNode root) { + // 每层放左边第一个 + stack = new LinkedList<>(); + TreeNode index = root; + while (index != null) { + stack.push(index); + index = index.left; + } + } + + public int next() { + TreeNode pop = stack.pop(); // 当前指针位置 + if (pop.right != null) { // 如果有边有,就把右边和右边的左子树都放入栈中 + TreeNode index = pop.right; + while (index != null) { + stack.push(index); + index = index.left; + } + } + return pop.val; + } + + public boolean hasNext() { + return !stack.isEmpty(); + } + } + + + class BSTIterator2 { + /** + * next访问到某个节点,就让他右边入栈 + */ + + Deque stack; + TreeNode now; + public BSTIterator2(TreeNode root) { + // 每层放左边第一个 + stack = new LinkedList<>(); + now = root; + } + + public int next() { + while (now != null) { + stack.push(now); + now = now.left; + } + now = stack.pop(); + int val = now.val; + now = now.right; + return val; + } + + public boolean hasNext() { + return now != null ||!stack.isEmpty(); + } + } + +/** + * Your BSTIterator object will be instantiated and called as such: + * BSTIterator obj = new BSTIterator(root); + * int param_1 = obj.next(); + * boolean param_2 = obj.hasNext(); + */ +} + + diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode17_12BiNode.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode17_12BiNode.java new file mode 100644 index 0000000..0b9eba0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode17_12BiNode.java @@ -0,0 +1,68 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/28 19:41 + * @注释 + */ +public class LeetCode17_12BiNode { + + @Test + public void test() { + TreeNode root = TreeNode.constructTreeByArray(4, 2, 5, 1, 3, null, 6, 0); + TreeNode treeNode = new Solution().convertBiNode(root); + TreeNode.treeToArray(treeNode).forEach(i -> System.out.println(i)); + + } + class Solution { + + TreeNode res = new TreeNode(); + TreeNode index = res; + public TreeNode convertBiNode(TreeNode root) { + circle(root); + return res.right; + } + + private void circle(TreeNode root) { + if (root == null) { + return; + } + circle(root.left); + index.right = new TreeNode(root.val); + index = index.right; + circle(root.right); + } + } + + class Solution1 { + + TreeNode res = new TreeNode(); + TreeNode index = res; + public TreeNode convertBiNode(TreeNode root) { + circle(root); + return res.right; + } + + private void circle(TreeNode root) { + if (root == null) { + return; + } + circle(root.left); + // 直接使用,不创建新对象,能提升很多效率 + index.right = root; + root.left = null; + index = index.right; + circle(root.right); + } + } +} + + + diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode189.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode189.java new file mode 100644 index 0000000..d1edec6 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode189.java @@ -0,0 +1,58 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/16 12:15 + * @注释 + */ +public class LeetCode189 { + @Test + public void test() + { + int[] nums = new int[]{-1}; + new Solution1().rotate(nums, 3); + System.out.println(Arrays.toString(nums)); + } + + + + class Solution { + public void rotate(int[] nums, int k) { + int[] newNums = new int[nums.length]; + for (int i = 0; i < newNums.length; i++) { + newNums[(i + k) % nums.length] = nums[i]; + } + System.arraycopy(newNums, 0, nums, 0, nums.length); + + } + + } + + class Solution1 { + public void rotate(int[] nums, int k) { + k %= nums.length; + reverse(nums, 0, nums.length - 1); + reverse(nums, 0, k - 1); + reverse(nums, k, nums.length - 1); + } + + public void reverse(int[] nums, int start, int end) { + while (start < end) { + swap(nums, start, end); + start++; + end--; + } + } + + public void swap(int[] nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode19.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode19.java new file mode 100644 index 0000000..75a1f8f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode19.java @@ -0,0 +1,144 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +public class LeetCode19 { + + @Test + public void test() { + Solution2 solution = new Solution2(); + ListNode listNode = solution.removeNthFromEnd(ListNode.listNodeFromArray(new int[]{1,2,3,4}), 3); + ListNode.printList(listNode); + + } + + /** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ + class Solution { + + + /** + * 链表中结点的数目为 sz + * 1 <= sz <= 30 + * 0 <= Node.val <= 100 + * 1 <= n <= sz + * + * 时间复杂度:O(Length) + * 空间复杂度:O(1) + * + * @param head + * @param n + * @return + */ + public ListNode removeNthFromEnd(ListNode head, int n) { + + // 空链表 + if (head == null) { + return head; + } + int length = getLength(head); + // 删除头 + if (n == length) { + head = head.next; + return head; + } + + int find = length - n; + ListNode index = head; + for (int i = 0; i < find - 1; i++) { + index = index.next; + } + index.next = index.next.next; + return head; + } + + int getLength(ListNode head) { + int length = 0; + ListNode index = head; + while (index != null) { + index = index.next; + length++; + } + return length; + } + } + + + class Solution1 { + + + /** + * 栈 + * 时间复杂度:O(Length) + * 空间复杂度:O(Length) + * + * 修改多使用这个栈会更快 + * LinkedList比Stack快的原因如下1: + * 基于数组实现:Stack基于数组实现,随机访问(查找)效率更高,增删改效率较低。 + * 基于链表实现:LinkedList基于链表实现,增删改效率更高,随机访问(查找)效率较低。 + * 对于频繁的插入、删除操作,利用LinkedList实现栈自然比Stack快很多。 + * @param head + * @param n + * @return + */ + public ListNode removeNthFromEnd(ListNode head, int n) { + + ListNode dummy = new ListNode(0, head); + Deque stack = new LinkedList(); + // 双端队列 + ListNode index = dummy; + while (index != null) { + stack.push(index); + index = index.next; + } + for (int i = 0; i < n; i++) { + stack.pop(); + } + ListNode peek = stack.peek(); + peek.next = peek.next.next; + return dummy.next; + } + } + + + class Solution2 { + + + /** + * 双指针 快慢节点追逐: + * 两个节点的差值为n,快指针走完了,慢指针就是了 + * + * @param head + * @param n + * @return + */ + public ListNode removeNthFromEnd(ListNode head, int n) { + ListNode dummy = new ListNode(0, head); + ListNode fast = dummy; + ListNode slow = dummy; + for (int i = 0; i <= n; i++) { + fast = fast.next; + } + while (fast!= null) { + fast = fast.next; + slow = slow.next; + } + slow.next = slow.next.next; + return dummy.next; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode198.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode198.java new file mode 100644 index 0000000..6e3210c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode198.java @@ -0,0 +1,40 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/3 13:50 + * @注释 + */ +public class LeetCode198 { + + @Test + public void test() + { + Solution solution = new Solution(); + int[] nums = new int[]{2,7}; + int rob = solution.rob(nums); + System.out.println(rob); + } + + class Solution { + public int rob(int[] nums) { + if (nums.length == 1) { + return nums[0]; + } + // dp[i] 表示 从0-i偷窃都最大价值 + // dp[i] = max(dp[i-1],dp[i-2]+nums[i]]) + int[] dp = new int[nums.length]; + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + for (int i = 2; i < nums.length; i++) { + dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); + } + return dp[nums.length - 1]; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode199.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode199.java new file mode 100644 index 0000000..9b4d999 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode199.java @@ -0,0 +1,87 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.*; +import java.util.function.Consumer; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/17 15:07 + * @注释 + */ +public class LeetCode199 { + + @Test + public void test() { + TreeNode root = TreeNode.constructTree(new Integer[]{1, 2, 3, 4}); + root.printTree(); + System.out.println(new Solution1().rightSideView(root)); + } + + + + class Solution { + /** + * 层次遍历,每层最右边就是结果 + * @param root + * @return + */ + public List rightSideView(TreeNode root) { + List res = new ArrayList<>(); + if (root == null) { + return res; + } + + Deque queue = new LinkedList<>(); + + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode pop = queue.pop(); + // 只加入每层最后一个元素 + if(i==size-1) res.add(pop.val); + if (pop.left != null) { + queue.add(pop.left); + } + if (pop.right != null) { + queue.add(pop.right); + } + } + } + return res; + } + } + + class Solution1 { + + + List res = new ArrayList<>(); + public List rightSideView(TreeNode root) { + if (root == null) { + return res; + } + level(root, 0); + return res; + } + + public void level(TreeNode root, int level) { + + if (root == null) { + return; + } + + // 每层只有一个输出,就是每层最右边的那个 + // 每层都是让右边先进入递归,就能保证获取到最右的数据 + if (res.size() == level) { + res.add(root.val); + } + level(root.right, level + 1); + level(root.left, level + 1); + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2.java new file mode 100644 index 0000000..f4500f2 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2.java @@ -0,0 +1,121 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/20 11:42 + * @注释 + */ +public class LeetCode2 { + + @Test + public void test() { + new Solution1().addTwoNumbers( + /*[9,9,9,9,9,9,9], l2 = [9,9,9,9]*/ + ListNode.listNodeFromArray(new int[]{9, 9, 9, 9, 9, 9, 9}) + , ListNode.listNodeFromArray(new int[]{9, 9, 9, 9}) + ).printList(); + } + + class Solution { + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + return circle(l1, l2, false); + } + + /** + * + * @param l1 + * @param l2 + * @param in 是否进1 + * @return + */ + public ListNode circle(ListNode l1, ListNode l2, boolean in) { + + if (l1 == null && l2 == null && in) { + return new ListNode(1); + } + + if (l1 == null) { + // l2 调用另一个递归方法,不断去判断是否需要在当前节点进1 + return judgeIn(l2, in); + } else if (l2 == null) { + return judgeIn(l1, in); + } + + int val = 0; + int sum = l1.val + l2.val; + if (in) { + val = sum + 1; + }else { + val = sum; + } + + ListNode res = new ListNode(val % 10); + res.next = circle(l1.next, l2.next, val >= 10); + return res; + } + + public ListNode judgeIn(ListNode node, boolean in) { + if (node == null) { + if (in) { + return new ListNode(1); + } + return null; + } + + int val = 0; + if (in) { + val = node.val + 1; + }else { + val = node.val; + } + ListNode res = new ListNode(val % 10); + res.next = judgeIn(node.next, val >= 10); + return res; + } + } + + class Solution1 { + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + ListNode indexA = l1; + ListNode indexB = l2; + boolean flagIn = false; + while (indexA != null && indexB != null) { + int sum = indexA.val + indexB.val; + if (flagIn) { + sum += 1; + } + indexA.val = sum % 10; + if (sum >= 10) { + flagIn = true; + }else { + flagIn = false; + } + + if (indexA.next == null && indexB.next == null && flagIn) { + indexA.next = new ListNode(1); + break; + } + + if (indexA.next == null && indexB.next != null) { + indexA.next = new ListNode(0); + } + if (indexB.next == null && indexA.next != null) { + indexB.next = new ListNode(0); + } + + + indexB = indexB.next; + indexA = indexA.next; + } + + + return l1; + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode20.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode20.java new file mode 100644 index 0000000..06085ee --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode20.java @@ -0,0 +1,46 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +/** + * 括号匹配 + */ +public class LeetCode20 { + + @Test + public void test() { + System.out.println(new Solution().isValid("()[]{}")); + System.out.println(new Solution().isValid("}")); + } + + class Solution { + public boolean isValid(String s) { + Deque stack = new LinkedList<>(); + char[] chars = s.toCharArray(); + for (char aChar : chars) { + if (aChar == '{' || aChar == '[' || aChar == '(') { + stack.push(aChar); + }else if (aChar == ']'){ + if (stack.isEmpty() || stack.pop() != '[') { + return false; + } + }else if (aChar == '}'){ + if (stack.isEmpty() ||stack.pop()!= '{') { + return false; + } + }else if (aChar == ')'){ + if (stack.isEmpty() || stack.pop() != '(') { + return false; + } + } + } + + return stack.isEmpty(); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode203.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode203.java new file mode 100644 index 0000000..e2c8b8f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode203.java @@ -0,0 +1,211 @@ +package cn.whaifree.leetCode.LinkedList; + + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * 链表 + * + * 203. 移除链表元素 + * 示例 1: + + * 输入:head = [1,2,6,3,4,5,6], val = 6 + * 输出:[1,2,3,4,5] + * 示例 2: + * + * 输入:head = [], val = 1 + * 输出:[] + * 示例 3: + * + * 输入:head = [7,7,7,7], val = 7 + * 输出:[] + * + */ +public class LeetCode203 { + + +// /** +// * [6] 6 +// * [] 6 +// * [2] 6 +// * +// * +// * @param head +// * @param val +// * @return +// */ +// public ListNode removeElements(ListNode head, int val) { +// +// // 如果链表只有一个节点或者没有要删除的元素,则直接返回原链表 +// if (head == null) { +// return head; +// } +// if (head.next == null && head.val == val) { +// head = null; +// return head; +// } else if (head.next == null) { +// return head; +// } +// +// // 定义一个指针pre指向head节点 +// // 定义一个指针index指向head.next节点 +// ListNode pre = head; +// ListNode index = head.next; +// +// // 遍历链表,直到index.next为null +// while (index.next != null) { +// +// // 如果index节点的值等于要删除的元素val +// if (index.val == val) { +// +// // 删除该节点 +// pre.next = index.next; +// +// // 将指针index移动到下一个节点 +// index = pre.next; +// +// // 将指针pre移动到下一个节点 +// pre = pre.next; +// +// // 继续遍历链表 +// continue; +// } +// +// // 如果index节点的值不等于要删除的元素val +// index = index.next; +// pre = pre.next; +// } +// // 尾巴节点为val,那就删除尾巴节点 +// if (index.val == val) { +// pre.next = null; +// } +// // 如果头节点的值等于要删除的元素val +// if (head.val == val) { +// head = head.next; +// } +// +// +// // 返回删除元素后的链表 +// return head; +// } + + + public ListNode removeElements1(ListNode head, int val) { + // 找到第一个head不删除的点 删除头结点时另做考虑 + while (head != null && head.val == val) { + head = head.next; + } + // 保证删完后不为空 + if(head==null) + return head; + // + ListNode index = head; + + while (index.next != null) { + if (index.next.val == val) { + index.next = index.next.next; + } else { + index = index.next; + } + } + return head; + } + +// /** +// * 递归 +// * @param head +// * @param val +// * @return +// */ +// public ListNode removeElements(ListNode head, int val) { +// if (head == null) { +// return null; +// } +// head.next = removeElements(head.next, val); +// if (head.next.val == val) { +// return head.next.next; +// } else { +// return head.next; +// } +// } + + + /** + * 递归 + * 1. 停止条件 + * 2. 循环返回值 + * @param head + * @param val + * @return + */ + public ListNode removeElements(ListNode head, int val) { + if (head == null) { + return null; + } + // h + // 6 6 + // 让head 之后的元素交给下个递归 + head.next = removeElements(head.next, val); + if (head.val == val) { + return head.next; + } else { + return head; + } + + // 递归的返回值为head.next,即传入的下一结点; + // 如果匹配就返回当前结点;不匹配,返回的head就是前一结点了。 + // 压栈时的head.next为后一个结点;弹栈时的head.next就位后前一个结点 + } + + public ListNode removeElements3(ListNode head, int val) { + if (head == null) { + return head; + } + + // 1. 获取当前节点 + // 2. 递归next 6 6 + head.next = removeElements3(head.next, val); + if (head.val == val) { + return head.next; + } else { + return head; + } + } + + + /** + * 0 1 2 3 + * 加上虚拟表头节点 + * @param head + * @param val + * @return + */ + public ListNode removeElements7(ListNode head, int val) { + ListNode virtualHead = new ListNode(0, head); + ListNode pre = virtualHead; + ListNode index = head; + head = virtualHead; + while (index != null) { + if (index.val == val) { + pre.next = index.next; + index = pre.next; + }else { + pre = pre.next; + index = index.next; + } + } + return head.next; + } + + + + + @Test + public void Test() { + ListNode listNode = ListNode.listNodeFromArray(new int[]{7,7,7,7}); +// ListNode.printList(listNode); + ListNode listNode1 = removeElements7(listNode, 7); + ListNode.printList(listNode1); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode206.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode206.java new file mode 100644 index 0000000..3f3eeae --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode206.java @@ -0,0 +1,127 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; + +import org.junit.Test; + +import java.util.List; +import java.util.Queue; +import java.util.Stack; + +/** + * 206. 反转链表 + * 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 + * + * 示例 1: + * 输入:head = [1,2,3,4,5] + * 输出:[5,4,3,2,1] + * + * 示例 2: + * 输入:head = [1,2] + * 输出:[2,1] + * 示例 3: + * 输入:head = [] + * 输出:[] + + * 提示: + * + * 链表中节点的数目范围是 [0, 5000] + * -5000 <= Node.val <= 5000 + */ +public class LeetCode206 { + + @Test + public void test() { + ListNode listNode = ListNode.listNodeFromArray(new int[]{1,2,3,4,5}); + ListNode listNode1 = reverseList2(listNode); + ListNode.printList(listNode1); + } + + /** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ + + /** + * 使用栈 + * @param head + * @return + */ + public ListNode reverseList(ListNode head) { + Stack integerStack = new Stack<>(); + ListNode index = head; + while (index!= null) { + integerStack.add(index.val); + index = index.next; + } + + ListNode ansHead = new ListNode(); + index = ansHead; + while (!integerStack.empty()) { + index.next = new ListNode(integerStack.pop()); + index = index.next; + } + return ansHead.next; + } + + + /** + * + * + * 使用三个指针 pre index tmp
+ * - 存储tmp为index的下一个节点,让index指向pre。
+ * pre index tmp
+ * 1 <-- 2 3 --> 4
+ * pre index tmp
+ * 1 <-- 2 3 --> 4
+ * pre index tmp
+ * 1 <-- 2 <-- 3 4
+ * + * 移动指针不一定要index.next, 在指针固定顺序的时候
+ * 可以让tmp=index.next;pre=index;index=tmp
+ * + * @param head + * @return + */ + public ListNode reverseList1(ListNode head) { + ListNode pre = null; + ListNode tmp = null; + ListNode index = head; + while (index != null) { + tmp = index.next; + index.next = pre; + pre = index; + index = tmp; + } + return pre; + } + + + /** + * 递归 + * - 递归 只考虑当前这个部分,把其他的部分扔给下一次递归 + * @param head + * @return + */ + public ListNode reverseList2(ListNode head) { + // 两个逆转 + return reverse(null, head); + } + + public ListNode reverse(ListNode pre, ListNode cur) { + if (cur == null) { + return pre; + } + // 只考虑三个点,1 2逆转,3(tmp 2.next)为下次递归的输入 + ListNode tmp = cur.next; + cur.next = pre; + return reverse(cur, tmp); + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode207.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode207.java new file mode 100644 index 0000000..2cb2142 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode207.java @@ -0,0 +1,100 @@ +package cn.whaifree.leetCode.Graph; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/16 0:02 + * @注释 + */ +public class LeetCode207 { + + @Test + public void test() { + int numCourses = 4; + int[][] prerequisites = {{1, 0},{0,2},{1,3}}; + System.out.println(new Solution().canFinish(numCourses, prerequisites)); + } + class Solution { + public boolean canFinish(int numCourses, int[][] prerequisites) { + List> graph = new ArrayList<>(); + + for (int i = 0; i < numCourses; i++) { + graph.add(new ArrayList<>()); + } + + // 统计入度个数 + int[] inGre = new int[numCourses]; + for (int i = 0; i < prerequisites.length; i++) { + int course = prerequisites[i][0]; + int preCourse = prerequisites[i][1]; + graph.get(preCourse).add(course); + inGre[course]++; + } + + // 对所有入度为0的进入队列 + Deque queue = new ArrayDeque<>(); + for (int i = 0; i < numCourses; i++) { + if (inGre[i] == 0) { + queue.add(i); + } + } + // 出对,并去边 + int exeCount = 0; + while (!queue.isEmpty()) { + Integer pop = queue.pop(); + exeCount++; + // 遍历这个pop点的出边 + List popOut = graph.get(pop); + for (int i = 0; i < popOut.size(); i++) { + int deleteSideNode = popOut.get(i); + inGre[deleteSideNode]--; + if (inGre[deleteSideNode] == 0) { + queue.add(deleteSideNode); + } + } + } + // 如果队列中没有元素了,但还有边,返回false + return exeCount == numCourses; + } + } + + + class Solution1 { + public boolean canFinish(int numCourses, int[][] prerequisites) { + // 统计入度个数 + int[] map = new int[2000]; + for (int i = 0; i < prerequisites.length; i++) { + map[prerequisites[i][0]]++; + } + // 对所有入度为0的进入队列 + Deque queue = new ArrayDeque<>(); + for (int i = 0; i < numCourses; i++) { + if (map[i] == 0) { + queue.add(i); + } + } + // 出对,并去边 + int exeCount = 0; + while (!queue.isEmpty()) { + Integer pop = queue.pop(); + exeCount++; + // 遍历所有的边 + for (int i = 0; i < prerequisites.length; i++) { + if (prerequisites[i][1] == pop) { + int deleteSideNode = prerequisites[i][0]; + map[deleteSideNode]--; + if (map[deleteSideNode] == 0) { + queue.add(deleteSideNode); + } + } + } + } + // 如果队列中没有元素了,但还有边,返回false + return exeCount == numCourses; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode209_2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode209_2.java new file mode 100644 index 0000000..b691c5f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode209_2.java @@ -0,0 +1,128 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * 209. 长度最小的子数组 + * 给定一个含有 n 个正整数的数组和一个正整数 target 。 + * + * 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 + * + * 示例 1: + * + * 输入:target = 7, nums = [2,3,1,2,4,3] + * 输出:2 + * 解释:子数组 [4,3] 是该条件下的长度最小的子数组。 + * 示例 2: + * + * 输入:target = 4, nums = [1,4,4] + * 输出:1 + * 示例 3: + * + * 输入:target = 11, nums = [1,1,1,1,1,1,1,1] + * 输出:0 + * + * 提示: + * + * 1 <= target <= 109 + * 1 <= nums.length <= 105 + * 1 <= nums[i] <= 105 + * + * 进阶: + * + * 如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。 + */ +public class LeetCode209_2 { + + /** + * 暴力求解,会超时 + * @param target + * @param nums + * @return + */ + public int minSubArrayLen(int target, int[] nums) { + + int minLength = Integer.MAX_VALUE; + for (int i = 0; i < nums.length; i++) { + int sum = 0; + for (int j = i; j < nums.length; j++) { + sum += nums[j]; + if (sum >= target) { + minLength = Math.min(minLength, j - i + 1); + break; + } + /** + * if (sum >= target && j - i +1 < minLength) { + * minLength = j - i + 1; + * break; + * } + */ + } + } + + + return minLength == Integer.MAX_VALUE ? 0 : minLength; + } + + public int minSubArrayLen1(int target, int[] nums) { + int left = 0; + int right = 0; + int sum = 0; + int ans = Integer.MAX_VALUE; + while (right < nums.length ) { + sum += nums[right]; + // 窗口内,找到最小子串 + while (sum >= target) { + ans = Math.min(ans, right - left + 1); + sum -= nums[left++]; + } + right++; + } + return ans == Integer.MAX_VALUE ? 0 : ans; + } + + + + class Solution { + /** + * 前缀和做法 + * @param target + * @param nums + * @return + */ + public int minSubArrayLen(int target, int[] nums) { + // 求前缀和 + int length = nums.length; + int[] preSum = new int[length + 1]; + for (int i = 1; i < preSum.length; i++) { + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + // 2,3,1,2,4,3 + // 因为每个元素都是正数,所以preSum是递增的,可以用二分查找 + int minLengthFillSolution = Integer.MAX_VALUE; + for (int i = 1; i < preSum.length; i++) { + // 从0开始查找 + int fill = target + preSum[i - 1]; + int intervalEnd = Arrays.binarySearch(preSum, fill); // 没找到就会返回负数 + if (intervalEnd < 0) { + intervalEnd = -intervalEnd - 1; // 防止查出来的是负数 + } + // 这个区间如果合理,就可能是正常的区间 + if (intervalEnd <= length) + minLengthFillSolution = Math.min(minLengthFillSolution, intervalEnd - (i - 1)); + // 注意区分下标 intervalEnd和i-1 前缀和为fill和target + } + return minLengthFillSolution == Integer.MAX_VALUE ? 0 : minLengthFillSolution; + } + } + + @Test + public void list() { + System.out.println(new Solution().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + +// System.out.println(minSubArrayLen1(5, new int[]{2,3,6})); + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode21.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode21.java new file mode 100644 index 0000000..2ecf941 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode21.java @@ -0,0 +1,79 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/4 13:05 + * @注释 + */ +public class LeetCode21 { + + + @Test + public void test() { + new Solution1().mergeTwoLists( + ListNode.listNodeFromArray(new int[]{5}), + ListNode.listNodeFromArray(new int[]{1, 2, 4}) + ).printList(); + } + + class Solution { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + if (list2 == null) { + return list1; + } + if (list1 == null) { + return list2; + } + + ListNode pre = new ListNode(-1); // 标记结果头部 + ListNode preIndex = pre; // 标记需要添加的位置 + // 合并有序链表 + ListNode indexA = list1; + ListNode indexB = list2; + while (indexA != null && indexB != null) { + if (indexA.val <= indexB.val) { + preIndex.next = indexA; + indexA = indexA.next; + }else { + preIndex.next = indexB; + indexB = indexB.next; + } + preIndex = preIndex.next; + } + + if (indexA == null) { + preIndex.next = indexB; + }else { + preIndex.next = indexA; + } + + return pre.next; + } + } + + + class Solution1 { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + + if (list1 == null) { + return list2; + } + if (list2 == null) { + return list1; + } + + if (list1.val < list2.val) { + list1.next = mergeTwoLists(list1.next, list2); + return list1; + }else { + list2.next = mergeTwoLists(list1, list2.next); + return list2; + } + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode210.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode210.java new file mode 100644 index 0000000..b7b2858 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode210.java @@ -0,0 +1,98 @@ +package cn.whaifree.leetCode.Graph; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/16 0:44 + * @注释 + */ +public class LeetCode210 { + @Test + public void test() { + int[][] prerequisites = {{1,0},{2,0},{3,1},{3,2}}; + int[] res = new Solution().findOrder(4, prerequisites); + System.out.println(Arrays.toString(res)); + } + + public int[] findOrder(int numCourses, int[][] prerequisites) { + if (numCourses == 0) return new int[0]; + int[] inDegrees = new int[numCourses]; + + + // 建立入度表 + for (int[] p : prerequisites) { + inDegrees[p[0]]++; // 记录每个节点的入度 + } + // 入度为0的节点队列 + Queue queue = new LinkedList<>(); + for (int i = 0; i < inDegrees.length; i++) { + if (inDegrees[i] == 0) queue.offer(i); // 入度为 0 的节点可以进行执行 + } + int count = 0; // 记录可以执行的任务数 + int[] res = new int[numCourses]; // 完整拓扑排序的执行过程 + + // 根据提供的可以执行的任务(入度为 0),删除入度为 0 的节点 + while (!queue.isEmpty()){ + int curr = queue.poll(); // 拿到一个可以执行的任务 + res[count++] = curr; // 这个任务可以执行,作为下一次执行的节点 + for (int[] p : prerequisites) { + if (p[1] == curr){ // {a,b} 表示 a 依赖 b b-->a + inDegrees[p[0]]--; + if (inDegrees[p[0]] == 0) queue.offer(p[0]); + } + } + } + if (count == numCourses) return res; + return new int[0]; + } + + + class Solution { + public int[] findOrder(int numCourses, int[][] prerequisites) { + List> graph = new ArrayList<>(); + for (int i = 0; i < numCourses; i++) { + graph.add(new ArrayList<>()); + } + int[] inGre = new int[numCourses]; + + Deque deque = new LinkedList<>(); + for (int[] prerequisite : prerequisites) { + int course = prerequisite[0]; + int pre = prerequisite[1]; + inGre[course]++; + graph.get(pre).add(course); + } + + for (int i = 0; i < inGre.length; i++) { + if (inGre[i] == 0) { + deque.add(i); + } + } + + int exec = 0; + int[] res = new int[numCourses]; + while (!deque.isEmpty()) { + Integer exe = deque.pop(); + res[exec] = exe; + exec++; + List in = graph.get(exe); + for (int into = 0; into < in.size(); into++) { + Integer intoNode = in.get(into); + inGre[intoNode]--; + if (inGre[intoNode] == 0) { + deque.add(intoNode); + } + } + } + + if (numCourses == exec) { + return res; + } + return new int[0]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode215.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode215.java new file mode 100644 index 0000000..74a2a43 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode215.java @@ -0,0 +1,518 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.io.*; +import java.util.*; +import java.util.function.BiConsumer; + +import static org.junit.Assert.assertArrayEquals; + +public class LeetCode215 { + + public static void main(String[] args) throws FileNotFoundException { + String name = "/Users/kyriewhluo/IdeaProjects/tsf/tsf-dispatch/src/main/resources/tsf-dispatch.yml"; + // 读取每一行 + HashMap> map = new HashMap<>(); + try (BufferedReader reader = new BufferedReader(new FileReader(name))) { + String line; + while ((line = reader.readLine()) != null) { + if (line.contains("tsf-resource")) { + String[] split = line.split("/"); + String key = "/" + split[1] + "/" + split[2]; + List orDefault = map.getOrDefault(key, new ArrayList<>()); + orDefault.add(line); + map.put(key, orDefault); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + map.forEach(new BiConsumer>() { + @Override + public void accept(String s, List strings) { + System.out.println("# key:" + s); + System.out.println("# size:" + strings.size()); + for (String string : strings) { + System.out.println(string); + } + + for (int i = 0; i < 3; i++) { + System.out.println(); + } + } + }); + } + + + @Test + public void sort_EmptyArray_ShouldHandleGracefull3y() { + int[] nums = {3,2,1,5,6,4}; + System.out.println(new Solution5().findKthLargest(nums, 2)); + System.out.println(Arrays.toString(nums)); + + } + + class Solution5 { + + /** + * 快速排序,某次base放对位置后,左边刚刚好有k-1个,就找到了 + * @param nums + * @param k + * @return + */ + public int findKthLargest(int[] nums, int k) { + return sort(nums, 0, nums.length - 1, k); + } + + /** + * 快速排序思路,对前n-1个进行不断交换,最后把基准替换到交接点 + * @param nums + * @param start + * @param end + * @param k + * @return + */ + public int sort(int[] nums, int start, int end, int k) { + + if (start > end) { + return nums[end]; + } + + int q = new Random().nextInt(end - start + 1) + start; + + swap(nums, q, end); + + int base = nums[end]; + int left = start; + int right = end; + while (left < right) { + + //从左往右遍历,当左指针指向的元素小于等于基数时,i++。左指针持续向右移动 + while (nums[left] >= base && left < right) { + left++; + } + //从右往左遍历,当右指针指向的元素大于等于基数时,j--。右指针持续向左移动 + while (nums[right] <= base && left < right) { + right--; + } + if (left < right) { + //当左右两个指针停下来时,交换两个元素 + swap(nums, left, right); + } + } + swap(nums, left, end); + + // 从大到小排序,如果左边k-1个,则left就是第k个,左边k-1个比他大 + if (left == k - 1) { + return nums[left]; + } + // 左边的数量太少了,往右边找 + if (left < k - 1) { + return sort(nums, left + 1, end, k); + } + return sort(nums, start, left - 1, k); + + } + public void swap(int[] heap, int start, int end) { + int temp = heap[start]; + heap[start] = heap[end]; + heap[end] = temp; + } + } + + + @Test + public void sort_EmptyArray_ShouldHandleGracefully8() { + + // [3,2,3,1,2,4,5,5,6], k = 4 + int[] nums = {5,4,3,2,1}; + System.out.println(new Solution4().findKthLargest(nums, 2)); + } + + class Solution4 { + public int findKthLargest(int[] nums, int k) { + for (int i = nums.length - 1; i > 0; i--) { + shiftUp(nums, i); + } + System.out.println(Arrays.toString(nums)); + return nums[nums.length - k]; + } + + public void shiftUp(int[] heap, int end) { + int parent = (end - 1) / 2; + while (parent >= 0) { + int left = parent * 2 + 1; + int right = parent * 2 + 2; + int k = parent; + if (left <= end &&heap[left] > heap[k]) { + k = left; + } + if (right <= end && heap[right] > heap[k]) { + k = right; + } + swap(heap, parent, k); + parent--; + } + swap(heap, 0, end); + } + + public void swap(int[] heap, int start, int end) { + int temp = heap[start]; + heap[start] = heap[end]; + heap[end] = temp; + } + } + + @Test + public void main() + { + int i = 0; + while (true) { + i++; + } +// +// int[] nums = {3,2,1,5,6,4}; +// int k = 2; +// Solution solution = new Solution(); +// int i = solution.findKthLargest(nums, k); +// System.out.println(i); + } + +// @Test +// public void test188() +// { +// new sol().findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 3); +// +// +// } + +// class sol{ +// /** +// * 3 +// * / \ +// * / \ +// * 5 -2147483648 +// * / +// * 2 右边那个有问题,所以不行 +// * @param nums +// * @param k +// * @return +// */ +// public int findKthLargest(int[] nums, int k) { +// Heap heap = new Heap(k); +// for (int num : nums) { +// heap.add(num); +// } +// return 1; +// } +// } + + +// class Heap{ +// +// +// int[] heap = null; +// +// public Heap(int k) { +// this.heap = new int[k + 1]; +// Arrays.fill(this.heap, Integer.MIN_VALUE); +// } +// +// public void add(int num) { +// heap[heap.length - 1] = num; +// shiftUp(heap, heap.length - 1); +// } +// +// +// /** +// * 固定长度的,让其 shiftUp +// * @param nums +// * @param numIndex 将 numsIndex 位置上移 +// */ +// public void shiftUp(int[] nums, int numIndex) { +// int k = numIndex; +// while (k > 0) { +// int parent = (k - 1) / 2; +//// if (nums[numIndex] < nums[parent]) { // 小顶堆 +// if (nums[k] > nums[parent]) { // 大顶堆 +// // 小顶堆,小的上移 +// swap(nums, parent, k); +// k = parent; +// }else { +// break; +// } +// TreeNode.constructTreeByArrayWithInteger(nums); +// } +// +// } +// +// public void swap(int[] nums, int start, int end) { +// int temp = nums[start]; +// nums[start] = nums[end]; +// nums[end] = temp; +// } +// +// } + + class Solution { + public int findKthLargest(int[] nums, int k) { + + + // 小顶堆 + PriorityQueue priorityQueue = new PriorityQueue<>(new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o1 - o2; + } + }); + for (int num : nums) { + priorityQueue.offer(num); + if (priorityQueue.size() > k) { + priorityQueue.poll(); + } + } + + return priorityQueue.poll(); + } + } + + @Test + public void test1() + { + + int[] nums = {3,2,1,5,6,4}; + int k = 2; + Solution1 solution = new Solution1(); + int i = solution.findKthLargest(nums, k); + System.out.println(i); + } + + class Solution1 { + public int findKthLargest(int[] nums, int k) { + sort(nums, nums.length - 1); + + return nums[k - 1]; + } + + /** + * 堆排序思路: + * 1. 依次遍历非叶节点 nonLeaf = (end - 1) / 2; -- + * 选取左右两边比他大的替换上来,不断替换直到最上面是最大的 + * 2. 把最大的堆顶移动到最后,确定一个最大值 + * @param nums + * @param end + */ + public void sort(int[] nums, int end) { + if (end <= 0) { + return; + } + int heapSize = nums.length; + for (int i = heapSize / 2; i >= 0; --i) { + int l = i * 2 + 1, r = i * 2 + 2, largest = i; + if (l < heapSize && nums[l] > nums[largest]) { + largest = l; + } + if (r < heapSize && nums[r] > nums[largest]) { + largest = r; + } + if (largest != i) { + swap(nums, i, largest); + sort(nums, heapSize - 1); + } + } + swap(nums, 0, end); + } + + public void swap(int[] nums, int start, int end) { + int temp = nums[start]; + nums[start] = nums[end]; + nums[end] = temp; + } + + + } + + + + + @Test + public void sort_EmptyArray_ShouldHandleGracefully() { + int[] nums = {}; + sort(nums); + assertArrayEquals(new int[0], nums); + } + + @Test + public void sort_NaturalNumberArray_ShouldSortInAscendingOrder() { + int[] nums = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}; + sort(nums); + assertArrayEquals(new int[]{1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9}, nums); + } + + @Test + public void sort_IntegerArray_ShouldSortInAscendingOrder() { + int[] nums = {10, -1, 2, 5, 0, 6, -3, 4}; + sort(nums); + assertArrayEquals(new int[]{-3, -1, 0, 2, 4, 5, 6, 10}, nums); + } + + @Test + public void sort_SingleElementArray_ShouldRemainUnchanged() { + int[] nums = {5}; + sort(nums); + assertArrayEquals(new int[]{5}, nums); + } + + @Test + public void sort_DuplicateElementsArray_ShouldSortInAscendingOrder() { + int[] nums = {4, 2, 2, 8, 3, 3, 1}; + sort(nums); + assertArrayEquals(new int[]{1, 2, 2, 3, 3, 4, 8}, nums); + } + + @Test + public void sort_NegativeNumberArray_ShouldSortInAscendingOrder() { + int[] nums = {-1, -2, -3, -4, -5}; + System.out.println(Arrays.toString(new Solution3().sortArray(nums))); + } + + class Solution3 { + public int[] sortArray(int[] nums) { + sort(nums, nums.length - 1); + return nums; + } + + /** + * 堆排序思路: + * 1. 依次遍历非叶节点 nonLeaf = (end - 1) / 2; -- + * 选取左右两边比他大的替换上来,不断替换直到最上面是最大的 + * 2. 把最大的堆顶移动到最后,确定一个最大值 + * @param nums + * @param end + */ + public void sort(int[] nums, int end) { + if (end <= 0) { + return; + } + + int nonLeaf = (end - 1) / 2; + while (nonLeaf >= 0) { + + + int left = 2 * nonLeaf + 1; + int right = 2 * nonLeaf + 2; + + + int maxIn = nonLeaf; // 父子三个节点的最大值 + if (left <= end && nums[maxIn] < nums[left]) { + maxIn = left; + } + if (right <= end && nums[maxIn] < nums[right]) { + maxIn = right; + } + swap(nums, nonLeaf, maxIn); + + + +// // noleaf至少有一个子节点 +// if (left <= end &&right <= end) { +// if (nums[left] < nums[right]) { +// if (nums[right] > nums[nonLeaf]) { +// swap(nums, nonLeaf, right); +// } +// }else { +// if (nums[left] > nums[nonLeaf]) { +// swap(nums, nonLeaf, left); +// } +// } +// } else { +// // 只有左边一个节点 +// if (nums[left] > nums[nonLeaf]) { +// swap(nums, nonLeaf, left); +// } +// } + nonLeaf--; + } + swap(nums, 0, end ); + sort(nums, end - 1); + } + + public void swap(int[] nums, int start, int end) { + int temp = nums[start]; + nums[start] = nums[end]; + nums[end] = temp; + } + } + + + /** + * 所有非叶子节点x(自 n/2 开始,表示下面都是叶子节点)找到子节点中的最大值,如果比x 还大,swap。再排序下一个非叶子节点 + */ + public void sort(int[] nums) { + sort(nums, nums.length - 1); + System.out.println(Arrays.toString(nums)); + } + + /** + * 堆排序思路: + * 1. 依次遍历非叶节点 nonLeaf = (end - 1) / 2; -- + * 选取左右两边比他大的替换上来,不断替换直到最上面是最大的 + * 2. 把最大的堆顶移动到最后,确定一个最大值 + * @param nums + * @param end + */ + public void sort(int[] nums, int end) { + if (end <= 0) { + return; + } + + int nonLeaf = (end - 1) / 2; + while (nonLeaf >= 0) { + + + int left = 2 * nonLeaf + 1; + int right = 2 * nonLeaf + 2; + + + int maxIn = nonLeaf; // 父子三个节点的最大值 + if (left <= end && nums[maxIn] < nums[left]) { + maxIn = left; + } + if (right <= end && nums[maxIn] < nums[right]) { + maxIn = right; + } + swap(nums, nonLeaf, maxIn); + + + +// // noleaf至少有一个子节点 +// if (left <= end &&right <= end) { +// if (nums[left] < nums[right]) { +// if (nums[right] > nums[nonLeaf]) { +// swap(nums, nonLeaf, right); +// } +// }else { +// if (nums[left] > nums[nonLeaf]) { +// swap(nums, nonLeaf, left); +// } +// } +// } else { +// // 只有左边一个节点 +// if (nums[left] > nums[nonLeaf]) { +// swap(nums, nonLeaf, left); +// } +// } + nonLeaf--; + } + swap(nums, 0, end ); + sort(nums, end - 1); + } + + public void swap(int[] nums, int start, int end) { + int temp = nums[start]; + nums[start] = nums[end]; + nums[end] = temp; + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode216.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode216.java new file mode 100644 index 0000000..2f7b01a --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode216.java @@ -0,0 +1,81 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/2 8:22 + * @注释 + */ +public class LeetCode216 { + + @Test + public void test() { + Solution solution = new Solution(); + solution.combinationSum3(9, 45).forEach( + list -> { + System.out.println(list); + } + ); + } + + class Solution { + + List> res = new LinkedList<>(); + List path = new ArrayList<>(); + int sum = 0; + /** + * 相加之和为n的k个数的组合 + * @param k + * @param n + * @return + */ + public List> combinationSum3(int k, int n) { + circle(1, 9, n, k); + return res; + } + + public void circle(int start, int end, int n, int k) { + if (path.size() == k && sum == n) { + res.add(new ArrayList<>(path)); + return; + } + + // 1. 如果sum>n了,证明往后加只会更大,因为都是正数,就不再继续了 + // sum>n + // + // 2. 如果 9个数要9个数 + // 已经选择size + // 还需选择k-size + // 可以选择的数end-start + // 可以选择的数<还需选择的数 end-start n) { + path.remove(path.size() - 1); + sum -= i; + return; + } + circle(i + 1, end, n, k); + path.remove(path.size() - 1); + sum -= i; + } + } + } + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode222.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode222.java new file mode 100644 index 0000000..5dd91fb --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode222.java @@ -0,0 +1,73 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/22 19:05 + * @注释 + */ +public class LeetCode222 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 3, 4, 5, 6}); + treeNode.printTree(); + System.out.println(new Solution1().countNodes(treeNode)); + } + + class Solution { + + + public int countNodes(TreeNode root) { + return inLevel(root); + } + + public int inLevel(TreeNode node) { + if (node==null) return 0; + int left = inLevel(node.left) + 1; + int right = inLevel(node.right) ; + return left + right; + } + } + + class Solution1 { + + + public int countNodes(TreeNode root) { + return inLevel(root); + } + + public int inLevel(TreeNode node) { + if (node == null) { + return 0; + } + // 计算左边深度 + int leftDepth = 0; + TreeNode leftNode = node.left; + while (leftNode != null) { + leftNode = leftNode.left; + leftDepth++; + } + + // 计算右边深度 + int rightDepth = 0; + TreeNode rightNode = node.right; + while (rightNode != null) { + rightNode = rightNode.right; + rightDepth++; + } + + // 如果两变深度一样,那么该树是完全二叉树 + if (leftDepth == rightDepth) { + return (2 << leftDepth) - 1; + } + // 如果两边深度不一样,递归左右子节点+1 + return inLevel(node.right) + inLevel(node.left) + 1; + + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode225.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode225.java new file mode 100644 index 0000000..68c71c3 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode225.java @@ -0,0 +1,174 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.Queue; + +/** + * 225. 用队列实现栈 + * + * 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 + * + * 实现 MyStack 类: + * + * void push(int x) 将元素 x 压入栈顶。 + * int pop() 移除并返回栈顶元素。 + * int top() 返回栈顶元素。 + * boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。 + * + * 注意: + * + * 你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。 + * 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。 + * + * 示例: + * + * 输入: + * ["MyStack", "push", "push", "top", "pop", "empty"] + * [[], [1], [2], [], [], []] + * 输出: + * [null, null, null, 2, 2, false] + * + * 解释: + * MyStack myStack = new MyStack(); + * myStack.push(1); + * myStack.push(2); + * myStack.top(); // 返回 2 + * myStack.pop(); // 返回 2 + * myStack.empty(); // 返回 False + * + */ +public class LeetCode225 { + + @Test + public void test() { + + Deque objects = new LinkedList<>(); + objects.add(1); + objects.add(2); + objects.push(3); + System.out.println(objects.pop()); +// objects.forEach(x -> System.out.println(x)); + + + MyStack1 myStack = new MyStack1(); + myStack.push(1); + myStack.push(2); + myStack.push(3); + + System.out.println(myStack.top()); + System.out.println(myStack.pop()); + + } + + + /** + * 每次入栈就加入其中的非空队列 + * 出栈就全部移动到另一个队列,并获取最后一个元素 + * + * 队列用add // add 尾巴进 + * 栈用push // push 头进 + * pop 头出 + * + * - 栈 push pop + * - 队列 add pop + */ + class MyStack { + + Deque queue1; + Deque queue2; + + public MyStack() { + queue1 = new LinkedList<>(); + queue2 = new LinkedList<>(); + } + + public void push(int x) { + if (!queue1.isEmpty()) { + queue1.add(x); + } else { + queue2.add(x); + } + } + + public int pop() { + if (!queue1.isEmpty()) { + // 将queue全部导入queue2,并获取最后一个元素返回 + while (queue1.size()!=1) { + queue2.add(queue1.pop()); + } + return queue1.pop(); + } else { + // 将queue2全部导入queue1,并获取最后一个元素返回 + while (queue2.size()!=1) { + queue1.add(queue2.pop()); + } + return queue2.pop(); + } + } + + public int top() { + if (!queue1.isEmpty()) { + // 将queue全部导入queue2,并获取最后一个元素返回 + while (queue1.size()>1) { + queue2.add(queue1.pop()); + } + Integer pop = queue1.pop(); + queue2.add(pop); + return pop; + } else { + // 将queue2全部导入queue1,并获取最后一个元素返回 + while (queue2.size()>1) { + queue1.add(queue2.pop()); + } + + Integer pop = queue2.pop(); + queue1.add(pop); + return pop; + } + } + + public boolean empty() { + return queue1.isEmpty() && queue2.isEmpty(); + } + } + + + /** + * push 的时候 把其替换到头部 + */ + class MyStack1 { + + Deque queue; + + + public MyStack1() { + queue = new LinkedList<>(); + } + + public void push(int x) { + queue.add(x); + int size = queue.size(); + while (size != 1) { + queue.add(queue.pop()); + size--; + } + } + + public int pop() { + return queue.pop(); + } + + public int top() { + return queue.peek(); + } + + public boolean empty() { + return queue.isEmpty(); + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode226.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode226.java new file mode 100644 index 0000000..f7f8182 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode226.java @@ -0,0 +1,148 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/19 14:54 + * @注释 + */ +public class LeetCode226 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 3, 4, 5}); + treeNode.printTree(); + TreeNode treeNode1 = new Solution2().invertTree(treeNode); + treeNode1.printTree(); + } + + class Solution { + public TreeNode invertTree(TreeNode root) { + reverse(root); + return root; + } + + public void reverse(TreeNode root) { + if (root == null) { + return; + } + swap(root); + invertTree(root.left); + invertTree(root.right); + } + + public void swap(TreeNode root) { + TreeNode tmp = root.left; + root.left = root.right; + root.right = tmp; + } + } + + class Solution1 { + /** + * 层次遍历 + * @param root + * @return + */ + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return root; + } + Deque queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + TreeNode pop = queue.pop(); + swap(pop); + if (pop.right != null) { + queue.add(pop.right); + } + if (pop.left != null) { + queue.add(pop.left); + } + } + return root; + } + + + public void swap(TreeNode root) { + TreeNode tmp = root.left; + root.left = root.right; + root.right = tmp; + } + } + + class Solution2 { + /** + * 先序遍历 + * @param root + * @return + */ + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return root; + } + Deque stack = new LinkedList<>(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode pop = stack.pop(); + swap(pop); + if (pop.right != null) { + stack.push(pop.right); + } + if (pop.left != null) { + stack.push(pop.left); + } + + } + return root; + } + + + public void swap(TreeNode root) { + TreeNode tmp = root.left; + root.left = root.right; + root.right = tmp; + } + } + + class Solution3 { + /** + * 先序遍历 + * @param root + * @return + */ + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return root; + } + Deque stack = new LinkedList<>(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode pop = stack.pop(); + swap(pop); + if (pop.right != null) { + stack.push(pop.right); + } + if (pop.left != null) { + stack.push(pop.left); + } + + } + return root; + } + + + public void swap(TreeNode root) { + TreeNode tmp = root.left; + root.left = root.right; + root.right = tmp; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode228.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode228.java new file mode 100644 index 0000000..5197d06 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode228.java @@ -0,0 +1,87 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.AsynchronousFileChannel; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/22 14:56 + * @注释 + */ +public class LeetCode228 { + + public static void main(String[] args) throws IOException { + AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Paths.get("D:\\project\\LeetCode\\README.md"), StandardOpenOption.READ); + ByteBuffer buffer = ByteBuffer.allocate(1024); + Future result = fileChannel.read(buffer, 0); + while (!result.isDone()) { + // do something + } + } + + @Test + public void test() { + int[] nums = {0, 2}; + System.out.println(new Solution().summaryRanges(nums)); + } + + class Solution { + +// public List summaryRanges(int[] nums) { +// List path = new ArrayList<>(); +// List res = new ArrayList<>(); +// for (int i = 1; i < nums.length; i++) { +// if (nums[i] != nums[i - 1]) { +// StringBuilder str = new StringBuilder(); +// for (int j = 0; j < path.size()-1; j++) { +// str.append(path.get(j)); +// str.append("->"); +// } +// str.append(path.get(path.size() - 1)); +// path.clear(); +// } +// path.add(String.valueOf(nums[i])); +// } +// } + public List summaryRanges(int[] nums) { + + + List res = new ArrayList<>(); + + int left = 0; + int right = 1; + while (right < nums.length) { + if (nums[right] != nums[right - 1] + 1) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(nums[left]); + if (left != right - 1) { + stringBuilder.append("->"); + stringBuilder.append(nums[right - 1]); + } + res.add(stringBuilder.toString()); + left = right; + } + right++; + } + if (left < nums.length) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(nums[left]); + if (left != right - 1) { + stringBuilder.append("->"); + stringBuilder.append(nums[right - 1]); + } + res.add(stringBuilder.toString()); + } + return res; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode23.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode23.java new file mode 100644 index 0000000..910aa3c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode23.java @@ -0,0 +1,129 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/5 12:00 + * @注释 + */ +public class LeetCode23 { + + @Test + public void test() + { + new Solution2().mergeKLists( + new ListNode[]{ + ListNode.listNodeFromArray(new int[]{}), + ListNode.listNodeFromArray(new int[]{1, 3, 4}), + ListNode.listNodeFromArray(new int[]{2, 6}) + } + ).printList(); + } + + class Solution { + public ListNode mergeKLists(ListNode[] lists) { + if (lists.length == 0) { + return null; + } + List arrayList = new ArrayList<>(Arrays.asList(lists)); + return merge(arrayList); + } + + public ListNode merge(List lists) { + // 删除list中所有null + // 使用removeIf()方法删除所有null元素 + lists.removeIf(Objects::isNull); + + if (lists.size() == 0) { + return null; + } + + int minIndex = 0; + // 找到最小的返回 + // 这个最小的的下一个就是递归的 + + // 找到最小的头节点的位置 + for (int i = 0; i < lists.size(); i++) { + if (lists.get(minIndex).val > lists.get(i).val) { + minIndex = i; + } + } + ListNode minNode = lists.get(minIndex); + // 去掉本节点 + lists.set(minIndex, minNode.next); + minNode.next = merge(lists); + return minNode; + + } + + } + + + class Solution1 { + public ListNode mergeKLists(ListNode[] lists) { + for (int i = 1; i < lists.length; i++) { + lists[i] = merge(lists[i], lists[i - 1]); + } + return lists[lists.length - 1]; + } + + public ListNode merge(ListNode one, ListNode two) { + if (one == null) { + return two; + } else if (two == null){ + return one; + } + + if (one.val < two.val) { + one.next = merge(one.next, two); + return one; + }else { + two.next = merge(one, two.next); + return two; + } + } + + } + + class Solution2 { + // 时间复杂度: + // O(nlogk),其中 k 为 lists的长度,n 为所有链表的节点数之和。 + + //著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + public ListNode mergeKLists(ListNode[] lists) { + + + PriorityQueue queue = new PriorityQueue<>(new Comparator() { + @Override + public int compare(ListNode o1, ListNode o2) { + return o1.val - o2.val; + } + }); + + for (ListNode list : lists) { + if (list!=null) queue.add(list); + } + + ListNode head = new ListNode(-1); + ListNode headIndex = head; + while (!queue.isEmpty()) { + ListNode poll = queue.poll(); + headIndex.next = poll; + headIndex = headIndex.next; + if (poll.next != null) { + queue.add(poll.next); + } + } + + return head.next; + } + + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode230.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode230.java new file mode 100644 index 0000000..6e85840 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode230.java @@ -0,0 +1,48 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/3 17:00 + * @注释 + */ +public class LeetCode230 { + @Test + public void test() { + + + + + + TreeNode treeNode = TreeNode.constructTreeByArray(5,3,6,2,4,null,null,1); + System.out.println(new Solution().kthSmallest(treeNode, 3)); + } + + class Solution { + int res = 0; + public int kthSmallest(TreeNode root, int k) { + if (root == null) { + return -1; + } + int left = kthSmallest(root.left, k); + if (left != -1) { + return left; + } + res++; + if (res == k) { + return root.val; + } + int right = kthSmallest(root.right, k); + if (right != -1) { + return right; + } + return -1; + } + + + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode232.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode232.java new file mode 100644 index 0000000..5564d95 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode232.java @@ -0,0 +1,122 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.Queue; + +/** + * 232. 用栈实现队列 + * + * 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): + * + * 实现 MyQueue 类: + * + * void push(int x) 将元素 x 推到队列的末尾 + * int pop() 从队列的开头移除并返回元素 + * int peek() 返回队列开头的元素 + * boolean empty() 如果队列为空,返回 true ;否则,返回 false + * 说明: + * + * 你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 + * 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。 + * + * 示例 1: + * + * 输入: + * ["MyQueue", "push", "push", "peek", "pop", "empty"] + * [[], [1], [2], [], [], []] + * 输出: + * [null, null, null, 1, 1, false] + * + * 解释: + * MyQueue myQueue = new MyQueue(); + * myQueue.push(1); // queue is: [1] + * myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) + * myQueue.peek(); // return 1 + * myQueue.pop(); // return 1, queue is [2] + * myQueue.empty(); // return false + * + * + * 提示: + * + * 1 <= x <= 9 + * 最多调用 100 次 push、pop、peek 和 empty + * 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作) + * + * + * 进阶: + * + * 你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。 + */ +public class LeetCode232 { + + @Test + public void test() { + MyQueue myQueue = new MyQueue(); + System.out.println(myQueue.empty()); + myQueue.push(1); + myQueue.push(2); + myQueue.push(3); + myQueue.push(4); + System.out.println(myQueue.peek()); + System.out.println(myQueue.pop()); + System.out.println(myQueue.empty()); + + + } + + + /** + 你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 + 一个空的队列不会调用 pop 或者 peek 操作 + + * // 进队列,全部放到Enter栈 + * // 一旦要出栈,检查Out栈有没有,如果没有将目前Enter栈全部弹到Out栈,再弹出第一个 + * + */ + class MyQueue { + + Deque stackEnter; + Deque stackOut; + + public MyQueue() { + this.stackEnter = new LinkedList<>(); + this.stackOut = new LinkedList<>(); + } + + public void push(int x) { + stackEnter.push(x); + } + + public int pop() { + int peek = peek(); + stackOut.pop(); + return peek; + } + + public int peek() { + if (stackOut.isEmpty()) { + while (!stackEnter.isEmpty()) { + stackOut.push(stackEnter.pop()); + } + } + // 不会对空操作 + return stackOut.peek(); + } + + public boolean empty() { + return stackEnter.isEmpty() && stackOut.isEmpty(); + } + } + +/** + * Your MyQueue object will be instantiated and called as such: + * MyQueue obj = new MyQueue(); + * obj.push(x); + * int param_2 = obj.pop(); + * int param_3 = obj.peek(); + * boolean param_4 = obj.empty(); + */ +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode234.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode234.java new file mode 100644 index 0000000..1284a5a --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode234.java @@ -0,0 +1,105 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.function.BiConsumer; + +public class LeetCode234 { + + + public static void main(String[] args) throws InterruptedException { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + for (int i = 0; i < 10; i++) { + map.put("1", 1); + } + + CountDownLatch countDownLatch = new CountDownLatch(10); + + new Thread(new Runnable() { + @Override + public void run() { + map.forEach( + new BiConsumer() { + @Override + public void accept(String s, Integer integer) { + System.out.println(s + ":" + integer); + } + } + ); + } + }).start(); + + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 10; i++) { + map.put("i" + i, i); + countDownLatch.countDown(); + } + } + }).start(); + + countDownLatch.await(); + System.out.println(map.size()); + } + + + @Test + public void test() + { + ListNode listNode = ListNode.listNodeFromArray(new int[]{1, 3, 3,2, 1}); + System.out.println(new Solution().isPalindrome(listNode)); + } + /** + * 1. 截取一半 + * - 逆转、对比 + * 2. 输出到list中,再回问判断 + * 3. + */ + + class Solution { + public boolean isPalindrome(ListNode head) { + int len = 0; + ListNode index = head; + while (index != null) { + len++; + index = index.next; + } + + index = head; + for (int i = 0; i < len / 2; i++) { + index = index.next; + } + + ListNode newHead = reverseList(index); + + + ListNode A = head; + ListNode B = newHead; + while (B != null) { + if (A.val != B.val) { + return false; + } + A = A.next; + B = B.next; + } + return true; + } + + private ListNode reverseList(ListNode head) { + ListNode prev = null; + ListNode curr = head; + while (curr != null) { + ListNode nextTemp = curr.next; + curr.next = prev; + prev = curr; + curr = nextTemp; + } + return prev; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode235.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode235.java new file mode 100644 index 0000000..61a1d0d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode235.java @@ -0,0 +1,66 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/30 21:10 + * @注释 + */ +public class LeetCode235 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(6,2,8,0,4,7,9,null,null,3,5); + + new Solution().lowestCommonAncestor(treeNode, treeNode.left.right, treeNode.left).printTree(); + } + + class Solution { + /** + * 1. p,q在两边,直接返回 + * 2. pq在左边,向左递归 + * 3. pq在右边,向右递归 + * @param root + * @param p + * @param q + * @return + */ + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { +// if (root == null) { +// return null; +// } +// if (root == p || root == q) { +// // 找到元素 +// return root; +// } + +// if (p.val < root.val && q.val > root.val) { +// return root; +// } +// if (p.val > root.val && q.val < root.val) { +// return root; +// } + + // 只有这个有用 + if (p.val > root.val && q.val > root.val) { + // 向右递归 + return lowestCommonAncestor(root.right, p, q); + } else if (p.val < root.val && q.val < root.val) { + // 向左递归 + return lowestCommonAncestor(root.left, p, q); + } + + + return root; + } + + public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) { + if (root.val > p.val && root.val > q.val) return lowestCommonAncestor1(root.left, p, q); + if (root.val < p.val && root.val < q.val) return lowestCommonAncestor1(root.right, p, q); + return root; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode236.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode236.java new file mode 100644 index 0000000..53ddd52 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode236.java @@ -0,0 +1,100 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/30 17:35 + * @注释 + */ +public class LeetCode236 { + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(1, 2, 3, 4, 5, 6); + + new Solution1().lowestCommonAncestor(treeNode, treeNode.left.right, treeNode.left).printTree(); + } + + + class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + + // 先找到两个树 + // 用两个List记录路径 + // 挨个对比,找到最后一个公共的点 + ArrayList e1 = new ArrayList<>(); + findNode(root, p, e1); + ArrayList e2 = new ArrayList<>(); + findNode(root, q, e2); + + + + + int minSize = Math.min(e1.size(), e2.size()); + int index = minSize - 1; + while (index >= 0) { + if (e1.get(index) == e2.get(index)) { + return e1.get(index); + } + index--; + } + + return null; + } + + public boolean findNode(TreeNode root, TreeNode wantFindNode, List path) { + + if (root==null) return false; + path.add(root); + if (root == wantFindNode) { + return true; + } + + boolean left = findNode(root.left, wantFindNode, path); + if (left == true) { + return true; + } + + boolean right = findNode(root.right, wantFindNode, path); + if (right == true) { + return true; + } + + path.remove(path.size() - 1); + + return left || right; + } + } + + class Solution1 { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root==null) return null; + // 左右找到两个树 + // 如果找到树了,返回该节点 + if (root.val == p.val || root.val == q.val) { + return root; + } + + TreeNode left = lowestCommonAncestor(root.left, p, q); + TreeNode right = lowestCommonAncestor(root.right, p, q); + + if(left == null && right == null) { // 若未找到节点 p 或 q + return null; + }else if(left == null && right != null) { // 若找到一个节点 + return right; + }else if(left != null && right == null) { // 若找到一个节点 + return left; + }else { // 若找到两个节点 + return root; + } + } + + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode238.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode238.java new file mode 100644 index 0000000..1314c6e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode238.java @@ -0,0 +1,77 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/17 13:58 + * @注释 + */ +public class LeetCode238 { + @Test + public void test() { + int[] nums = {1, 2, 3, 4}; + int[] ints = productExceptSelf(nums); + for (int anInt : ints) { + System.out.println(anInt); + } + } + + class Solution { + /** + * [-1,1,0,-3,3] + * -1 -1 0 0 0 + * 0 0 0 -9 3 + * + * @param nums + * @return + */ + public int[] productExceptSelf(int[] nums) { + int[] preMul = new int[nums.length]; + preMul[0] = nums[0]; + for (int i = 1; i < nums.length; i++) { + preMul[i] = preMul[i - 1] * nums[i]; + } + + int[] afterMul = new int[nums.length]; + afterMul[nums.length - 1] = nums[nums.length - 1]; + for (int i = nums.length - 2; i >= 0; i--) { + afterMul[i] = afterMul[i + 1] * nums[i]; + } + + for (int i = 0; i < nums.length; i++) { + int pre = (i > 0) ? preMul[i - 1] : 1; + int after = i < nums.length - 1 ? afterMul[i + 1] : 1; + nums[i] = pre * after; + } + + return nums; + } + } + + //维护两个变量,beforeSum表示前缀和,afterSum表示后缀和 + // 两个指针不断缩小会相交 + public int[] productExceptSelf(int[] nums) { + int n = nums.length; + int[] ans = new int[n]; + Arrays.fill(ans, 1); + int beforeSum = 1; + int afterSum = 1; + + int left = 0; + int right = nums.length - 1; + while (left < nums.length) { + ans[left] *= beforeSum; + ans[right] *= afterSum; + beforeSum *= nums[left]; + afterSum *= nums[right]; + left++; + right--; + } + + return ans; + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode239.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode239.java new file mode 100644 index 0000000..5e4efc9 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode239.java @@ -0,0 +1,94 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @Author whai文海 + * @Date 2024/1/9 14:49 + * @注释 + * + * 239. 滑动窗口最大值 + + * 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 + * + * 返回 滑动窗口中的最大值 。 + * + * + * + * 示例 1: + * + * 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 + * 输出:[3,3,5,5,6,7] + * 解释: + * 滑动窗口的位置 最大值 + * --------------- ----- + * [1 3 -1] -3 5 3 6 7 3 + * 1 [3 -1 -3] 5 3 6 7 3 + * 1 3 [-1 -3 5] 3 6 7 5 + * 1 3 -1 [-3 5 3] 6 7 5 + * 1 3 -1 -3 [5 3 6] 7 6 + * 1 3 -1 -3 5 [3 6 7] 7 + * 示例 2: + * + * 输入:nums = [1], k = 1 + * 输出:[1] + */ +public class LeetCode239 { + + @Test + public void test() { + int[] nums = new int[]{1, 3, -1, -3, 5, 3, 6, 7}; + int[] res = new Solution().maxSlidingWindow(nums, 3); + for (int re : res) { + System.out.println(re); + } + } + + class Solution { + /** + * 维持一个单调队列,队列里存放的是对应值得下标。 + * 如果 此次队列头部指针为i,即num[i]为目前窗口的最大值。 + * - 如果这个最大值的下标不在下一个窗口的范围内,那么需要将这个值删除 + * @param nums + * @param k + * @return + */ + public int[] maxSlidingWindow(int[] nums, int k) { + // 单调队列,维持一个单调递减的队列 + Deque queue = new LinkedList<>(); + + // n个元素,k个窗口,一共为n-k个输出 + int[] res = new int[nums.length - k + 1]; + + + for (int i = 0; i < nums.length; i++) { + + // 判断当前队首的值是否在本次的窗口内,i-k为窗口左边 + if (!queue.isEmpty()&&queue.peek() <= i - k) { + queue.pop(); + } + + // 保证单调递减 + while (!queue.isEmpty() && nums[i] >= nums[queue.peekLast()]) { + queue.removeLast(); + } + queue.addLast(i); + + + // 从第k个开始才有结果 + if(i+1 >= k){ + res[i+1-k] = nums[queue.peek()]; + } + + // 从第k个开始,先把值存进去,在下次循环判断是否这个值存在于这个新的区间中 + } + + + return res; + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode24.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode24.java new file mode 100644 index 0000000..da8f13f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode24.java @@ -0,0 +1,113 @@ +package cn.whaifree.leetCode.LinkedList; + +import org.junit.Test; +import cn.whaifree.leetCode.model.ListNode; + +/** + * 两两交换链表中的节点 + * 中等 + * 相关标签 + * 相关企业 + * 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 + * + * 示例 1: + * 输入:head = [1,2,3,4] + * 输出:[2,1,4,3] + * + * 示例 2: + * 输入:head = [] + * 输出:[] + * + * 示例 3: + * 输入:head = [1] + * 输出:[1] + * + */ +public class LeetCode24 { + + /** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + * pre index tmp + * 0 -> 1 -> 2 -> 3 -> 4 -> 5 + * + * pre index tmp + * 0 1 -> 2 -> 3 -> 4 -> 5 + * ----------^ + * + * ----------- + * pre index tmp | + * 0 1 -> 2 -> 3 -> 4 -> 5 + * ----------^ + * + * ----------- + * pre index tmp | + * 0 1 <- 2 -> 3 -> 4 -> 5 + * ----------^ + * + * pre tmp index + * 0-> 2 -> 1 -> 3 -> 4 -> 5 + * + * + * pre tmp index + * 0-> 2 -> 1 -> 3 -> 4 -> 5 + */ + public ListNode swapPairs(ListNode head) { + if (head == null) { + return head; + } + ListNode pre = new ListNode(0, head); + ListNode tmp = head.next; + ListNode index = head; + head = pre; + while (tmp != null) { + pre.next = tmp; + index.next = tmp.next; + tmp.next = index; + pre = index; + index = pre.next; + tmp = index == null ? null : index.next; + } + return head.next; + } + + public ListNode swapPairsD(ListNode head) { + if (head == null) { + return head; + } + return swap(head, head.next); + } + + /** + * 递归的关键: + * 1. 结束条件 + * 2. 递归条件(只考虑当前这一点点的情况,剩下的交给下次递归) + * @param pre + * @param after + * @return + */ + public ListNode swap(ListNode pre, ListNode after) { + if (pre == null || after == null) { + return pre; + } + // 递归后面的指针 + pre.next = swap(after.next, after.next == null ? null : after.next.next); + after.next = pre; + + return after; + } + + + @Test + public void test() { + ListNode listNode = swapPairsD(ListNode.listNodeFromArray(new int[]{1,2,3,4,5})); + ListNode.printList(listNode); + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2487.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2487.java new file mode 100644 index 0000000..bab2d86 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2487.java @@ -0,0 +1,98 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +public class LeetCode2487 { + @Test + public void test() { + new Solution1().removeNodes(ListNode.listNodeFromArray(new int[]{5, 2, 13, 3, 8})).printList(); + } + + + /** + * 找到最大的节点,找到下一个最大的节点,此区间全部删掉。 + * 每次删除后MaxNode为null + * + * 即最后变成了递减的链表 + * + */ + class Solution { + /** + * 递归 + * @param head + * @return + */ +// public ListNode removeNodes(ListNode head) { +// ListNode dummy = new ListNode(0, head); +// ListNode pre = dummy; +// ListNode index = head; +// ListNode maxNode = dummy; +// while (index != null) { +// if (index.val > maxNode.val) { +// maxNode = index; +// // 删除pre到maxNode的前一个节点 +// pre.next = maxNode; +// maxNode.next = removeNodes(maxNode.next); +// } +// index = index.next; +// } +// +// return dummy.next; +// } + public ListNode removeNodes(ListNode head) { + return remove(new ListNode(0, head)); + } + + public ListNode remove(ListNode head) { + if (head == null) { + return null; + } + + head.next = remove(head.next); + if (head.next != null && head.val < head.next.val) { + return head.next; + } else { + return head; + } + } + + } + + class Solution1 { + + + public ListNode removeNodes(ListNode head) { + + ListNode newHead = reverse(head); + // 变成从右往左边移除比newHead小的 + ListNode index = newHead; + ListNode tmpMaxNode = newHead; + while (index.next != null) { + if (index.next.val < tmpMaxNode.val) { + index.next = index.next.next; + } else { + index = index.next; + tmpMaxNode = index; + } + } + // 最后那个数是永远不会删除的 + return reverse(newHead); + } + + public ListNode reverse(ListNode head) { + // 反转链表 + ListNode index = head; + ListNode pre = null; + + while (index != null) { + ListNode tmp = index.next; + index.next = pre; + pre = index; + index = tmp; + } + // {5, 2, 13, 3, 8} + return pre; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode25.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode25.java new file mode 100644 index 0000000..736a315 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode25.java @@ -0,0 +1,62 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/23 13:43 + * @注释 + */ +public class LeetCode25 { + + @Test + public void test() { + ListNode head = ListNode.listNodeFromArray(new int[]{1, 2, 3, 6, 7, 8, 9, 20}); +// new Solution().reverse(null, head, 3).printList(); + new Solution().reverseKGroup(head, 2).printList(); + } + + class Solution { + public ListNode reverseKGroup(ListNode head, int k) { + ListNode pre = new ListNode(-1, head); + return reverseRange(pre.next, k); + } + + + /** + * pre往后k个元素翻转 + * @param pre + * @param k + * @return + */ + public ListNode reverseRange(ListNode pre, int k) { + ListNode index = pre; + ListNode nextNode = pre; + int i = 0; + while (i < k && nextNode != null) { + nextNode = nextNode.next; + i++; + } + if (i < k) { + return pre; + } + ListNode reverseAfterHead = reverse(null, index, k); + index.next = reverseRange(nextNode, k); + return reverseAfterHead; + } + + public ListNode reverse(ListNode pre, ListNode after,int k) { + if (k <= 0) { + return pre; + } + if (after == null) { + return pre; + } + ListNode next = after.next; + after.next = pre; + return reverse(after, next, k - 1); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode257.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode257.java new file mode 100644 index 0000000..e3db3a3 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode257.java @@ -0,0 +1,173 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.Node; +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/22 21:54 + * @注释 + */ +public class LeetCode257 { + + @Test + public void test() { + + TreeNode root = TreeNode.constructTree(new Integer[]{1, 2, 3, 5,6,7,8,9,0,6}); + root.printTree(); + + System.out.println(new Solution3().binaryTreePaths(root)); + } + class Solution { + + List res = new ArrayList(); + + public List binaryTreePaths(TreeNode root) { + if (root == null) { + return res; + } + deal(root, ""); + return res; + } + + public void deal(TreeNode root, String s) { + + if (root == null) return; + if (root.left == null && root.right == null) { + res.add(new StringBuilder(s).append(root.val).toString()); + } + String tmp = new StringBuilder(s).append(root.val).append("->").toString(); + deal(root.left, tmp); + deal(root.right, tmp); + } + + } + + + class Solution1 { + + List res = new ArrayList(); + + public List binaryTreePaths(TreeNode root) { + if (root == null) { + return res; + } + deal(root, ""); + return res; + } + + public void deal(TreeNode treeNode, String s) { + + if (treeNode==null) return; + //根节点 + if (treeNode.right == null && treeNode.left == null) { + res.add(s + treeNode.val); +// res.add(new StringBuilder().append(s).append(treeNode.val).toString()); + } + +// String tmp = new StringBuilder().append(s).append("->").append(treeNode.val).toString(); + String tmp = s + treeNode.val + "->"; + deal(treeNode.left, tmp); + deal(treeNode.right, tmp); + } + + + + } + + class Solution2 { + + List res = new ArrayList(); + List route = new ArrayList(); + + + public List binaryTreePaths(TreeNode root) { + if (root == null) { + return res; + } + deal(root); + return res; + } + + public void deal(TreeNode treeNode) { + if (treeNode == null) { + return; + } + route.add(treeNode.val); + if (treeNode.left == null && treeNode.right == null) { + // 根节点 + // 可以知道结果了 + StringBuilder stringBuilder = new StringBuilder(); + int size = route.size(); + for (int i = 0; i < size - 1; i++) { + stringBuilder.append(route.get(i)).append("->"); + } + stringBuilder.append(route.get(size - 1)); + res.add(stringBuilder.toString()); + return; + } + if (treeNode.right != null) { + deal(treeNode.right); + // 回溯 + route.remove(route.size() - 1); + } + if (treeNode.left != null) { + deal(treeNode.left); + route.remove(route.size() - 1); + } + + } + + + + } + + class Solution3 { + + + public List binaryTreePaths(TreeNode root) { + List res = new ArrayList(); + + if (root == null) { + return res; + } + + Deque stack = new ArrayDeque<>(); + stack.add(root); + stack.add(root.val + ""); + while (!stack.isEmpty()) { + TreeNode nodePeek = (TreeNode) stack.pop(); + String s = (String) stack.pop(); + // 叶子节点 + if (nodePeek.left == null && nodePeek.right == null) { +// s += "->" + nodePeek.val; + res.add(s); + } + + // 左右进栈 + if (nodePeek.left != null) { + stack.add(nodePeek.left); + stack.add(new StringBuilder().append(s).append("->").append(nodePeek.left.val).toString()); + } + if (nodePeek.right != null) { + stack.add(nodePeek.right); + stack.add(new StringBuilder().append(s).append("->").append(nodePeek.right.val).toString()); + } + } + + return res; + } + + + + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode26.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode26.java new file mode 100644 index 0000000..5de03d6 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode26.java @@ -0,0 +1,91 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * 删除有序数组中的重复项 + * 简单 + * 相关标签 + * 相关企业 + * 提示 + * 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 + * + * 考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过: + * + * 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。 + * 返回 k 。 + * 判题标准: + * + * 系统会用下面的代码来测试你的题解: + * + * int[] nums = [...]; // 输入数组 + * int[] expectedNums = [...]; // 长度正确的期望答案 + * + * int k = removeDuplicates(nums); // 调用 + * + * assert k == expectedNums.length; + * for (int i = 0; i < k; i++) { + * assert nums[i] == expectedNums[i]; + * } + * 如果所有断言都通过,那么您的题解将被 通过。 + * + * + * + * 示例 1: + * + * 输入:nums = [1,1,2] + * 输出:2, nums = [1,2,_] + * 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。 + * 示例 2: + * + * 输入:nums = [0,0,1,1,1,2,2,3,3,4] + * 输出:5, nums = [0,1,2,3,4] + * 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。 + * + * + * 提示: + * + * 1 <= nums.length <= 3 * 104 + * -104 <= nums[i] <= 104 + * nums 已按 非严格递增 排列 + */ +public class LeetCode26 { + + public int removeDuplicates(int[] nums) { + // 保证return k 的k nums 前k个为唯一递增的 + int left = 0; // 左指针,指向无重复元素数组的起始位置 + int right = 1; // 右指针,指向当前元素数组的位置 + while (right < nums.length) { + if (nums[right] == nums[left]) { // 如果右指针指向的元素等于左指针指向的元素 + right++; // 则右指针向右移动 + } else { + nums[++left] = nums[right++]; // 若不相等,则将当前元素放入无重复元素数组中,并同时将左指针和右指针向右移动 + } + } + return left + 1; // 返回无重复元素数组的长度 + } + + public int removeDuplicates1(int[] nums) { + // 保证return k 的k nums 前k个为唯一递增的 + int left = 0; + int right = 1; + int jump = 0; + while (right < nums.length) { + if (nums[right] == nums[left]) { + right++; + jump++; + } else { + nums[left + 1] = nums[right]; + right++; + left++; + } + } + return left + 1; + } + + + @Test + public void test() { + System.out.println(removeDuplicates(new int[]{1,1,2})); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2602.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2602.java new file mode 100644 index 0000000..6f863f0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode2602.java @@ -0,0 +1,164 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 16:59 + * @注释 + */ +public class LeetCode2602 { + @Test + public void test() + { + Solution solution = new Solution(); + int[] nums = {3,1,6,8}; + int[] queries = {1,5}; + List res = solution.minOperations(nums, queries); + res.forEach(System.out::println); + } + + + /** + * 超时 + */ + class Solution { + public List minOperations(int[] nums, int[] queries) { + List res = new ArrayList<>(); + for (int query : queries) { + res.add(target(nums, query)); + } + return res; + } + + public long target(int[] nums, int target) { + + long res = 0; + for (int num : nums) { + res += Math.abs(target - num); + } + return res; + } + } + + class Solution1 { + public List minOperations(int[] nums, int[] queries) { + List res = new ArrayList<>(); + Arrays.sort(nums); + // 排序后,找到对应的元素,左边小于,右边大于 + // 求前缀和 + int length = nums.length; + long[] preSum = new long[length + 1]; + for (int i = 0; i < length; i++) { + preSum[i + 1] = preSum[i] + nums[i]; + } + + for (int target : queries) { + int index = findIndex(nums, target); + long left = (long) index * target - preSum[index]; + // index 为横坐标 target为纵坐标高度 preSum为index位置前面的总和 + long right = preSum[length] - preSum[index] - (long) target * (length - index); + res.add(left + right); + } + + // 一侧的前缀和与 “平均值*一侧区间长度” 就代表这一侧的总操作数 + + return res; + } + + + public int findIndex(int[] nums, int target) { + int left = 0; + int right = nums.length - 1; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] == target) { + return mid; + } else if (nums[mid] > target) { + right = mid - 1; + } else { + left = mid + 1; + } + } + return right; + } + + } + + @Test + public void test1() + { + Solution2 solution2 = new Solution2(); + int[] nums = {3,1,6,8}; + int[] queries = {5}; + List res = solution2.minOperations(nums, queries); + res.forEach(System.out::println); + } + + + class Solution2 { + public List minOperations(int[] nums, int[] queries) { + Arrays.sort(nums); + + // 计算前缀和 + long[] preSum = new long[nums.length + 1]; + for (int i = 1; i < preSum.length; i++) { + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + + List res = new ArrayList<>(); + for (int query : queries) { + res.add(getOperation(nums, query, preSum)); + } + return res; + + } + + /** + * + * + * @param nums 原数组 + * @param target 目标 + * @param preSum 前缀和 + * @return + */ + public Long getOperation(int[] nums, int target,long[] preSum) { + + int index = findIndex(nums, target); + // index左边全部比他小、右边全部比他大 + // 0 - index 为小于他的数字个数 index-length为大于他的个数 + // 小于他的数的总和 = 小于的个数 index * (target-nums[0]) - index位置的前缀和(前缀和就是一个下三角形的面积) + long leftIncr = (long) index * target - preSum[index]; + long rightIncr = + preSum[nums.length] - preSum[index] + - (long) target * (nums.length - index); + + return leftIncr + rightIncr; + } + + /** + * 二分查找 + * @param nums 有序数组 + * @param target + * @return + */ + public int findIndex(int[] nums, int target) { + int left = 0, right = nums.length - 1; + while (left <= right) { + int mid = (right + left) / 2; + if (nums[mid] < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + return left; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode27.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode27.java new file mode 100644 index 0000000..577c617 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode27.java @@ -0,0 +1,94 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 + * + * 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 + * + * 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 + * + * + * + * 说明: + * + * 为什么返回数值是整数,但输出的答案是数组呢? + * + * 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 + * + * 你可以想象内部操作如下: + * + * // nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 + * int len = removeElement(nums, val); + * + * // 在函数里修改输入数组对于调用者是可见的。 + * // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 + * for (int i = 0; i < len; i++) { + * print(nums[i]); + * } + * + * + * 示例 1: + * + * 输入:nums = [3,2,2,3], val = 3 + * 输出:2, nums = [2,2] + * 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。 + * 示例 2: + * + * 输入:nums = [0,1,2,2,3,0,4,2], val = 2 + * 输出:5, nums = [0,1,3,0,4] + * 解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。 + * + * + * 提示: + * + * 0 <= nums.length <= 100 + * 0 <= nums[i] <= 50 + * 0 <= val <= 100 + * + * 相关题目推荐 + * 26.删除排序数组中的重复项(opens new window) + * 283.移动零(opens new window) + * 844.比较含退格的字符串(opens new window) + * 977.有序数组的平方(opens new window) + * #其他语言版本 + * + */ +public class LeetCode27 { + +// public int removeElement(int[] nums, int val) { +// int hasCount = 0; +// int numLength = nums.length; +// for (int i = 0; i < nums.length; i++) { +// if (nums[i] == val) { +// hasCount++; +// } +// } +// return numLength - hasCount; +// } + + // 双指针 + public int removeElement(int[] nums, int val) { + int slowIndex = 0; + + for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) { + if (nums[fastIndex] != val) { + nums[slowIndex] = nums[fastIndex]; + slowIndex++; + } + } + + return slowIndex; + } + @Test + public void testSearch1() { + + LeetCode27 leetCode27 = new LeetCode27(); + System.out.println("return" + leetCode27.removeElement(new int[]{0,1,2,2,3,0,4,2}, 2)); + + } + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode274.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode274.java new file mode 100644 index 0000000..9f1a4bb --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode274.java @@ -0,0 +1,35 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/16 17:17 + * @注释 + */ +public class LeetCode274 { + @Test + public void test() + { + int[] nums = new int[]{1,3,1}; + System.out.println(new Solution().hIndex(nums)); + } + + class Solution { + public int hIndex(int[] citations) { + + Arrays.sort(citations); + + for (int i = 0; i < citations.length; i++) { + int h = citations.length - i; + if (citations[i] >= h) { + return h; + } + } + return 0; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode279.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode279.java new file mode 100644 index 0000000..039bc63 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode279.java @@ -0,0 +1,58 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 11:53 + * @注释 + */ +public class LeetCode279 { + + @Test + public void test(){ + Solution solution = new Solution(); + int numSquares = solution.numSquares(12); + System.out.println(numSquares); + } + + + class Solution { + public int numSquares(int n) { + + // 完全平方数 任意取,使其满足n容量的背包的最少数量 + // 给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。 + // dp[j] 表示容量为j的背包 最少 需要的 完全平方数 的数量 + + int[] dp = new int[n + 1]; + Arrays.fill(dp, Integer.MAX_VALUE); + + + // 求组合数就是外层for循环遍历物品,内层for遍历背包 + // 求排列数就是外层for遍历背包,内层for循环遍历物品 {1,0} {0,1} + // 本题都可以 + dp[0] = 0; +// for (int j = 0; j <= n; j++) { +// for (int i = 1; i * i <= j; j++) { +// // i-j*j 表示 之前的完全平方数 + 这个挖 +// dp[j] = Math.min(dp[j - i * i] + 1, dp[j]); +// } +// } + + for (int i = 1; i * i <= n; i++) { + for (int j = i * i; j <= n; j++) { + // i-j*j 表示 之前的完全平方数 + 这个挖 + dp[j] = Math.min(dp[j - i * i] + 1, dp[j]); + //dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。 + // 或者说, dp[j-i*i]表示j-i*i的最小需要平方数,加上我们给到的i*i这一个平方数,就是+1,即dp[j - i * i] + 1 + } + } + + return dp[n]; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode28.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode28.java new file mode 100644 index 0000000..3542521 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode28.java @@ -0,0 +1,64 @@ +package cn.whaifree.radom; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/8 11:09 + * @注释 + */ + +public class LeetCode28 { + + @Test + public void test() { + + int i = new Solution().strStr("aabaadaabaaf", "aabaaf"); + System.out.println(i); + + } + + class Solution { + public int strStr(String haystack, String needle) { + int[] next = constructNext(needle); + + int j = 0; + for (int i = 0; i < haystack.length(); i++) { + while (j > 0 && haystack.charAt(i) != needle.charAt(j)) { + j = next[j - 1]; + } + if (haystack.charAt(i) == needle.charAt(j)) { + j++; + } + if (j == needle.length()) { + return i - j + 1; + } + } + + return -1; + + } + + // 构造next数组 + public int[] constructNext(String needle) { + int length = needle.length(); + int[] next = new int[length]; + int j = 0;// 前缀 + for (int i = 1; i < length; i++) { + // 如果不匹配 往前跳 + while (j > 0 && needle.charAt(i) != needle.charAt(j)) { + j = next[j - 1]; + } + // 如果匹配 设置next[i]=j + if (needle.charAt(i) == needle.charAt(j)) { + j++; + } + next[i] = j; + } + return next; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode287.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode287.java new file mode 100644 index 0000000..d3db02d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode287.java @@ -0,0 +1,55 @@ +package cn.whaifree.leetCode.Array; + + +import org.junit.Test; + +public class LeetCode287 { + + @Test + public void test() { + System.out.println(new Solution().findDuplicate(new int[]{1, 3, 3, 2})); + } + + class Solution { + /** + * 将数组转换为链表思想 + * [ 1, 3, 4, 2, 2] + * 0 1 2 3 4 + * + * 0->1->3->[2->4->2->4->2.....] + * + * ListNode index = index.next + * 等价于 int index = nums[index] + * + * + * - nums.length == n + 1 + * - 1 <= nums[i] <= n + * 表明 如果只有3个元素,取值区间只能为[1,2,3] + * + * @param nums + * @return + */ + public int findDuplicate(int[] nums) { + + // 因为 1 <= n <= 105 所以0只在开始出现过。 + // 两个指针 + int fast = 0; + int slow = 0; + slow = nums[slow]; + fast = nums[nums[fast]]; + // 找到相遇的地方 + while (fast != slow) { + fast = nums[nums[fast]]; + slow = nums[slow]; + } + // 此时两个指针指向同个地方,表示在环的里面 + int tmp = 0; + while (nums[tmp] != nums[slow]) { + tmp = nums[tmp]; + slow = nums[slow]; + } + + return nums[tmp]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode289.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode289.java new file mode 100644 index 0000000..82c88dc --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode289.java @@ -0,0 +1,102 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/23 11:08 + * @注释 + */ +public class LeetCode289 { + + @Test + public void test() { + int[][] board = new int[][]{{0, 1, 0}, {0, 0, 1}, {1, 1, 1}, {0, 0, 0}}; + new Solution().gameOfLife(board); + for (int[] ints : board) { + System.out.println(Arrays.toString(ints)); + } + } + + class Solution { + + /** + * 为了保证当前修改后的状态不会影响下一个状态的判定,设置另外的状态 + * 如题所示,只有三种: + * 1. 如果当前是活细胞,但是变成了死细胞,那么设置为-1 + * 2. 如果当前是活细胞,仍然是活细胞,那么不变仍为1 + * 3. 如果当前是死细胞,但是变成了活细胞,那么设置为2 + * 那么最后遍历修改完状态之后,将-1修改回为0,2修改回为1 + * @param board + */ + public void gameOfLife(int[][] board) { + //设置方向来遍历某个节点周围的另外几个节点 + int[] ner = new int[]{-1,0,1}; + //获取行和列 + int rows = board.length; + int cols = board[0].length; + //遍历每一个节点格子 + for (int row = 0; row < rows; row++) { + for (int col = 0; col < cols; col++) { + //设置当前节点周围的存活细胞的数量 + int liveNer = 0; + /** + * 当前节点是[ i , j ] + * [i-1,j-1] [i-1,j] [i-1,j+1] + * [ i ,j-1] [ i ,j] [ i ,j+1] + * [i+1,j-1] [i+1,j] [i+1,j+1] + * 那么以当前节点为中心,要求周围的节点,则最多是3*3形式 + * 并且所有的行和列都是用当前节点+1或者-1或者不变构成 + * 所以我们设置 ner = {-1,0,1} 来形成遍历 + */ + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + //必须保证不计算当前节点(不计算自己) + if (!(ner[i]==0 && ner[j]==0)){ + //当前节点的相邻节点坐标 + int r = row+ner[i]; + int c = col+ner[j]; + /**判断当前周围节点的存活状态,要求满足两个状态 + * 1. 必须保证要在 board 矩阵中 + * 2. 并且**起始状态要是存活,则当前状态为1或者-1都可以(因为这两个状态都表示起始状态为活细胞)** + **/ + if ((r >= 0 && r < rows) && (c >= 0 && c < cols) && (Math.abs(board[r][c]) == 1)) { + // -1和1 初始状态都是活细胞 + liveNer++; + } + } + } + } + /**开始判断当前节点的存活状态 + * 因为遍历到当前节点的时候,还没有开始修改细胞状态,所以还是0和1的细胞状态 + * 那么只需要判断状态变化的即可,否则状态不变 + **/ + if ((board[row][col]==1) && ( liveNer>3 || liveNer<2)){ + // -1 代表这个细胞过去是活的现在死了 + board[row][col]=-1; + } + if (board[row][col]==0 && ( liveNer==3)){ + // 2 代表这个细胞过去是死的现在活了 + board[row][col]=2; + } + } + } + //再把额外的状态修改回去 + for (int row = 0; row < rows; row++) { + for (int col = 0; col < cols; col++) { + if (board[row][col] == 2) { + board[row][col] = 1; + } + if (board[row][col] == -1){ + board[row][col] = 0; + } + } + } + + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode28_2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode28_2.java new file mode 100644 index 0000000..28e58d1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode28_2.java @@ -0,0 +1,125 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * 28. 找出字符串中第一个匹配项的下标 + * + * 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。 + * + * 示例 1: + * + * 输入:haystack = "sadbutsad", needle = "sad" + * 输出:0 + * 解释:"sad" 在下标 0 和 6 处匹配。 + * 第一个匹配项的下标是 0 ,所以返回 0 。 + * 示例 2: + * + * 输入:haystack = "leetcode", needle = "leeto" + * 输出:-1 + * 解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。 + * + * 提示: + * 1 <= haystack.length, needle.length <= 104 + * haystack 和 needle 仅由小写英文字符组成 + */ +public class LeetCode28_2 { + + @Test + public void test() { + String haystack = "aabaadaabaaf"; + String needle = "aabaaf"; + int i = new Solution1().strStr(haystack, needle); + System.out.println(i); + } + + class Solution { + public int strStr(String haystack, String needle) { + + int begin = 0; + int length = needle.length(); + int end = begin + length; + while (end <= haystack.length()) { + if (haystack.substring(begin, end).equals(needle)) { + return begin; + } + begin++; + end++; + + } + return -1; + } + } + + // KMP + class Solution1 { + public int strStr(String haystack, String needle) { + int[] next = next(needle); + System.out.println(Arrays.toString(next)); + int length = haystack.length(); + // [0, 1, 0, 1, 2, 0] + // aabaadaabaaf + // aabaaf + int j = 0; + for (int i = 0; i < length; i++) { + // 往前跳 + while (j > 0 && needle.charAt(j) != haystack.charAt(i)) { + j = next[j - 1]; + } + if (needle.charAt(j) == haystack.charAt(i)) { + j++; + } + if (j == needle.length()) { + return i - needle.length() + 1; + } + } + return -1; + } + + // 求Next数组 + public int[] next(String s) { + int[] next = new int[s.length()]; + int j = 0; + for (int i = 1; i < s.length(); i++) { + // 不匹配 + while (j > 0 && s.charAt(i) != s.charAt(j)) { + j = next[j - 1]; + } + // 匹配 + if (s.charAt(i) == s.charAt(j)) { + j++; + } + next[i] = j; + } + return next; + } + } +} + + +class Dfather{ + static int count = 1; + static{ + System.out.println("Initialize class Dfather"); + } +} + +class Dson extends Dfather{ + static{ + System.out.println("Initialize class Dson"); + } +} + +class Test4 { + public static void main(String[] args) { + String a = "d"; //字面量 + String b = "d"; //字面量,存常量池 + System.out.println(a == b); + a = new String("d"); //对象,存堆 + System.out.println("a=" + a); + System.out.println("b=" + b); + System.out.println(a == b); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode3.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode3.java new file mode 100644 index 0000000..add6930 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode3.java @@ -0,0 +1,91 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +import java.util.Set; +import java.util.TreeSet; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/21 11:30 + * @注释 + */ +public class LeetCode3 { + + @Test + public void test() { + String s = "abcabcbb"; + System.out.println(new Solution1().lengthOfLongestSubstring(s)); + + } + + class Solution { + public int lengthOfLongestSubstring(String s) { + if (s.length() == 0) { + return 0; + } + + // s 由英文字母、数字、符号和空格组成 + Set set = new TreeSet<>(); // 保持原来的顺序 + int right = 0; + int left = 0; + int maxLength = 0; + while (right < s.length()) { + char c = s.charAt(right); + if (set.contains(c)) { + maxLength = Math.max(maxLength, right - left); + while (set.contains(c)) { + set.remove(s.charAt(left)); + left++; + } + } + set.add(c); + right++; + } + return Math.max(set.size(), maxLength); + } + } + + class Solution1 { + /** + * + * @param s + * @return + */ + public int lengthOfLongestSubstring(String s) { + if (s.length() == 0) { + return 0; + } + + boolean[] map = new boolean[95]; + + // s 由英文字母、数字、符号和空格组成 + // Set set = new TreeSet<>(); // 保持原来的顺序 + int right = 0; + int left = 0; + int maxLength = 0; + while (right < s.length()) { + char c = s.charAt(right); + if (map[c - 32]) { + maxLength = Math.max(maxLength, right - left); + while (map[c - 32]) { + map[s.charAt(left) - 32] = false; + left++; + } + } + map[c - 32] = true; + right++; + } + + int mapSize= 0; + for (boolean b : map) { + if (b) { + mapSize++; + } + } + + return Math.max(mapSize, maxLength); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode300.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode300.java new file mode 100644 index 0000000..139f828 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode300.java @@ -0,0 +1,79 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/22 13:23 + * @注释 + */ +public class LeetCode300 { + + @Test + public void test() + { + int[] nums = {4,10,4,3,8,9}; + Solution solution = new Solution(); + int i = solution.lengthOfLIS(nums); + System.out.println(i); + } + + class Solution { + /** + * int[i][j] 表示i-j的最长严格递增子序列长度 + * @param nums + * @return + */ + public int lengthOfLIS(int[] nums) { + int[] dp = new int[nums.length]; + + + // dp[i]表示i之前包括i的以(nums[i]结尾)(即每次都必须包括i,每次都需要和i比较)的最长递增子序列的长度 + // 位置i的最长升序子序列 = j从0到i-1各个位置的 最长升序子序列 + 1 的 最大值 + Arrays.fill(dp, 1); + int res = 1; + for (int i = 1; i < nums.length; i++) { + for (int j = 0; j < i; j++) { + if (nums[j] < nums[i]) { + dp[i] = Math.max(dp[i], dp[j] + 1); + } + } + + res = Math.max(res, dp[i]);// 取长的子序列 + } + + return res; + } + } + + + class Solution1 { + + public int lengthOfLIS(int[] nums) { + // 最长严格递增子序列的长度 + /** + * dp[i] 表示包含从0-i包含i(i在每次循环中是最后一个)的最长递增子序列的长度 + */ + int[] dp = new int[nums.length]; + Arrays.fill(dp, 1); // 最初就是1个 + + int res = 1; + for (int i = 1; i < nums.length; i++) { + for (int j = 0; j < i; j++) { + // 从0到i-1 + // nums[j] < nums[i] 就证明 nums[j] 小于 nums[i] ,前面有多少个j就计算多少次 + if (nums[j] < nums[i]) { + dp[i] = Math.max(dp[i], dp[j] + 1); // dp[i] 为0-(j-1)的最长递增子序列长度,dp[j] + 1 为0-j的最长递增子序列长度,取两者最大值 + } + } + res = Math.max(res, dp[i]); // 每次获得以i为最后一个的最长递增子序列的长度 + } + return res; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode31.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode31.java new file mode 100644 index 0000000..00147ad --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode31.java @@ -0,0 +1,161 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/5 13:18 + * @注释 + */ +public class LeetCode31 { + @Test + public void test() { + int[] nums = {3,2,1}; + new Solution1().nextPermutation(nums); + + for (int i = 0; i < nums.length; i++) { + System.out.print(nums[i] + " "); + } + + } + + class Solution { + public void nextPermutation(int[] nums) { + if (nums.length == 1) { + return; + } + + // 1.下一个数 比当前数大 + // 将后面的「大数」与前面的「小数」交换,就能得到更大的数 + // 2. 下一个数 增加的幅度尽可能的小 + // - 尽可能靠右的低位 进行交换 + // - 将一个 尽可能小的「大数」 与前面的「小数」交换 + // 123465 把 5和4换 + // - 「大数」后面的所有数 重置为升序 + // 123564 把5后面重新排序 + + // 1. 从后往前找到第一个升序排列,此时后面那部分一定是降序 + int i; + for (i = nums.length - 2; i >= 0; i--) { + if (nums[i] < nums[i + 1]) { + break; + } + } + if (i == -1) { + // 最后一个排序 654321,直接逆转 + reverse(nums, 0, nums.length - 1); + return; + } + + // 2. 从i+1开始找到最小的值 + int min; + for (min = nums.length - 1; min > 0; min--) { + if (nums[min] > nums[i]) { + break; + } + } + // 3. 交换i和minIndex + swap(nums, i, min); + // 4. 后面为降序,直接让其逆转变为升序 + reverse(nums, i + 1, nums.length - 1); + + + } + + public void reverse(int[] nums, int start, int end) { + while (start < end) { + swap(nums, start, end); + start++; + end--; + } + } + + public void swap(int[] nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } + } + + class Solution1 { + public void nextPermutation(int[] nums) { + if (nums.length == 1) { + return; + } + + int i = nums.length - 2; + while (i >= 0) { + if (nums[i] < nums[i + 1]) { + break; + } + i--; + } + + if (i == -1) { + // 最后一个排序 654321,直接逆转 + reverse(nums, 0, nums.length - 1); + return; + } + + int min = nums.length - 1; + while (min > 0) { + if (nums[min] > nums[i]) { + break; + } + min--; + } + + + // 3. 交换i和minIndex + swap(nums, i, min); + // 4. 后面为降序,直接让其逆转变为升序 + reverse(nums, i + 1, nums.length - 1); + } + + public void reverse(int[] nums, int start, int end) { + while (start < end) { + swap(nums, start, end); + start++; + end--; + } + } + + public void swap(int[] nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } + } + + + +} + +class ass extends as{ + + @Override + public void test() { + + } + + @Override + void test1() { + + } + + @Override + protected void test2() { + + } +} + + +abstract class as{ + + abstract public void test() ; + + abstract void test1(); + + abstract protected void test2(); +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode322.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode322.java new file mode 100644 index 0000000..413ac9f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode322.java @@ -0,0 +1,92 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/27 12:58 + * @注释 + */ +public class LeetCode322 { + @Test + public void test() { + int[] coins = {1}; + int amount = 0; + int i = new Solution1().coinChange(coins, amount); + System.out.println(i); + } + + class Solution { + public int coinChange(int[] coins, int amount) { + int[] dp = new int[amount + 1]; + Arrays.fill(dp, Integer.MAX_VALUE); + + dp[0] = 0; // 总和为0的方案为0 + for (int i = 0; i < coins.length; i++) { + for (int j = coins[i]; j <= amount ; j++) { + //只有dp[j-coins[i]]不是初始最大值时,该位才有选择的必要 + if (dp[j - coins[i]] != Integer.MAX_VALUE) { + //选择硬币数目最小的情况 + // 不放 和 放(加上本次方案1) + dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1); + } + } + } + + /** + * 输入:coins = [2], amount = 3 + * 输出:-1 + */ + return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount]; + } + } + + + class Solution1 { + /** + * 背包容量为amount + * coins里随便取 + * + * dp[j] 表示使用[0-i]任意硬币取凑出j的最小硬币数 + * + * [1, 2, 5] + * 0 1 2 3 4 5 6 + * 0 0 1 2 3 4 5 6 + * 1 0 1 1 2 2 3 3 + * 2 + * 3 + * 4 + * + * dp[j] = math.min(dp[j],dp[j-coin[i]]+1) + * + * @param coins + * @param amount + * @return + */ + public int coinChange(int[] coins, int amount) { + + + int[] dp = new int[amount+1]; + + + for (int i = 1; i < dp.length; i++) { + dp[i] = Integer.MAX_VALUE; + } + + + dp[0] = 0; + for (int i = 0; i < coins.length; i++) { + for (int j = coins[i]; j < amount + 1; j++) { + if (dp[j - coins[i]] != Integer.MAX_VALUE) { + dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1); + } + } + } + + return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode33.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode33.java new file mode 100644 index 0000000..502d993 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode33.java @@ -0,0 +1,74 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/15 10:32 + * @注释 + */ +public class LeetCode33 { + + + @Test + public void test() + { + int[] nums = new int[]{4, 5, 6, 7, 0, 1, 2}; + int target = 0; + int i = new Solution().search(nums, target); + System.out.println(i); + } + + class Solution { + /** + * + * @param nums 旋转后的值 + * @param target + * @return + */ + public int search(int[] nums, int target) { + + // 二分查找,关键在于如何找到两个递增区间的交结处k + // 判断left和mid的关系 + // 如果nums[left] < nums[mid] 即mid在left-k的区间 + // if(targetnums[left]) 在left到mid区间 + // else mid到right区间 + // 如果nums[left] > nums[mid] 即mid在k-right的区间 + // if(target>nums[mid]&&target= nums[left]) { + right = mid - 1; + } else { + left = mid + 1; + } + } else { + if (target > nums[mid] && target <= nums[right]) { + left = mid + 1; + } else { + right = mid - 1; + } + } + } + + return -1; + + } + } +// +// class Solution1 { +// public int search(int[] nums, int target) { +// +// } +// } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode332difficult.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode332difficult.java new file mode 100644 index 0000000..75d2964 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode332difficult.java @@ -0,0 +1,246 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/20 10:29 + * @注释 + */ +public class LeetCode332difficult { + @Test + public void test() { + List> tickets = new ArrayList<>(); + // 加上这一串 [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]] +// tickets.add(new ArrayList() {{ +// add("JFK"); +// add("SFO"); +// }}); +// tickets.add(new ArrayList() {{ +// add("JFK"); +// add("ATL"); +// }}); +// tickets.add(new ArrayList() {{ +// add("SFO"); +// add("ATL"); +// }}); +// tickets.add(new ArrayList() {{ +// add("ATL"); +// add("JFK"); +// }}); +// tickets.add(new ArrayList() {{ +// add("ATL"); +// add("SFO"); +// }}); + + String[][] routes = { + {"JFK", "SFO"}, + {"JFK", "ATL"}, + {"SFO", "JFK"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"}, + {"ATL", "AAA"}, + {"AAA", "BBB"}, + {"BBB", "ATL"} + }; + + + for (String[] route : routes) { + tickets.add(Arrays.asList(route)); + } + + Solution1 solution = new Solution1(); + solution.findItinerary(tickets).forEach( + list -> { + System.out.println(list); + } + ); + } + + /** + * 超时 + */ + class Solution { + + List res = new ArrayList<>(); + private LinkedList path = new LinkedList<>(); + boolean[] used = null; + public List findItinerary(List> tickets) { + Collections.sort(tickets, new Comparator>() { + @Override + public int compare(List a, List b) { + // 两个字符串比较 + return a.get(1).compareTo(a.get(1)); + } + }); + // 最后,会按照目的地进行排序["JFK","SFO"],["JFK","ATL"],会变成["JFK","ATL"],["JFK","SFO"] + + path.add("JFK"); + used = new boolean[tickets.size()]; + + // 1. 字典排序选择 + // 2. 已经走过的标记 + backTracking(tickets); + return res; + } + + public void backTracking(List> tickets) { + if (path.size() == 1 + tickets.size()) { + res = new LinkedList(path); + return; + } + + int size = tickets.size(); + for (int i = 0; i < size; i++) { + if (!used[i] && path.getLast().equals(tickets.get(i).get(0))) { + String target = tickets.get(i).get(1); + path.add(target); + used[i] = true; + + backTracking(tickets); + + used[i] = false; + path.removeLast(); + + } + + } + + } + +// /** +// * 在tickets返回未被use的索引,多个索引进行比较 +// * +// * @param tickets +// * @return 在tickets中的索引 +// */ +// public int compareAndUnUsed(List> tickets, String start) { +// int res = -1; +// for (int i = 0; i < tickets.size(); i++) { +// List aPath = tickets.get(i); +// String st = aPath.get(0); +// if (start.equals(st) && used[i] == false) { +// if (res != -1) { +// String target = aPath.get(1); +// String beforeRes = tickets.get(res).get(1); +// if (!compareBeforeIsBetter(beforeRes, target)) { +// res = i; +// } +// }else { +// res = i; +// } +// } +// } +// return res; +// } +// +// public boolean compareBeforeIsBetter(String before,String after) { +// for (int i = 0; i < 3; i++) { +// char be = before.charAt(i); +// char af = after.charAt(i); +// if (be > af) { +// return false; +// } else if (be < af) { +// return true; +// } +// // 如果字母相同,比较下一个字母 +// } +// return true; +// } + + + } + + + class Solution1 { + + List res = new ArrayList<>(); + private LinkedList path = new LinkedList<>(); + boolean[] used = null; + public List findItinerary(List> tickets) { + Collections.sort(tickets, new Comparator>() { + @Override + public int compare(List a, List b) { + // 两个字符串比较 + return a.get(1).compareTo(b.get(1)); + } + }); + // 最后,会按照目的地进行排序["JFK","SFO"],["JFK","ATL"],会变成["JFK","ATL"],["JFK","SFO"] + + path.add("JFK"); + used = new boolean[tickets.size()]; + + // 1. 字典排序选择 + // 2. 已经走过的标记 + backTracking(tickets); + return res; + } + + public boolean backTracking(List> tickets) { + if (path.size() == 1 + tickets.size()) { + res = new LinkedList(path); + return true; + } + + for (int i = 0; i < tickets.size(); i++) { + if (!used[i] && path.getLast().equals(tickets.get(i).get(0))) { + String target = tickets.get(i).get(1); + path.add(target); + used[i] = true; + + if (backTracking(tickets)) { + return true; + } + + + used[i] = false; + path.removeLast(); + + } + + } + return false; + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode337.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode337.java new file mode 100644 index 0000000..dee49fe --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode337.java @@ -0,0 +1,71 @@ +package cn.whaifree.leetCode.Dynamic; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/3 13:55 + * @注释 + */ +public class LeetCode337 { + + @Test + public void test() + { + System.out.println(new Solution().rob(TreeNode.constructTreeByArray(4,1,null,2,null,3))); + } + + + class Solution { + public int rob(TreeNode root) { + /** + * dp[0]表示不选该点的最大收益 dp[1]表示选该节点的最大收益 + * + */ + int[] ints = robDown(root); + return Math.max(ints[0], ints[1]); + } + + public int[] robDown(TreeNode root) { + int res[] = new int[2]; + if (root == null) { + return res; + } + int[] left = robDown(root.left); + int[] right = robDown(root.right); + + // 不偷:Max(左孩子不偷,左孩子偷) + Max(右孩子不偷,右孩子偷) + // 不偷:左右随意,选最大的 + res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); + // 偷:左孩子不偷+ 右孩子不偷 + 当前节点偷 + // 偷:必须保证左右都不偷 + res[1] = left[0] + right[0] + root.val; + return res; + } + + } + + class Solution1 { + public int rob(TreeNode root) { + // 两层,根节点用和不用 + return Math.max(robDown(root, true), robDown(root, false)); + } + + public int robDown(TreeNode root, boolean flag) { + if (root == null) { + return 0; + } + + int left = robDown(root.left, !flag); + int right = robDown(root.right, !flag); + + if (flag) { + return left + right + root.val; + }else { + return left + right; + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode34.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode34.java new file mode 100644 index 0000000..92e2f15 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode34.java @@ -0,0 +1,109 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * 34. 在排序数组中查找元素的第一个和最后一个位置 + * 中等 + * 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 + * + * 如果数组中不存在目标值 target,返回 [-1, -1]。 + * + * 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 + * 示例 1: + * + * 输入:nums = [5,7,7,8,8,10], target = 8 + * 输出:[3,4] + * 示例 2: + * + * 输入:nums = [5,7,7,8,8,10], target = 6 + * 输出:[-1,-1] + * 示例 3: + * + * 输入:nums = [], target = 0 + * 输出:[-1,-1] + * + * + * 提示: + * + * 0 <= nums.length <= 105 + * -109 <= nums[i] <= 109 + * nums 是一个非递减数组 + * -109 <= target <= 109 + */ +public class LeetCode34 { + /** + * 非递减顺序排列的整数数组 + * [0,length] + * [5,8,8,8,8,10] + * @param nums + * @param target + * @return + */ + public int[] searchRange(int[] nums, int target) { + int[] ans = new int[2]; + // 三头 + int left = 0; + int right = nums.length - 1; + while (left <= right) { + int middle = (left + right) / 2; + if (nums[middle] == target) { + // 在[left,middle) , (middle,right]区间里找到第一个和最后一个target + +// break; + // 找到了一个 + if (nums[left] == target && nums[right] == target) { + ans[0] = left; + ans[1] = right; + return ans; + } else if (nums[left] == target) { + right--; + } else if (nums[right] == target) { + left++; + } else { + right--; + left++; + } + } else if (nums[middle] < target) { + left = middle + 1; + } else { + right = middle - 1; + } + } + ans[0] = -1; + ans[1] = -1; + return ans; + } + public int[] searchRange2(int[] nums, int target) { + int leftIdx = binarySearch(nums, target, true); + int rightIdx = binarySearch(nums, target, false) - 1; + if (leftIdx <= rightIdx && rightIdx < nums.length && nums[leftIdx] == target && nums[rightIdx] == target) { + return new int[]{leftIdx, rightIdx}; + } + return new int[]{-1, -1}; + } + + public int binarySearch(int[] nums, int target, boolean lower) { + int left = 0, right = nums.length - 1, ans = nums.length; + while (left <= right) { + int mid = (left + right) / 2; + if (nums[mid] > target || (lower && nums[mid] >= target)) { + right = mid - 1; + ans = mid; + } else { + left = mid + 1; + } + } + return ans; + } + + + + @Test + public void test() { + for (int i : searchRange2(new int[]{5,8,8,8,8,10}, 8)) { + System.out.println(i); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode343.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode343.java new file mode 100644 index 0000000..6b28608 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode343.java @@ -0,0 +1,47 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/11 11:14 + * @注释 + */ +public class LeetCode343 { + + @Test + public void test() { + System.out.println(new Solution().integerBreak(10)); + } + + class Solution { + /** + * dp[i] 表示 拆分出i后的乘积的最大值 + * dp[i] = 遍历 dp[i-j] * i 或者 i * j + * dp[i] 可能为两个数相乘,或者是多个数相乘(这时就需要遍历)。 + * 初始化 dp[0] = null;dp[1] = 1; + * + * [0 1 2 3 4 5 6 7 8 9 10] + * [1 1 1 2 4 6 9 12 16 27 36] + * + * + * @param n + * @return + */ + public int integerBreak(int n) { + + int[] dp = new int[n + 1]; +// dp[0] = 1; + dp[2] = 1; // 表示数字2可以划分为1+1 1*1为最大值 + for (int i = 2; i < n+1; i++) { + for (int j = 1; j < i - 1; j++) { + // Math.max((i - j) * j, dp[i - j] * j) 表示两个数相乘 和使用 前面的数相乘 + dp[i] = Math.max(dp[i], Math.max((i - j) * j, dp[i - j] * j)); + } + } + + return dp[n]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode344.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode344.java new file mode 100644 index 0000000..242423c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode344.java @@ -0,0 +1,40 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +public class LeetCode344 { + + @Test + public void test() { + char[] s = "helco1".toCharArray(); + new Solution().reverseString(s); + for (char c : s) { + System.out.println(c); + } + } + + + + class Solution { + + + public void reverseString(char[] s) { +// for (int i = 0; i < s.length / 2; i++) { +// char tmp = s[i]; +// s[i] = s[s.length - i - 1]; +// s[s.length - i - 1] = tmp; +// } + + int left = 0; + int right = s.length - 1; + while (left < right) { + char tmp = s[left]; + s[left] = s[right]; + s[right] = tmp; + left++; + right--; + } + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode347.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode347.java new file mode 100644 index 0000000..a491e87 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode347.java @@ -0,0 +1,140 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +/** + * + * + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/10 11:39 + * @注释 + * + * 347. 前 K 个高频元素 + + * 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 + * + * + * + * 示例 1: + * + * 输入: nums = [1,1,1,2,2,3], k = 2 + * 输出: [1,2] + * 示例 2: + * + * 输入: nums = [1], k = 1 + * 输出: [1] + * + * 提示: + * + * 1 <= nums.length <= 105 + * k 的取值范围是 [1, 数组中不相同的元素的个数] + * 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的 + * + * + * 进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。 + * + * + */ +public class LeetCode347 { + + @Test + public void test() { + for (int i : new Solution1().topKFrequent(new int[]{4,1,-1,2,-1,2,3}, 2)) { + System.out.println(i); + } + + + } + + class Solution { + + /** + * 先将 值 和 频率 存储在hashMap中 + * 使用一个大顶堆 + * 将前k个值导入,就形成了一个大顶堆(这个大顶堆维持k个) + * 后面的数据挨个导入, + * - 如果比当前最大值大,去除堆顶(堆顶是最小的值,比最小的值还大) + * - 导入 + * + * @param nums + * @param k + * @return + */ + public int[] topKFrequent(int[] nums, int k) { + + HashMap map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + + // 小顶堆 + PriorityQueue heap = new PriorityQueue<>(new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + // 一定要分清 0 正数 负数 + return map.get(o1) - map.get(o2); + } + }); + map.keySet().forEach(key -> { + // 导入前k个数据,作为基准堆 + if (heap.size() < k) { + heap.add(key); + } else if (map.get(key) > map.get(heap.peek())) { + // k个之外的数,如果频率比堆顶(目前堆频率最小的值)要大,就删除堆顶,加入此数(会自动调整到合适的位置) + heap.remove(); // 等于poll + heap.add(key); + } + }); + + int[] res = new int[k]; + int index = 0; + for (Integer integer : heap) { + res[index++] = integer; + } + return res; + } + } + + class Solution1 { + /** + * 全部导入大顶堆,获取前k个就好了 + * @param nums + * @param k + * @return + */ + public int[] topKFrequent(int[] nums, int k) { + + HashMap map = new HashMap<>(); + for (int num : nums) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + + // 大顶堆 + PriorityQueue heap = new PriorityQueue<>(new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o2[1] - o1[1]; + } + }); + + // 将所有entry存入堆 + for (Map.Entry entry : map.entrySet()) { + heap.add(new int[]{entry.getKey(), entry.getValue()}); + } + + int[] res = new int[k]; + // 获取堆的前k个数据 + for (int i = 0; i < k; i++) { + res[i] = heap.poll()[0]; + } + + return res; + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode35.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode35.java new file mode 100644 index 0000000..4967351 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode35.java @@ -0,0 +1,93 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 + * 请必须使用时间复杂度为 O(log n) 的算法。 + * + * 示例 1: + * 输入: nums = [1,3,5,6], target = 5 + * 输出: 2 + * 示例 2: + * 输入: nums = [1,3,5,6], target = 2 + * 输出: 1 + * 示例 3: + * 输入: nums = [1,3,5,6], target = 7 + * 输出: 4 + * + * 提示: + * + * 1 <= nums.length <= 104 + * -104 <= nums[i] <= 104 + * nums 为 无重复元素 的 升序 排列数组 + * -104 <= target <= 104 + */ +public class LeetCode35 { + + /** + * left左边的值一直保持小于target,right右边的值一直保持大于等于target, + * 而且left最终一定等于right+1, + * 这么一来,循环结束后, + * 在left和right之间画一条竖线,恰好可以把数组分为两部分: + * left左边的部分和right右边的部分,而且left左边的部分全部小于target,并以right结尾; + * right右边的部分全部大于等于target,并以left为首。 + * + * 所以最终答案一定在left的位置。 + * @param nums + * @param target + * @return + */ + public int searchInsert(int[] nums, int target) { + // 定义左右指针,分别指向数组的起始位置和结束位置 + int left = 0; + int right = nums.length - 1; + // 当左指针小于等于右指针时,进行循环 + while (left <= right) { + // 计算中间位置的索引 右边距减去左边距,右移一位,然后加上左边距,得到中间值 + // right-left 就是从0开始到n, 右移动一位就是除以2,获得到这个区间的一半,加上起始的left 就是(right + left)/2 + int middle = ((right - left) >> 1) + left; + // 如果中间位置的元素等于目标元素,返回中间位置的索引 + if (nums[middle] == target) { + return middle; + // 如果中间位置的元素大于目标元素,将右指针移动到中间位置的左侧一个位置 + } else if (nums[middle] > target) { + right = middle - 1; + // 如果中间位置的元素小于目标元素,将左指针移动到中间位置的右侧一个位置 + } else { + left = middle + 1; + } + } + // 当找不到目标元素时,返回左指针的值 + return left; + } + + + public int searchInsert1(int[] nums, int target) { + int left = 0; + int right = nums.length; + while (left < right) { + int middle = (right + left) / 2; + if (nums[middle] == target) { + return middle; + } else if (nums[middle] > target) { + right = middle ; + } else { + left = middle + 1; + } + } + return left; + } + + + @Test + public void Test() { + int[] ints = {1, 3, 5, 8,10}; + int[] ints1 = {}; + + int middle = ((8 - 4) >> 1) + 4; + + // 1000 - 0100 = 0100 >> 1 = 0010 ==> 2 + 4 + System.out.println(searchInsert1(ints, 2)); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode367.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode367.java new file mode 100644 index 0000000..98612fa --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode367.java @@ -0,0 +1,106 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * 给你一个正整数 num 。如果 num 是一个完全平方数,则返回 true ,否则返回 false 。 + * 完全平方数 是一个可以写成某个整数的平方的整数。换句话说,它可以写成某个整数和自身的乘积。 + * 不能使用任何内置的库函数,如 sqrt 。 + * + * 示例 1: + * + * 输入:num = 16 + * 输出:true + * 解释:返回 true ,因为 4 * 4 = 16 且 4 是一个整数。 + * + * + * 示例 2: + * + * 输入:num = 14 + * 输出:false + * 解释:返回 false ,因为 3.742 * 3.742 = 14 但 3.742 不是一个整数。 + * + * 提示: + * 1 <= num <= 231 - 1 + */ +public class LeetCode367 { + + /** + * 时间复杂度:O(logn) + * 空间复杂度:O(1) + * @param num + * @return + */ + public boolean isPerfectSquare(int num) { + int left = 0; + int right = num; + while (left <= right) { + int middle = (left + right) / 2; + if (middle * middle == num) { + return true; + } else if ((long) middle * middle > num) { + right = middle - 1; +// rigjt--; + } else { + // 如果middle * middle < num ,那么 寻找的区间就应该是 xx,middle) 或者说middle*middle 这个数太大了 +// left++; + left = middle + 1; + } + } + return false; + } + + + /** + * 代码中使用的 pow\texttt{pow}pow 函数的时空复杂度与 CPU 支持的指令集相关,这里不深入分析。 + * @param num + * @return + */ + public boolean isPerfectSquare1(int num) { + double sqrt = Math.sqrt(num); + // 判断有没有小数 + if (sqrt == (int) sqrt) { + return true; + } else { + return false; + } + } + + /** + * 时间复杂度:On + * 空间复杂 O1 + * @param num + * @return + */ + public boolean isPerfectSquare2(int num) { + // 暴力 + for (int i = 1; i <= num; i++) { + if ((long)i * i == num) { + return true; + } + } + return false; + } + + + + + @Test + public void main() { + LeetCode367 solution = new LeetCode367(); + + // Test case 1: num is a perfect square + int num1 = 16; + assertTrue(solution.isPerfectSquare1(num1)); + + // Test case 2: num is not a perfect square + int num2 = 15; + assertFalse(solution.isPerfectSquare1(num2)); + + } +} + + diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode376.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode376.java new file mode 100644 index 0000000..a0038cf --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode376.java @@ -0,0 +1,45 @@ +package cn.whaifree.leetCode.Greedy; + + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/24 13:23 + * @注释 + */ +public class LeetCode376 { + + @Test + public void test() { +// System.out.println(new Solution().wiggleMaxLength(new int[]{1, 7, 4, 9, 2, 5})); + System.out.println("========"); + System.out.println(new Solution().wiggleMaxLength(new int[]{1,17,5,10,13,15,10,5,16,8})); + } + + + class Solution { + public int wiggleMaxLength(int[] nums) { + if (nums.length <= 1) { + return nums.length; + } + //当前差值 + int curDiff = 0; + //上一个差值 + int preDiff = 0; + int count = 1; + for (int i = 1; i < nums.length; i++) { + //得到当前差值 + curDiff = nums[i] - nums[i - 1]; + //如果当前差值和上一个差值为一正一负 + //等于0的情况表示初始时的preDiff + if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) { + count++; + preDiff = curDiff; + } + } + return count; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode377.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode377.java new file mode 100644 index 0000000..cf5bce1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode377.java @@ -0,0 +1,104 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/27 11:46 + * @注释 + */ +public class LeetCode377 { + + @Test + public void test() { + int[] nums = {1, 2, 3}; + int target = 4; + int res = new Solution1().combinationSum4(nums, target); + System.out.println(res); + } + + + /** + * 超时 + */ + class Solution { + int sum = 0; + int res = 0; + public int combinationSum4(int[] nums, int target) { + backTracking(nums, target); + return res; + } + + public void backTracking(int[] nums, int target) { + if (sum == target) { + res++; + return; + } + if (sum > target) { + return; + } + + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + backTracking(nums, target); + sum -= nums[i]; + } + + } + + } + + /** + * dp 完全背包 + */ + class Solution1 { + + /** + * 1 2 3随意取,使得总包围target + * @param nums + * @param target + * @return + */ + public int combinationSum4(int[] nums, int target) { + + + // dp[j] 表示 从0-i-1任取,使得满足包容量为j的可能性 + /** + * 0 1 2 3 4 + * [1, 1, 0, 0, 0] + * [1, 1, 2, 0, 0] + * [1, 1, 2, 4, 0] + * [1, 1, 2, 4, 7] + */ + int[] dp = new int[target + 1]; + dp[0] = 1; // 都不放入 情况有一种 + for (int j = 1; j < target + 1; j++) { + for (int i = 0; i < nums.length; i++) { + if (j >= nums[i]) { + dp[j] = dp[j] + dp[j - nums[i]]; + // dp[j] 不放 + // dp[j - nums[i]] 放,放也有多种情况 + } + } + /** + * 如果把遍历nums(物品)放在外循环, + * 遍历target的作为内循环的话,举一个例子: + * 计算dp[4]的时候,结果集只有 {1,3} 这样的集合,忽略了{3,1} + */ + } + /** + * 如果求 组合数 就是外层for循环遍历物品,内层for遍历背包。 + * 如果求 排列数 就是外层for遍历背包,内层for循环遍历物品。 + */ + return dp[target]; + } + + + } + + + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode39.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode39.java new file mode 100644 index 0000000..ba469d2 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode39.java @@ -0,0 +1,51 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/6 23:57 + * @注释 + */ +public class LeetCode39 { + + @Test + public void test() { + new Solution().combinationSum(new int[]{2, 3, 6, 7}, 7).forEach( + list -> { + list.forEach(System.out::print); + System.out.println(); + } + ); + } + + + class Solution { + + List> res = new ArrayList<>(); + List path = new ArrayList<>(); + public List> combinationSum(int[] candidates, int target) { + backTracking(candidates, 0, target); + return res; + } + + public void backTracking(int[] candidates, int index, int need) { + if (need < 0) { + return; + } + if (need == 0) { + res.add(new ArrayList<>(path)); + } + for (int i = index; i < candidates.length ; i++) { + path.add(candidates[i]); + backTracking(candidates, i, need - candidates[i]); + path.remove(path.size() - 1); + } + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode392.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode392.java new file mode 100644 index 0000000..ce37a13 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode392.java @@ -0,0 +1,82 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/25 12:41 + * @注释 + */ +public class LeetCode392 { + @Test + public void test() { + String s = "abc"; + String t = "ahbgdc"; + boolean subsequence = new Solution1().isSubsequence(s, t); + System.out.println(subsequence); + } + + class Solution { + /** + * 子序列 + * s是否是t的子序列 + * + * dp[i][j] 表示 + * + * @param s + * @param t + * @return + */ + public boolean isSubsequence(String s, String t) { + + boolean flag = false; + int j = 0; + for (int i = 0; i < s.length(); i++) { + while (j < t.length()) { + if (s.charAt(i) == t.charAt(j)) { + flag = true; + j++; + break; + } + j++; + } + if (!flag) { + return false; + } + flag = false; + } + return true; + } + } + + class Solution1 { + /** + * dp[i][j]表示s的i到t的j 相同子序列的长度 + * + * 转变为 求两个序列相同子序列的长度 + * + * ahbgdc + * acbdc + * @param s + * @param t + * @return + */ + public boolean isSubsequence(String s, String t) { + + int[][] dp = new int[s.length() + 1][t.length() + 1]; + char[] s1 = s.toCharArray(); + char[] t1 = t.toCharArray(); + for (int i = 1; i <= s1.length; i++) { + for (int j = 1; j <= t1.length; j++) { + if (s1[i - 1] == t1[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]); + } + } + } + return dp[s1.length][t1.length] == s1.length; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode40.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode40.java new file mode 100644 index 0000000..a040d47 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode40.java @@ -0,0 +1,76 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/6 23:57 + * @注释 + */ +public class LeetCode40 { + + @Test + public void test() { + new Solution().combinationSum2(new int[]{10,1,2,7,6,1,5}, 8).forEach( + list -> { + list.forEach(System.out::print); + System.out.println(); + } + ); + } + + + class Solution { + + List> res = new LinkedList<>(); + List path = new ArrayList<>(); + boolean[] used; + + /** + * 结果不能重复!!!! + * 1. 排序candidates + * 2. 使用used[]数组记录使用 + * 3. 一旦candi[index]==cnadi[index-1]&&user[index]=true,那么就是用过的,不添加 + * @param candidates + * @param target + * @return + */ + public List> combinationSum2(int[] candidates, int target) { + Arrays.sort(candidates); + used = new boolean[candidates.length]; + backTracking(candidates, 0, target); + return res; + } + + public void backTracking(int[] candidates, int index, int need) { + if (need < 0) { + return; + } + if (need == 0) { + res.add(new ArrayList<>(path)); + } + for (int i = index; i < candidates.length ; i++) { + + // 取第一个数先 used放1,再放0; + // 取第二个数时,如果can两个数相同,并且used为0,表示前一个数用过。 + // 如果 used为1,表示还没从递归中出来,即是【1,1】中的第二个1,是需要的 + if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) { + continue; + } + + path.add(candidates[i]); + used[i] = true; + backTracking(candidates, i+1, need - candidates[i]); + used[i] = false; + path.remove(path.size() - 1); + } + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode404.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode404.java new file mode 100644 index 0000000..f42406f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode404.java @@ -0,0 +1,96 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/24 19:03 + * @注释 + */ +public class LeetCode404 { + + @Test + public void test(){ + TreeNode treeNode = TreeNode.constructTree(new Integer[]{3,9,20,null,null,15,7}); + treeNode.printTree(); + System.out.println(new Solution2().sumOfLeftLeaves(treeNode)); + } + + class Solution { + public int sumOfLeftLeaves(TreeNode root) { + if (root == null) { + return 0; + } + int right = sumOfLeftLeaves(root.right); + int left = sumOfLeftLeaves(root.left); + + // 如果左边存在,且是叶子节点,再返回 + if (root.left != null && root.left.left == null && root.left.right == null) { + return left + right + root.left.val; + } + return left + right; + } + } + + class Solution1 { + public int sumOfLeftLeaves(TreeNode root) { + if (root == null) { + return 0; + } + Deque stack = new LinkedList<>(); + stack.push(root); + // 遍历 + while (!stack.isEmpty()) { + TreeNode pop = stack.pop(); + if (pop != null) { + // 遇到没进入过的节点 + if (pop.right!=null) stack.push(pop.right); + if (pop.left!=null) stack.push(pop.left); + stack.push(pop); + stack.push(null); + + } else { + TreeNode pop1 = stack.pop(); +// if (pop1.left.left == null && pop1.left.right == null) { +// +// } + } + } + return 1; + } + } + + class Solution2 { + public int sumOfLeftLeaves(TreeNode root) { + if (root == null) { + return 0; + } + Deque deque= new LinkedList<>(); + deque.add(root); + // 遍历 + int sum = 0; + while (!deque.isEmpty()) { + TreeNode pop = deque.pop(); + if (pop.right != null) { + deque.add(pop.right); + } + if (pop.left != null) { + // left是叶子节点,并且是左边 + if (pop.left.right == null && pop.left.left == null) { + sum += pop.left.val; + } + deque.add(pop.left); + } + + } + return sum; + } + } +} + diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode406.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode406.java new file mode 100644 index 0000000..3fa6ba1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode406.java @@ -0,0 +1,66 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.util.*; +import java.util.function.IntFunction; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/29 11:52 + * @注释 + */ +public class LeetCode406 { + + @Test + public void test() throws InterruptedException { + int[][] ints = new int[][]{ + {7,0},{4,4},{7,1},{5,0},{6,1},{5,2} + }; + + String gc = new String("gc"); + List list = new LinkedList<>(); + int i = 0; + while (true) { + list.add(gc + gc + i++); + } + +// for (int[] i : new Solution().reconstructQueue(ints)) { +// System.out.println(Arrays.toString(i)); +// } + } + + class Solution { + public int[][] reconstructQueue(int[][] people) { + // {7,0},{4,4},{7,1},{5,0},{6,1},{5,2} + Arrays.sort(people, new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + if (o1[0] == o2[0]) { + // 身高相同时,前面数量少的在前 + return o1[1] - o2[1]; + }else { + return o2[0] - o1[0]; + } + } + }); + for (int[] person : people) { + System.out.println(Arrays.toString(person)); + } + + System.out.println("===="); + + // 排序: [[7,0], [7,1], [6,1], [5,0], [5,2],[4,4]] + List list = new LinkedList<>(); + + // 节点i的前面必然都比i高,那么只要把i插入到i[1]对应的位置,必然满足条件 + for (int[] p : people) { + list.add(p[1],p); + } + + return list.toArray(new int[people.length][]); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode415.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode415.java new file mode 100644 index 0000000..4dee1ae --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode415.java @@ -0,0 +1,70 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +public class LeetCode415 { + + @Test + public void main() { + System.out.println(new Solution().addStrings("111", "59999")); + } + + + class Solution { + public String addStrings(String num1, String num2) { + char[] c1 = num1.toCharArray(); + char[] c2 = num2.toCharArray(); + int index1 = c1.length - 1; + int index2 = c2.length - 1; + StringBuilder stringBuilder = new StringBuilder(); + boolean retail = false; + while (index1 >= 0 && index2 >= 0) { + int char1 = c1[index1] - '0'; + int char2 = c2[index2] - '0'; + int tmpAns = char1 + char2; + if (retail) { + tmpAns += 1; + retail = false; + } + if (tmpAns >= 10) { + tmpAns %= 10; + retail = true; + } + stringBuilder.append(tmpAns); + index2--; + index1--; + } + + while (index1 >= 0) { + int tmpAns = c1[index1--] - '0'; + if (retail) { + tmpAns += 1; + retail = false; + } + if (tmpAns >= 10) { + tmpAns %= 10; + retail = true; + } + stringBuilder.append( tmpAns); + } + + while (index2 >= 0) { + int tmpAns = c2[index2--] - '0'; + if (retail) { + tmpAns += 1; + retail = false; + } + if (tmpAns >= 10) { + tmpAns %= 10; + retail = true; + } + stringBuilder.append(tmpAns); + } + + if (retail) { + stringBuilder.append(1); + } + return stringBuilder.reverse().toString(); + } + } +} \ No newline at end of file diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode416.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode416.java new file mode 100644 index 0000000..655342b --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode416.java @@ -0,0 +1,207 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/14 12:24 + * @注释 + */ +public class LeetCode416 { + + + @Test + public void test() { + int[] nums = {1,2,3,5}; + boolean canPartition = new Solution3().canPartition(nums); + System.out.println(canPartition); + } + +// class Solution { +// /** +// * 分割为2部分 +// * @param nums +// * @return +// */ +// public boolean canPartition(int[] nums) { +// Arrays.sort(nums); +// +// int rightSum = 0; +// for (int num : nums) { +// rightSum += num; +// } +// int leftSum = 0; +// for (int i = 0; i < nums.length; i++) { +// if (leftSum == rightSum) { +// return true; +// } else if (leftSum > rightSum) { +// return false; +// } +// leftSum += nums[i]; +// rightSum -= nums[i]; +// } +// return false; +// } +// } + + class Solution { + + int sumHalf = 0; + int nowSum = 0; + /** + * 回溯 + * + * @param nums + * @return + */ + public boolean canPartition(int[] nums) { + for (int num : nums) { + sumHalf += num; + } + sumHalf /= 2; + return backTracking(nums, 0); + } + + public boolean backTracking(int[] nums, int start) { + if (nowSum == sumHalf) { + return true; + }else if (nowSum>sumHalf){ + return false; + } + + boolean b = false; + for (int i = start; i < nums.length; i++) { + nowSum += nums[i]; + b = backTracking(nums, i + 1); + // 不行,有可能某些元素没在集合内 + nowSum -= nums[i]; + if (b==true) return true; + } + + return b; + } + } + + + class Solution2 { + /** + * 转换为背包问题 + * nums 为商品的重量、同时为商品的价值 + * 背包容量为sum/2 且需要装满 + * + * 0 1 2 3 4 5 + * 0 0 n0 n0 n0 n0 n0 + * 1 0 + * 2 0 + * 3 0 + * 4 0 + * 5 0 + * + * 不放东西的最大价值 dp[i][j] = dp[i-1][j] + * 放东西的最大价值 max(dp[i-1][j] , dp[i-1][j-nums[i]]+values[i]) + * + * @param nums + * @return + */ + public boolean canPartition(int[] nums) { + int sumHalf = 0; + for (int num : nums) { + sumHalf += num; + } + if (sumHalf % 2 != 0) { + return false; + } + sumHalf /= 2; + + int length = nums.length; + int[][] dp = new int[length][sumHalf + 1]; +// for (int i = 0; i < length; i++) { +// dp[i][0] = 0; +// } + for (int i = nums[0]; i <= sumHalf; i++) { + dp[0][i] = nums[0]; + } + + for (int i = 1; i < length; i++) { + for (int j = 1; j <= sumHalf; j++) { + if (nums[i] > j) { + // 放不下 + dp[i][j] = dp[i - 1][j]; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]); + } + + if (dp[i][j] == sumHalf) { + return true; + } + } + } + return false; + } + } + + class Solution3 { + /** + * 将nums的元素放入背包中 + * 1. 背包容量 sum/2 + * 2. 物品i重量nums[i];价值nums[i] + * + * 0 1 2 3 4 5 + * 0 + * 1 + * 2 + * + * dp[j]表示 j背包容量的最大价值 + * + * + * + * // 递推公式 + * 2. 放下 dp[j] = max(dp[j], dp[j-weight[i]]+nums[i]) + * + * 从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了。 + * + * @param nums + * @return + */ + public boolean canPartition(int[] nums) { + + int sum = 0; + for (int num : nums) { + sum += num; + } + + if (sum % 2 != 0) { + return false; + } + + // 包裹最大容量 + int packageCapacity = sum / 2; + + int[] dp = new int[packageCapacity + 1]; + + for (int i = 0; i < nums.length; i++) { + // 包的容量必须大于物品i重量才能放进去 + /** + * 如果正序遍历 + * dp[1] = dp[1 - weight[0]] + value[0] = 15 + * 此时容量1的背包已经放入了 + * dp[2] = dp[2 - weight[0]] + value[0] = 30 + * 此时又放入了一次 + */ + for (int j = packageCapacity; j >= nums[i]; j--) { + dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]); + //剪枝一下,每一次完成內層的for-loop,立即檢查是否dp[target] == target,優化時間複雜度(26ms -> 20ms) + if(dp[packageCapacity] == packageCapacity) + return true; + } + } + + // 包裹容量和目标值一样 + return dp[packageCapacity] == packageCapacity; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode429.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode429.java new file mode 100644 index 0000000..4439cb0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode429.java @@ -0,0 +1,102 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.Node; +import org.junit.Test; + +import java.util.*; +import java.util.function.Consumer; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/18 10:05 + * @注释 + */ +public class LeetCode429 { + + + @Test + public void test() { + Node node = new Node(1); + node.children = new LinkedList<>(); + node.children.add(new Node(2)); + node.children.add(new Node(3)); + node.children.add(new Node(4)); + node.children.get(2).children = new ArrayList<>(); + node.children.get(2).children.add(new Node(6)); + node.children.get(2).children.add(new Node(7)); + + List> lists = new Solution1().levelOrder(node); + System.out.println(lists); + + } + + class Solution { + public List> levelOrder(Node root) { + + + List> res = new LinkedList<>(); + + if (root == null) { + return res; + } + Deque queue = new LinkedList<>(); + + queue.add(root); + while (!queue.isEmpty()) { + + int size = queue.size(); + List e = new ArrayList<>(); + for (int i = 0; i < size; i++) { + Node pop = queue.pop(); + e.add(pop.val); + List children = pop.children; + if (children != null && !children.isEmpty()) { + children.forEach(new Consumer() { + @Override + public void accept(Node node) { + queue.add(node); + } + }); + } + } + res.add(e); + + } + return res; + } + } + + /** + * 递归实现 + */ + class Solution1 { + List> res = new ArrayList<>(); + public List> levelOrder(Node root) { + if (root == null) { + return res; + } + level(root, 0); + return res; + } + + void level(Node root, int level) { + + if (root == null) { + return; + } + // 没有对应的层数值就创建 + if (res.size() <= level) { + res.add(new ArrayList<>()); + } + List e = res.get(level); + e.add(root.val); + List children = root.children; + if (children != null) { + children.forEach( + node -> level(node, level + 1) + ); + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode435.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode435.java new file mode 100644 index 0000000..b412933 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode435.java @@ -0,0 +1,108 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/4 15:46 + * @注释 + */ +public class LeetCode435 { + + @Test + public void test() { + // intervals = [[1,2],[2,3],[3,4],[1,3]] + int[][] ints = {{1, 2}, {1, 3}, {2, 3}, {3, 4}}; + System.out.println(new Solution1().eraseOverlapIntervals(ints)); + } + + class Solution { + public int eraseOverlapIntervals(int[][] intervals) { + Arrays.sort(intervals, new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o1[0] - o2[0]; + } + }); + + int sub = 0; + for (int i = 1; i < intervals.length; i++) { + if (intervals[i][0] <= intervals[i - 1][1]) { + sub++; + intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]); + }else { + intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]); + } + } + + return sub; + } + + } + + class Solution1 { + + /** + * 想象成一次性最多参加几个活动 + * 按照结束时间排序。 + * + * 每次right边界就是取最早活动结束的时间; + * 如果某次活动开始时间刚刚好比上一个活动结束的时间要晚,那么就能多参加一次活动 + * + * @param intervals + * @return + */ + public int eraseOverlapIntervals(int[][] intervals) { + Arrays.sort(intervals, new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o1[1] - o2[1]; + } + }); + + int normalCount = 1; + int right = intervals[0][1]; + for (int i = 1; i < intervals.length; i++) { + // 如果这次活动的开始时间比上个活动结束的时间要早,那么这个活动就不参加了 + if (intervals[i][0] >= right) { + // 如果这次活动的开始时间比上个活动结束的时间要晚,那么这个活动就可以参加 + // 最新的结束时间更新为这个活动的结束时间 + right = intervals[i][1]; + normalCount++; + } + } + return intervals.length - normalCount; + } + + } + + class Solution2 { + public int eraseOverlapIntervals(int[][] intervals) { + Arrays.sort(intervals, new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o1[1] - o2[1]; + } + }); + + int normalCount = 1; + for (int i = 1; i < intervals.length; i++) { + + if (intervals[i - 1][1] <= intervals[i][0]) { + normalCount++; + } else { + // i的右边界有不重合,则正常区间+1 + intervals[i][1] = Math.min(intervals[i - 1][1], intervals[i][1]); + } + } + + return intervals.length - normalCount; + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode45.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode45.java new file mode 100644 index 0000000..04b653d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode45.java @@ -0,0 +1,102 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/27 11:01 + * @注释 + */ +public class LeetCode45 { + + @Test + public void test() { + System.out.println(new Solution().jump(new int[]{2,3,1,1,4})); + } + + class Solution { + /** + * 每个区间内只有一个最跳数 + * 每个区间只增加一次jump + * 1. 标记临时最大区间 + * 2. 标记区间结束时jump++ + * @param nums + * @return + */ + public int jump(int[] nums) { + + // 最远覆盖范围能否到达nums.length-1 + + if (nums.length == 1) { + return 0; + } + + // 最大覆盖范围 + int maxCover = 0; + + // 当前index覆盖范围区间 + int curInterval = 0; + int jumpCount = 0; + for (int i = 0; i < nums.length; i++) { + // 当前最大覆盖区间 + maxCover = Math.max(maxCover, i + nums[i]); + + // 必须等待区间增加后再判断是否到末位 + if (maxCover >= nums.length - 1) { + jumpCount++; + break; + } + + // 如果到了当前index覆盖的区间最后一个 + if (i == curInterval) { + jumpCount++; + curInterval = maxCover; + + } + + + } + return jumpCount; + } + } + + class Solution1 { + /** + * 每个区间内只有一个最跳数 + * 每个区间只增加一次jump + * 1. 标记临时最大区间 + * 2. 到达最大跳数++ + * @param nums + * @return + */ + public int jump(int[] nums) { + + // 最远覆盖范围能否到达nums.length-1 + + if (nums.length == 1) { + return 0; + } + + // 最大覆盖范围 + int maxCover = 0; + + // 当前index覆盖范围区间 + int curInterval = 0; + int jumpCount = 0; + for (int i = 0; i < nums.length - 1; i++) { + // if (nextDistance >= nums.size() - 1) break; + // 让nums.length变成num.length-1 本质是一样的 + + // 当前最大覆盖区间 + maxCover = Math.max(maxCover, i + nums[i]); + if (i == curInterval) { + jumpCount++; + curInterval = maxCover; + } + } + return jumpCount; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode450.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode450.java new file mode 100644 index 0000000..acae216 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode450.java @@ -0,0 +1,157 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/31 9:38 + * @注释 + */ +public class LeetCode450 { + + @Test + public void test() { + new Solution1().deleteNode(TreeNode.constructTreeByArray(5,3,6,2,4,null,7,null,null), 0).printTree(); + + } + + class Solution { + public TreeNode deleteNode(TreeNode root, int key) { + if (root == null) { + return null; + } + + if (root.left == null && root.right == null && root.val == key) { + return null; + } + + + TreeNode pre = null; + TreeNode tmp = root; + while (tmp!=null) { + if (tmp.val > key) { + pre = tmp; + tmp = tmp.left; + } else if (tmp.val < key) { + pre = tmp; + tmp = tmp.right; + } else { + break; + } + } + + // 找不到该要删除的节点 + if (pre != null && pre.val != key && tmp == null) { + return root; + } + + + + // 左右都为空 + // 左为空 + // 右为空 + if (pre.left == tmp) { + if (tmp.right == null && tmp.left == null) { + pre.left = null; + } else if (tmp.left == null) { + pre.left = tmp.right; + } else if (tmp.right == null) { + pre.left = tmp.left; + } + }else if (pre.right == tmp){ + if (tmp.right == null && tmp.left == null) { + pre.right = null; + } else if (tmp.left == null) { + pre.right = tmp.right; + } else if (tmp.right == null) { + pre.right = tmp.left; + } + } + // 左右都不空 + // tmp.left移动到tmp.right.left.....最后 + TreeNode move = tmp.right; + while (move.left != null) { + move = move.left; + } + move.left = tmp.left; + // tmp.right.left移动到tmp的位置 有可能在pre的左边或右边 + if (pre.left == tmp) { + pre.left = tmp.right; + } else { + pre.right = tmp.right; + } + return root; + } + } + + + class Solution1 { + /** + * 递归 + * @param root + * @param key + * @return + */ + public TreeNode deleteNode(TreeNode root, int key) { + + if (root == null) { + return root; + } + if (root.val == key) { + + // 左边为空 返回右边 + // 两边都为空,则返回空,随便返回子节点 + if (root.left == null) { + return root.right; + } + if (root.right == null) { + return root.left; + } + TreeNode index = root.right; + while (index.left != null) { + index = index.left; + } + index.left = root.left; + return root.right; + } + + if (root.val > key) { + root.left = deleteNode(root.left, key); + } else if (root.val < key) { + root.right = deleteNode(root.right, key); + } + return root; + } + } + + /** + * 把二叉树变成链表 + */ + class Solution2 { + TreeNode pre = new TreeNode(); + TreeNode cur = pre; + + public TreeNode deleteNode(TreeNode root, int key) { + search(root, key); + return pre.right; + } + + private void search(TreeNode root, int key) { + if (root == null) { + return; + } + search(root.left, key); + TreeNode r = root.right; + if (root.val != key) { + cur.right = root; + root.left = null; + root.right = null; + cur = cur.right; + } + search(r, key); + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode452.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode452.java new file mode 100644 index 0000000..2e9e282 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode452.java @@ -0,0 +1,94 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Comparator; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/4 14:25 + * @注释 + */ +public class LeetCode452 { + + @Test + public void test() { + // [[3,9],[7,12],[3,8],[6,8],[9,10],[2,9],[0,9],[3,9],[0,6],[2,8]] + int[][] ints = { + {3,9},{7,12},{3,8},{6,8},{9,10},{2,9},{0,9},{3,9},{0,6},{2,8} + }; + + + System.out.println(new Solution1().findMinArrowShots(ints)); + } + + class Solution { + /** + * + * 按照最近出从小到大排序,判断下一个区间是否有交集 + * - 有交集,取交集最小值作为都能bomb的点 + * - 没有交集 res++表示下一个区间的箭 + * @param points + * @return + */ + public int findMinArrowShots(int[][] points) { + // 先按首位从小到大排序,end为start结束,此区间全部bomb + Arrays.sort(points, new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return Long.compare(o1[0], o2[0]); + } + }); + + int res = 1; + for (int i = 1; i < points.length; i++) { + + if (points[i][0] < points[i - 1][1]) { + // 新的区间,有交集 + points[i][1] = Math.min(points[i][1], points[i - 1][1]); + }else { + res++; + } + + } + + return res; + } + + } + + class Solution1 { + /** + * 按照最远处排序,判断下一元素是否在上一个的区间内,不是就res++ + * @param points + * @return + */ + public int findMinArrowShots(int[][] points) { + //按最远处从小到大排序 + Arrays.sort(points, new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + //-2147483646,-2147483645],[2147483646,2147483647 这个用例 + return Long.compare(o1[1], o2[1]); + } + }); + + int res = 1; + int right = points[0][1]; + for (int i = 1; i < points.length; i++) { + if (points[i][0] <= right) { + //当前箭能够射穿这个气球 + continue; + } + res++; + right = points[i][1]; + } + + return res; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode453.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode453.java new file mode 100644 index 0000000..eeec099 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode453.java @@ -0,0 +1,64 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/29 12:54 + * @注释 + */ +public class LeetCode453 { + @Test + public void test() + { + int[] nums = {1, 1,1}; + int res = new Solution1().minMoves(nums); + System.out.println(res); + } + + class Solution { + /** + * 让n-1个元素加1 等价于让1个元素-1,直到全部元素相等 + * @param nums + * @return + */ + public int minMoves(int[] nums) { + int min = Integer.MAX_VALUE; + for (int num : nums) { + min = Math.min(min, num); + } + int res = 0; + for (int num : nums) { + res += Math.abs(min - num); + } + return res; + } + } + + class Solution1 { + /** + * 让n-1个元素加1 等价于让1个元素-1,直到全部元素相等 + * 前缀和解法 + * @param nums + * @return + */ + public int minMoves(int[] nums) { + + // 获取前缀和 + int length = nums.length; + int[] preSum = new int[length + 1]; + // 找到最小的元素的index + int minIndex = 0; + for (int i = 1; i <= length; i++) { + if (nums[minIndex] > nums[i - 1]) { + minIndex = i - 1; + } + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + + return preSum[length] - nums[minIndex] * length; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode455.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode455.java new file mode 100644 index 0000000..ea45620 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode455.java @@ -0,0 +1,59 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/24 13:04 + * @注释 + */ +public class LeetCode455 { + + @Test + public void test() { + System.out.println(new Solution().findContentChildren(new int[]{1, 2, 3,1}, new int[]{2,3,1})); + } + + class Solution { + /** + * + * @param g 孩子的胃口 + * @param s 饼干 + * @return + */ + public int findContentChildren(int[] g, int[] s) { + // 找到g中最大的,分配s中最大的看看是否满足 + Arrays.sort(g); + Arrays.sort(s); + + int res = 0; + + + int gIndex = g.length-1; + int sIndex = s.length - 1; + while (sIndex >= 0 && gIndex >= 0) { + + // 饼干可以分配,就让两个指针-- + if (s[sIndex] >= g[gIndex]) { + res++; + sIndex--; + gIndex--; + } else { + // 饼干不能分配,就分配给更小的孩子 + gIndex--; + } + } + + return res; + } + + + + + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode459.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode459.java new file mode 100644 index 0000000..3105275 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode459.java @@ -0,0 +1,71 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/7 11:49 + * @注释 + */ +public class LeetCode459 { + @Test + public void test() { + String s = "aa"; + Solution solution = new Solution(); + boolean repeatedSubstringPattern = solution.repeatedSubstringPattern(s); + System.out.println(repeatedSubstringPattern); + + + String aabaaf = "aabaaf"; + int[] ints = conNext(new int[aabaaf.length()], aabaaf); + System.out.println(Arrays.toString(ints)); + + } + + class Solution { + + /** + * 如果一个串能s被子串重复出现组成 abcabc 由两个abc组成 + * - s+s如果能被s组成 abcabcabcabc能被abcabc组成 + * @param s + * @return + */ + public boolean repeatedSubstringPattern(String s) { + if (s.length() == 1) { + return false; + } + String contact = s.substring(1) + s.substring(0, s.length() - 1); + if (contact.contains(s)) { + return true; + } + return false; + } + } + + public int[] conNext(int[] next, String s) { + + // 1. 初始化 + int j = 0; // 前缀 + + // i 为后缀 + for (int i = 1; i < next.length; i++) { + //如果前缀后缀不相同,不断往前跳前缀 + while (j > 0 && s.charAt(i) != s.charAt(j)) { + j = next[j - 1]; + } + //前后缀相同,设置next[i]为next[i-1]+1, 并且j++ + if (s.charAt(i) == s.charAt(j)) { + j++; + } + // 表示j前后相同的部分 aabaa 如果j指向b i指向a,那么i前面经历过两次s.i==s.j 对应j=2,那么next i对应位置的下标就是前缀j=2 + // 实际就是两个指针不断对比,如果一样就继续对比下一个数,如果不一样就让前缀j进行回退 + next[i] = j; + } + return next; + } + + // 如何找到 +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode46.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode46.java new file mode 100644 index 0000000..79f31ef --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode46.java @@ -0,0 +1,92 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/19 11:01 + * @注释 + */ +public class LeetCode46 { + @Test + public void test() { + new Solution1().permute(new int[]{1, 2, 3}).forEach( + list -> { + System.out.println(list); + } + ); + } + + class Solution { + + List> res = new ArrayList<>(); + List path = new ArrayList<>(); + boolean[] used = null; + + + public List> permute(int[] nums) { + used = new boolean[nums.length]; + backTracking(nums); + return res; + } + + public void backTracking(int[] nums) { + + if (path.size() == nums.length) { + res.add(new ArrayList<>(path)); + return; + } + + for (int i = 0; i < nums.length; i++) { + if (used[i] == true) { + continue; + } + used[i] = true; + path.add(nums[i]); + backTracking(nums); + used[i] = false; + path.remove(path.size() - 1); + } + + } + + + } + + class Solution1 { + + List> res = new ArrayList<>(); + List path = new ArrayList<>(); + + + public List> permute(int[] nums) { + backTracking(nums); + return res; + } + + public void backTracking(int[] nums) { + + if (path.size() == nums.length) { + res.add(new ArrayList<>(path)); + return; + } + + for (int i = 0; i < nums.length; i++) { + if (path.contains(nums[i])) { + continue; + } + path.add(nums[i]); + backTracking(nums); + path.remove(path.size() - 1); + } + + } + + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode462.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode462.java new file mode 100644 index 0000000..8ccbce0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode462.java @@ -0,0 +1,50 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/29 13:15 + * @注释 + */ +public class LeetCode462 { + + @Test + public void test() + { + Solution solution = new Solution(); + int[] nums = {1,2,3}; + int i = solution.minMoves2(nums); + System.out.println(i); + } + + class Solution { + /** + * +1 或 -1 + * @param nums + * @return + */ + public int minMoves2(int[] nums) { + // 排序后找到中位数 + Arrays.sort(nums); + // 前缀和 + int length = nums.length; + int[] preSum = new int[length + 1]; + for (int i = 1; i < preSum.length; i++) { + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + // 中位数 + int middleIndex = length / 2; + int middleValue = nums[middleIndex]; + + int left = middleIndex * middleValue - preSum[middleIndex]; + int right = preSum[preSum.length - 1] - preSum[middleIndex] - (length - middleIndex) * middleValue; + return left + right; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode468.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode468.java new file mode 100644 index 0000000..3a85cc7 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode468.java @@ -0,0 +1,82 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/19 22:08 + * @注释 + */ +public class LeetCode468 { + + @Test + public void test() { + + System.out.println(5 & 0xFF); + + Solution solution = new Solution(); + System.out.println(solution.validIPAddress("20EE:Fb8:85a3:0:0:8A2E:0370:7334:12")); + } + + class Solution { + public String validIPAddress(String queryIP) { + boolean ipv6 = queryIP.contains(":"); + if (ipv6 && isIpv6(queryIP)) { + return "IPv6"; + } else if (!ipv6 && isIpv4(queryIP)){ + return "IPv4"; + } + return "Neither"; + } + + + public boolean isIpv6(String s) { + String[] split = s.split(":", -1); + if (split.length != 8) { + return false; + } + for (String item : split) { + if (item.length() > 4 || item.isEmpty()) { + return false; + } + + try { + int i = Integer.parseInt(item, 16);// 16进制 + + } catch (Exception e) { + return false; + } + } + return true; + } + + public boolean isIpv4(String s) { + String[] split = s.split("\\."); + if (split.length != 4) { + return false; + } + for (String item : split) { + if (item.length() > 3 || item.isEmpty()) { + return false; + } + try { + int i = Integer.parseInt(item); + if (i == 0 && item.length() != 1) { + return false; + } + if (item.startsWith("0") && i != 0) { // 00.0.0.0. + return false; + } + if (i < 0 || i > 255) { + return false; + } + } catch (Exception e) { + return false; + } + + } + return true; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode47.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode47.java new file mode 100644 index 0000000..ca58e3e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode47.java @@ -0,0 +1,126 @@ +package cn.whaifree.leetCode.BackTracking; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/19 16:41 + * @注释 + */ +public class LeetCode47 { + + @Test + public void test(){ + new Solution1().permuteUnique(new int[]{1, 1, 2}).forEach( + list -> { + System.out.println(list); + + } + ); + } + + /** + * 使用层的set+路径的bool[] + */ + class Solution { + + List> res = new ArrayList<>(); + List path = new ArrayList<>(); + boolean[] used = null; + /** + * 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 + * 相比46题,不重复 + * @param nums + * @return + */ + public List> permuteUnique(int[] nums) { + used = new boolean[nums.length]; + + backTracking(nums); + + return res; + } + + public void backTracking(int[] nums) { + if (path.size() == nums.length) { + res.add(new ArrayList<>(path)); + return; + } + + // 这个set用来对每层进行过滤,每层不能重复 + // used对每个路径进行过滤,没个路径不会出现同一个index,但有可能多个index都是同一个元素 + HashSet set = new HashSet<>(); + for (int i = 0; i < nums.length; i++) { + if (used[i] == true || set.contains(nums[i])) { + continue; + } + set.add(nums[i]); + used[i] = true; + path.add(nums[i]); + backTracking(nums); + used[i] = false; + path.remove(path.size() - 1); + } + } + } + + /** + * 使用排序+used + */ + class Solution1 { + + List> res = new ArrayList<>(); + List path = new ArrayList<>(); + boolean[] used = null; + /** + * 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 + * 相比46题,不重复 + * @param nums + * @return + */ + public List> permuteUnique(int[] nums) { + used = new boolean[nums.length]; + Arrays.sort(nums); + + backTracking(nums); + return res; + } + + public void backTracking(int[] nums) { + if (path.size() == nums.length) { + res.add(new ArrayList<>(path)); + return; + } + + + for (int i = 0; i < nums.length; i++) { + // used[i - 1] == false,说明同⼀树层nums[i - 1]使⽤过 + // 如果同⼀树层nums[i - 1]使⽤过则直接跳过 + // 一层 + if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) { + continue; + } + // used[i] == true,说明同⼀树⽀nums[i]使⽤过 + // 这个路径上被使用过 + // 一条路径 + if (used[i]) { + continue; + } + used[i] = true; + path.add(nums[i]); + backTracking(nums); + used[i] = false; + path.remove(path.size() - 1); + } + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode474.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode474.java new file mode 100644 index 0000000..78de04f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode474.java @@ -0,0 +1,109 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/26 11:49 + * @注释 + */ +public class LeetCode474 { + + @Test + public void test() + { + String[] strs = {"10","0001","111001","1","0"}; + int m = 5; + int n = 3; +// System.out.println(new Solution().findMaxForm(strs, m, n)); + // "10", "0", "1" + strs = new String[]{"10","0","1"}; + System.out.println(new Solution1().findMaxForm(strs, 1, 1)); + + } + class Solution { + public int findMaxForm(String[] strs, int m, int n) { + + // 三维 dp[i][j][k] 表示在前i个字符串中,包含了了j个0和k个1的最大子集长度 + // String[i]为物品 j k 为背包 + // 初始化: 当物品i=0 ,表示在前0个字符串中,没有字符串可以使用,dp[0][j][k]=0 + // 递推公式: + // 获取0的数量numZero 获取1的数量numOne + // 当j=zeroNumber + int[][] dp = new int[m + 1][n + 1]; + + for (String str : strs) { + int zeroNumber = calculateZeroNumber(str); + int oneNumber = str.length() - zeroNumber; + for (int j = m; j >= zeroNumber; j--) { + for (int k = n; k >= oneNumber; k--) { + dp[j][k] = Math.max(dp[j - zeroNumber][k - oneNumber] + 1, dp[j][k]); + } + } + } + + return dp[m][n]; + } + + public int calculateZeroNumber(String str) + { + int num = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) == '0') + { + num++; + } + } + return num; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode48.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode48.java new file mode 100644 index 0000000..b53cb12 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode48.java @@ -0,0 +1,90 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/15 12:00 + * @注释 + */ +public class LeetCode48 { + + @Test + public void test() + { + // [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]] + int[][] matrix = new int[][]{{5,1,9,11},{2,4,8,10},{13,3,6,7},{15,14,12,16}}; + Solution solution = new Solution(); + solution.rotate(matrix); + } + + class Solution { + public void rotate(int[][] matrix) { + // 1 1 1 3 + // 1 2 2 3 + // 1 3 3 3 + + // 1 1 1 4 + // 1 2 2 4 + // 1 3 3 4 + // 1 4 4 4 + + // 1 1 1 4 + // 1 4 4 4 + // 4 4 4 1 + // 4 1 1 1 + + // 1 2 2 1 + // 2 1 2 3 + // 2 3 3 2 + // 3 2 2 1 + // 2 1 1 2 + + int length = matrix.length; + + + for (int i = 0; i < length / 2; i++) { + for (int j = i; j < length - 1 - i; j++) { + int tmp = matrix[i][j]; + matrix[i][j] = matrix[length - j - 1][i]; + matrix[length - j - 1][i] = matrix[length - i - 1][length - j - 1]; + matrix[length - i - 1][length - j - 1] = matrix[j][length - i - 1]; + matrix[j][length - i - 1] = tmp; + } + } + +// int i = 0; +// for (int j = i; j < length - 1; j++) { +// int tmp = matrix[i][j]; +// matrix[i][j] = matrix[length - j - 1][i]; +// matrix[length - j - 1][i] = matrix[length - i - 1][length - j - 1]; +// matrix[length - i - 1][length - j - 1] = matrix[j][length - i - 1]; +// matrix[j][length - i - 1] = tmp; +// } +// +// i = 1; +// for (int j = i; j < length - 1 - i; j++) { +// int tmp = matrix[i][j]; +// matrix[i][j] = matrix[length - j - 1][i]; +// matrix[length - j - 1][i] = matrix[length - i - 1][length - j - 1]; +// matrix[length - i - 1][length - j - 1] = matrix[j][length - i - 1]; +// matrix[j][length - i - 1] = tmp; +// } + + + + + + + + for (int k = 0; k < length; k++) { + for (int l = 0; l < length; l++) { + System.out.print(matrix[k][l] + " "); + } + System.out.println(); + } + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode491.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode491.java new file mode 100644 index 0000000..51f3ac1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode491.java @@ -0,0 +1,59 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/18 16:41 + * @注释 + */ +public class LeetCode491 { + + @Test + public void test() { + new Solution().findSubsequences(new int[]{4,6,7,5,7}).forEach(list -> { + System.out.println(list); + }); + } + + class Solution { + + List> res = new ArrayList<>(); + List path = new ArrayList<>(); + public List> findSubsequences(int[] nums) { + + backTracking(nums, 0); + return res; + } + + public void backTracking(int[] nums, int index) { + + if (path.size() > 1) { + // 插入res + res.add(new ArrayList<>(path)); + } + + Set set = new HashSet<>(); + for (int i = index; i < nums.length; i++) { + // 如果不满足非递减,即递增,这个子树不保留 + if ((!path.isEmpty() && path.get(path.size() - 1) > nums[i]) // 递增 + || set.contains(nums[i]) // 如[4,7,xx,7],[4,7]已经出现在path中,7加入了set,那么在本层后面遇到7的时候,就直接continues + ) { + continue; + } + set.add(nums[i]); + path.add(nums[i]); + backTracking(nums, i + 1); + path.remove(path.size() - 1); + } + + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode494.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode494.java new file mode 100644 index 0000000..32c4260 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode494.java @@ -0,0 +1,232 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/18 16:17 + * @注释 + */ +public class LeetCode494 { + + @Test + public void test() + { + int[] nums = {1,1,1,1,1}; + int target = 3; + System.out.println(new Solution2().findTargetSumWays(nums, target)); + } + + class Solution { + /** + * 背包容量为3 + * left(+1的数量)-right(-1的数量) = target + * left-right = target + * left+right = sum (right = sum -left) + * left = (target + sum)/2 + * 表示正数有多少个是固定的,就是我们的背包容量 + * + * + * 使用nums[i] 里面全是1 装满容量为left的背包,有几种方法 + * + * if j> nums[i] + * dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]] + * 不放 放 + * else + * dp[i][j] = dp[i-1][j] + * 1,1,1,1,1 + * + * 0 1 2 3 4 + * 0 1 1 0 0 0 + * 1 0 0 1 0 0 + * 2 0 3 + * 3 + * 4 + * + * @param nums + * @param target + * @return + */ + public int findTargetSumWays(int[] nums, int target) { + + int sum = 0; + for (int num : nums) { + sum += num; + } + + // 总和还比不过绝对值,1不够用 + if(sum < Math.abs(target)){ + return 0; + } + + // left 为+1的数量 +1的数量必须是整数 + if((sum + target) % 2 != 0) { + return 0; + } + + int left = (sum + target) >> 1; // (sum + target) / 2; + + + int length = nums.length; + int[][] dp = new int[length + 1][left + 1]; + + + // 01背包 + // i(1 ~ len)表示遍历(不一定选)了 i 个元素,j(0 ~ sum) 表示它们的和 + dp[0][0] = 1; + for (int i = 1; i <= length; i++) { + for (int j = 0; j <= left; j++) { + // 装不下(不选当前元素) + if (j - nums[i - 1] < 0) { + dp[i][j] = dp[i - 1][j]; + // 可装可不装(当前元素可选可不选) + } else { + dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]]; + } + } + } + + /** + * 初始化:0个元素,和为0,情况有1种(因为没有元素,所以只能不选,和为0):dp[0][0] = 1 + * 不选当前元素,即"部分和"(即j)与之前相同:dp[i][j] = dp[i - 1][j] + * 可选可不选,不选的情况是2,选当前元素的话则之前的状态应为dp[i - 1][j - num](这里的num指的是当前元素的值,即代码中的nums[i - 1]),二者相加,即:dp[i][j] = dp[i - 1][j] + dp[i - 1][j - num] + */ + + return dp[length][left]; + + } + } + + class Solution1 { + + public int findTargetSumWays(int[] nums, int S) { + int sum = 0; + for (int num : nums) { + sum += num; + } + // 背包容量为整数,sum + S为奇数的话不满足要求 + if (((sum + S) & 1) == 1) { + return 0; + } + // 目标和不可能大于总和 + if (S > sum) { + return 0; + } + sum = (sum + S) >> 1; + int len = nums.length; + int[][] dp = new int[len + 1][sum + 1]; + dp[0][0] = 1; + + // 如果迭代部分 j 的初值赋 1 的话,就要先初始化 j = 0 的情况 + /* int count = 1; + for (int i = 1; i <= len; i++) { + // ±0 均可 + if (nums[i - 1] == 0) { + count *= 2; + } + dp[i][0] = count; + } */ + + // 01背包 + // i(1 ~ len)表示遍历(不一定选)了 i 个元素,j(0 ~ sum) 表示它们的和 + for (int i = 1; i <= len; i++) { + for (int j = 0; j <= sum; j++) { + // 装不下(不选当前元素) + if (j - nums[i - 1] < 0) { + dp[i][j] = dp[i - 1][j]; + // 可装可不装(当前元素可选可不选) + } else { + dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]]; + } + } + } + + return dp[len][sum]; + } + + } + + class Solution2 { + public int findTargetSumWays(int[] nums, int S) { + int sum = 0; + for(int i=0; isum) return 0; + S += sum; + int[] dp = new int[S+1]; + dp[0] = 1; + for(int num: nums){ + for(int i=S; i>=0; i--){ + if(i-num>=0){ + dp[i] = dp[i] + dp[i-num]; + } + } + } + return dp[S]; + } + } + + class Solution3 { + /** + * 查找目标和的方法数 + * 给定一个整数数组 nums 和一个目标整数 target,求出可以通过从数组中选择数字并进行加法运算得到目标和的方法数。 + * 数组中的每个数字可以被选择任意次数。 + * + * 其中 dp[i][j] 表示在数组 nnums 的前 i 个数中选取元素,使得这些元素之和等于 j 的方案数 + * + * + * @param nums 整数数组,包含要进行加法运算的整数 + * @param target 目标整数,要达到的和 + * @return 返回可以通过选择数组中的数字并进行加法运算得到目标和的方法数 + */ + public int findTargetSumWays(int[] nums, int target) { + // 计算数组 nums 中所有数字的和 + int sum = 0; + for (int num : nums) { + sum += num; + } + // 计算达到目标和需要减去的数 + int diff = sum - target; + // 如果差值小于0或者差值为奇数,则无法达到目标和,返回0 + if (diff < 0 || diff % 2 != 0) { + return 0; + } + // 计算可以取的负数的个数 + int n = nums.length; + int neg = diff / 2; + // 使用动态规划的二维数组,dp[i][j] 表示前 i 个数字中选取和为 j 的方法数 + int[][] dp = new int[n + 1][neg + 1]; + // 初始化,当不选取任何数字时,和为 0 的方法数为 1 + dp[0][0] = 1; + // 遍历数组 nums,更新 dp 数组 + for (int i = 1; i <= n; i++) { + int num = nums[i - 1]; + for (int j = 0; j <= neg; j++) { + // 不选择当前数字 num + dp[i][j] = dp[i - 1][j]; + // 选择当前数字 num + if (j >= num) { + dp[i][j] += dp[i - 1][j - num]; + } + } + } + // 返回最后一个数字选取和为 neg 的方法数 + return dp[n][neg]; + } + + } + + + @Test + public void test1() + { + int[] nums = {1,1,1,1,1}; + int target = 3; + System.out.println(new Solution3().findTargetSumWays(nums, target)); + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode5.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode5.java new file mode 100644 index 0000000..17e3024 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode5.java @@ -0,0 +1,102 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/22 12:16 + * @注释 + */ +public class LeetCode5 { + + @Test + public void test() + { + Solution1 solution = new Solution1(); + String s = "cbbd"; + String s1 = solution.longestPalindrome(s); + System.out.println(s1); + } + + class Solution { + /** + * 动态规划 + * dp[i][j] 表示 i-j的串是不是回文串 + * 同时记录i和j的最大差值的i和j + * + * s[i] = s[j] 时 + * dp[i][j] = + * 1. i=j true + * 2. i=j+1 true + * 3. if(dp[i+1][j-1]) true + * + * + * @param s + * @return + */ + public String longestPalindrome(String s) { + int length = s.length(); + boolean[][] dp = new boolean[length][length]; + + int maxI = 0; + int maxJ = 0; + + // dp[i+1][j-1] 决定了dp[i][j] 所以 要从下往上,从左往右遍历 + for (int i = length; i >= 0; i--) { + for (int j = i; j < length; j++) { + if (s.charAt(i) == s.charAt(j) && (i == j || i + 1 == j || dp[i + 1][j - 1])) { + if ((maxJ - maxI) <= j - i) { + maxI = i; + maxJ = j; + } + dp[i][j] = true; + } + } + } + return s.substring(maxI, maxJ+1); + } + } + + class Solution1 { + public String longestPalindrome(String s) { + char[] chars = s.toCharArray(); + // 向外扩展,统计回文长度 + int length = s.length(); + int start = 0; + int end = 0; + for (int i = 0; i < length; i++) { + + int a = getHuiWenLengthReturnLength(chars, i, i); + int b = getHuiWenLengthReturnLength(chars, i, i + 1); + + int maxLength = Math.max(a, b); + if (maxLength > end - start){ + start = i - (maxLength - 1) / 2; + end = i + maxLength / 2; + } + + + } + return s.substring(start, end + 1); + } + + public String getHuiWenLength(char[] chars, int left, int right) { + while (left >= 0 && right < chars.length && chars[left] == chars[right]) { + left--; + right++; + } + return new String(chars, left + 1, right - left - 1); + } + + public int getHuiWenLengthReturnLength(char[] chars, int left, int right) { + while (left >= 0 && right < chars.length && chars[left] == chars[right]) { + left--; + right++; + } + return right - left - 1; + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode501.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode501.java new file mode 100644 index 0000000..485344f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode501.java @@ -0,0 +1,91 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/30 11:07 + * @注释 + */ +public class LeetCode501 { + class Solution { + List res = new ArrayList<>(); + int maxFrequency = 0; + public int[] findMode(TreeNode root) { + circle(root, 0); + return null; + } + public void circle(TreeNode root, int maxFrequency) { + if (root == null) { + return; + } + if (root.right != null && root.right.val == root.val) { + + } + } + } + + @Test + public void test() { + TreeNode root = TreeNode.constructTreeByArray(6,2,8,0,4,7,9,null,null,2,6); + for (int i : new Solution1().findMode(root)) { + System.out.println(i); + } + } + class Solution1 { + List res = new ArrayList<>(); + // 记录当前出现次数最多的 + int max = 0; + TreeNode pre = null; + int sum = 0; + + public int[] findMode(TreeNode root) { + circle(root); + int size = res.size(); + int[] r = new int[size]; + for (int i = 0; i < size; i++) { + r[i] = res.get(i); + } + return r; + } + + public void circle(TreeNode root) { + + if (root == null) { + return; + } + circle(root.left); + + int rootValue = root.val; + // 如果当前节点是root,那么pre就是左节点 + // 如果当前节点是right,那么pre就是root + if (pre == null || rootValue != pre.val) { + sum = 1; + }else { + sum++; + } + + // 如果出现次数比当前已经有的最大值都多,那么重新统计 + if (sum > max) { + max = sum; + res.clear(); + res.add(rootValue); + } else if (sum == max) { + res.add(rootValue); + } + // 记录上一个节点 + pre = root; + + + circle(root.right); + + + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode509.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode509.java new file mode 100644 index 0000000..47ef87b --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode509.java @@ -0,0 +1,48 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/8 11:44 + * @注释 + */ +public class LeetCode509 { + + @Test + public void test() { + System.out.println(new Solution1().fib(10)); + } + + class Solution { + public int fib(int n) { + if (n==0) return 0; + if (n==1) return 1; + return fib(n - 1) + fib(n - 2); + } + } + + + class Solution1 { + /** + * 1. 确定dp数组(dp table)以及下标的含义 + * 2. 确定递推公式 dp[i] = dp[i - 1] + dp[i - 2]; + * 3. dp数组如何初始化 dp[0] = 0; dp[1] = 1; + * 4. 确定遍历顺序 + * 5. 举例推导dp数组 0 1 1 2 3 5 8 13 21 34 55 + * @param n + * @return + */ + public int fib(int n) { + if (n<=1) return n; + int[] dp = new int[n + 1]; + dp[0] = 0; + dp[1] = 1; + for (int i = 2; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode51.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode51.java new file mode 100644 index 0000000..4347219 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode51.java @@ -0,0 +1,113 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/20 12:03 + * @注释 + */ +public class LeetCode51 { + + @Test + public void test() { + new Solution().solveNQueens(4).forEach( + list -> { + for (String s : list) { + System.out.println(s); + } + + } + ); + } + + + class Solution { + List> res = new ArrayList<>(); + + // 地图 + char[][] chessMap = null; + + /** + * 1. 形成棋盘 + * 2. 选择点进行填充 + * 填充后,判断该点上列、斜45、45度角是否有被使用过 + * - 如果有,回溯到上次递归 + * - 没有,标记该点Q,去下一行row+1进行填充 + * @param n + * @return + */ + public List> solveNQueens(int n) { + chessMap = new char[n][n]; + for (char[] c : chessMap) { + Arrays.fill(c, '.'); + } + backTracking(n, 0); + + return res; + } + + public void backTracking(int n, int row) { + if (row == n) { + List element = new ArrayList<>(); + for (char[] chars : chessMap) { + StringBuilder s = new StringBuilder(); + for (char aChar : chars) { + s.append(aChar); + } + element.add(s.toString()); + } + res.add(element); + return; + } + + for (int col = 0; col < n; col++) { + if (isValid(n, col, row)) { + + chessMap[row][col] = 'Q'; + backTracking(n, row + 1); + // 回溯 + chessMap[row][col] = '.'; + } + } + + } + + /** + * 判断是否有效 + * + * @param n n皇后 + * @param col 列 + * @param row 行 + * @return + */ + public boolean isValid(int n, int col, int row) { + // 判断某列是否有被使用过的,其实只要该点往上搜索就可以,下面的必定为. + for (int i = 0; i < row; i++) { + if (chessMap[i][col] == 'Q') { + return false; + } + } + // 判断45度 该点左上搜索 + for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { + // 只要让某个点,不断往斜45度向左上检查就可以 + if (chessMap[i][j] == 'Q') { + return false; + } + } + // 判断斜45、135度 该点右边上搜索 + for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) { + // 只要让某个点,不断往斜45度向左上检查就可以 + if (chessMap[i][j] == 'Q') { + return false; + } + } + return true; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode513.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode513.java new file mode 100644 index 0000000..87307d5 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode513.java @@ -0,0 +1,89 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/24 19:35 + * @注释 + */ +public class LeetCode513 { + @Test + public void test() { + ExecutorService executor = Executors.newFixedThreadPool(5); + executor.submit(new Callable() { + @Override + public Object call() throws Exception { + return null; + } + + }); + + + TreeNode root = TreeNode.constructTree(new Integer[]{1}); + root.printTree(); + System.out.println(new Solution1().findBottomLeftValue(root)); + } + + class Solution { + public int findBottomLeftValue(TreeNode root) { + if (root == null) { + return 0; + } + + ArrayList> e = new ArrayList<>(); + Deque deque = new java.util.LinkedList<>(); + deque.add(root); + int res = 0; + while (!deque.isEmpty()) { + int size = deque.size(); + while (size-- > 0) { + TreeNode pop = deque.pop(); + if (pop.right!=null) deque.add(pop.right); + if (pop.left!=null) deque.add(pop.left); + if (deque.isEmpty()) { + res = pop.val; + } + } + } + return res; + + } + } + + class Solution1 { + Integer depth = 0; + Integer res = 0; + public int findBottomLeftValue(TreeNode root) { + // 只有一个节点 + if (root.left==null&&root.right==null) return root.val; + level(root, 0); + return res; + } + + public void level(TreeNode root, int level) { + if (root == null) { + return; + } + if (root.right == null && root.left == null) { + if (level > depth) { + depth = level; + res = root.val; + } + // 遇到每层层第一个叶子节点,就可能是叶子节点,如果层数更深,那么就替换 + return; + } + level(root.left, level + 1); + level(root.right, level + 1); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode515.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode515.java new file mode 100644 index 0000000..bda7fa6 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode515.java @@ -0,0 +1,56 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.Node; +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Consumer; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/18 10:45 + * @注释 + */ +public class LeetCode515 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{3, 1, 5, 0, 2, 4, 6, null, null, null, 3}); + treeNode.printTree(); + List integers = new Solution().largestValues(treeNode); + System.out.println(integers); + } + + class Solution { + public List largestValues(TreeNode root) { + + List res = new ArrayList(); + + if (root == null) { + return res; + } + + Deque queue = new LinkedList<>(); + + queue.add(root); + while (!queue.isEmpty()) { + int size = queue.size(); + int max = Integer.MIN_VALUE; + + for (int i = 0; i < size; i++) { + TreeNode pop = queue.pop(); + max = Math.max(pop.val, max); + if (pop.left != null) queue.add(pop.left); + if (pop.right != null) queue.add(pop.right); + } + res.add(max); + } + return res; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode516.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode516.java new file mode 100644 index 0000000..72ed739 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode516.java @@ -0,0 +1,51 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/5/2 15:57 + * @注释 + */ +public class LeetCode516 { + @Test + public void test() + { + Solution solution = new Solution(); + System.out.println(solution.longestPalindromeSubseq("bbbab")); + } + + class Solution { + /** + * 子序列 + * dp[i][j] 表示 i-j的最长回文子序列长度 + * 0 1 2 3 4 + * 0 1 + * 1 2 1 + * 2 3 2 1 + * 3 3 2 1 1 不相等取上、右边的最大值 + * 4 4 3 3 1 1 相等 取dp[i+1][j-1]+2 + * + * @param s + * @return + */ + public int longestPalindromeSubseq(String s) { + int[][] dp = new int[s.length()][s.length()]; + for (int i = 0; i < s.length(); i++) { + for (int j = i; j >= 0; j--) { + if (i == j) { + dp[i][j] = 1; + continue; + } + if (s.charAt(i) == s.charAt(j)) { + dp[i][j]= dp[i - 1][j + 1] + 2; + }else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j + 1]); + } + } + } + return dp[s.length() - 1][0]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode518.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode518.java new file mode 100644 index 0000000..378414a --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode518.java @@ -0,0 +1,90 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/26 15:37 + * @注释 + */ +public class LeetCode518 { + + @Test + public void test() { + int[] coins = {1, 2, 5}; + int amount = 5; + int i = new Solution2().change(amount, coins); + System.out.println(i); + } + + class Solution { + /** + * dp[j] 表示前i个硬币容量为j的背包能够装入的组合数 + * + * dp[j] = dp[j-coins[i-1]] + 1 + * + * @param amount + * @param coins + * @return + */ + public int change(int amount, int[] coins) { + + + int[] dp = new int[amount + 1]; + + dp[0] = 1; + for (int i = 1; i <= coins.length; i++) { + for (int j = coins[i - 1]; j <= amount; j++) { + dp[j] = dp[j] + dp[j - coins[i - 1]] ; + } + } + + return dp[amount]; + + } + } + + class Solution2{ + + /** + * 二维数组 + * @param amount + * @param coins + * @return + */ + public int change(int amount, int[] coins) { + int n = coins.length; + int[][] dp = new int[n + 1][amount + 1]; + + // 初始化第一行,即不使用任何硬币时,只有金额为0的方法数为1 + for (int j = 0; j <= amount; j++) { + dp[0][j] = 0; + } + dp[0][0] = 1; + + // 初始化第一列,即凑齐金额为0的方法数都是1(不使用任何硬币) + for (int i = 0; i <= n; i++) { + dp[i][0] = 1; + } + + // 动态规划填表 + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= amount; j++) { + // 不使用第i种硬币 + dp[i][j] = dp[i - 1][j]; + + // 如果当前金额j大于等于第i种硬币的面值,那么可以考虑使用这种硬币 + // 使用第i种硬币的方法数等于不使用第i种硬币的方法数加上使用第i种硬币后的方法数 + if (j >= coins[i - 1]) { + dp[i][j] += dp[i][j - coins[i - 1]]; + } + } + } + + return dp[n][amount]; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode53.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode53.java new file mode 100644 index 0000000..70d280a --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode53.java @@ -0,0 +1,47 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/25 11:59 + * @注释 + */ +public class LeetCode53 { + + @Test + public void test() { + Solution solution = new Solution(); + int[] nums = new int[]{-1,-3}; + int i = solution.maxSubArray(nums); + System.out.println(i); + } + + class Solution { + + /** + * + * @param nums + * @return + */ + public int maxSubArray(int[] nums) { + // dp[i] 表示包含元素i的的最大和 + // dp[0] = nums[0] + + int[] dp = new int[nums.length]; + dp[0] = nums[0]; + int max = nums[0]; + for (int i = 1; i < nums.length; i++) { + if (dp[i - 1] > 0 && dp[i - 1] + nums[i] > 0) { // 如果p[i - 1] < 0 则只能拖后腿 + dp[i] = dp[i - 1] + nums[i]; + } else { + // 拖后腿,重新计算 + dp[i] = nums[i]; + } + max = Math.max(max, dp[i]); + } + return max; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode530.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode530.java new file mode 100644 index 0000000..1fb2f7e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode530.java @@ -0,0 +1,112 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/28 18:44 + * @注释 + */ +public class LeetCode530 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(236,104,701,null,227,null,911); + System.out.println(new Solution2().getMinimumDifference(treeNode)); + } + + class Solution { + + int res = Integer.MAX_VALUE; + public int getMinimumDifference(TreeNode root) { + difference(root); + return res; + } + + public void difference(TreeNode root) { + //二叉树搜索树,差值为相邻节点 + if (root == null) { + return; + } + int right = Integer.MAX_VALUE; + if (root.right != null) { + right = Math.abs(root.val - root.right.val); + } + int left = Integer.MAX_VALUE; + if (root.left != null) { + left = Math.abs(root.val - root.left.val); + } + + if (right < left && right < res) { + res = right; + } else if (left <= right && left < res) { + res = left; + } + difference(root.right); + difference(root.left); + } + } + + class Solution1 { + + int res = Integer.MAX_VALUE; + int storage = Integer.MAX_VALUE; + public int getMinimumDifference(TreeNode root) { + difference(root); + return res; + } + + public void difference(TreeNode root) { + if (root == null) { + return; + } + difference(root.left); + int i = Math.abs(storage - root.val); + if (i < res) { + res = i; + } + // 记录当前这个值,进入下次递归使用 + storage = root.val; + difference(root.right); + } + } + + + + class Solution2 { + + + public int getMinimumDifference(TreeNode root) { + + Deque deque = new LinkedList<>(); + deque.push(root); + int res = Integer.MAX_VALUE; + TreeNode before = null; + while (!deque.isEmpty()) { + TreeNode pop = deque.pop(); + if (pop != null) { + if (pop.right != null) deque.push(pop.right); + deque.push(pop); + deque.push(null); + if (pop.left != null) deque.push(pop.left); + } else { + TreeNode s = deque.pop(); + if (before != null) { + res = Math.min(res, s.val - before.val); + } + before = s; + System.out.println(s.val); + } + } + return res; + + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode538.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode538.java new file mode 100644 index 0000000..399908f --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode538.java @@ -0,0 +1,65 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/31 19:15 + * @注释 + */ +public class LeetCode538 { + + @Test + public void test() { + + new Solution1().convertBST(TreeNode.constructTreeByArray(4, 1, 6, 0, 2, 5, 7, null, null, null, 3, null, null, null, 8)).printTree(); + } + + class Solution { + int sum = 0; + public TreeNode convertBST(TreeNode root) { + if (root == null) { + return null; + } + root.right = convertBST(root.right); + root.val += sum; + sum = root.val; + root.left = convertBST(root.left); + return root; + } + } + + + class Solution1 { + public TreeNode convertBST(TreeNode root) { + + if (root == null) { + return null; + } + + Deque stack = new java.util.LinkedList<>(); + stack.push(root); + + + int sum = 0; + while (!stack.isEmpty()) { + TreeNode pop = stack.pop(); + if (pop == null) { + TreeNode ans = stack.pop(); + ans.val += sum; + sum = ans.val; + } else { + if (pop.left!=null) stack.push(pop.left); + stack.push(pop); + stack.push(null); + if (pop.right!=null) stack.push(pop.right); + } + } + return root; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode53_2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode53_2.java new file mode 100644 index 0000000..95ef6d8 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode53_2.java @@ -0,0 +1,79 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/25 10:53 + * @注释 + */ +public class LeetCode53_2 { + @Test + public void test() { + System.out.println(new Solution1().maxSubArray(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4})); + System.out.println(new Solution1().maxSubArray(new int[]{5,4,-1,7,8})); + + } + + class Solution { + /** + * 遇到加上变为负数,重新从0计算。 + * 因为前面那一串会拖累后面那串 + * @param nums + * @return + */ + public int maxSubArray(int[] nums) { + int maxSum = Integer.MIN_VALUE; + int sum = 0; + for (int i = 0; i < nums.length; i++) { + // 加上某个数后是否会变为负数,会则直接从0开始计算,因为其只会拖累后面的串 + sum += nums[i]; + maxSum = Math.max(sum, maxSum); + if (sum < 0) { + sum = 0; + } + } + + + return maxSum; + } + } + + + class Solution1 { + + /** + * 动态规化 + * dp[i] 表示i出最大子序列的和 + * if dp[i-1]+nums[i]>0 dp[i] = dp[i-1] + nums[i] + * else dp[i] = nums[i] + * + * [-2,1,-3,4,-1,2,1,-5,4] + * [-2,1,-3,4,3,5,6,1,5] + * + * @param nums + * @return + */ + public int maxSubArray(int[] nums) { + int[] dp = new int[nums.length]; + dp[0] = nums[0]; + int max = dp[0]; + for (int i = 1; i < nums.length; i++) { + dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]); + max = Math.max(dp[i], max); +// if (dp[i - 1] > 0 && dp[i - 1] + nums[i] > 0) { +// dp[i] = dp[i - 1] + nums[i]; +// } else { +// dp[i] = nums[i]; +// } +// max = Math.max(dp[i], max); + } + return max; + + } + } + + +} + diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode54.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode54.java new file mode 100644 index 0000000..c33c17d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode54.java @@ -0,0 +1,154 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 + */ +public class LeetCode54 { + + public List spiralOrder(int[][] matrix) { + int width = matrix[0].length; + int height = matrix.length; + List s = new ArrayList<>(width * height); + + if (width == 1) { + + } else if (height == 1) { + + } + + int loop = Math.min(width, height) / 2; + int start = 0; + int i = 0, j = 0; + while (start < loop) { + + for (i = start; i < width - start - 1; i++) { + s.add(matrix[start][i]); + } + + for (j = start; j < height - start - 1; j++) { + s.add(matrix[j][i]); + } + + for (; i >= start + 1; i--) { + s.add(matrix[j][i]); + } + + for (; j >= start + 1; j--) { + s.add(matrix[j][i]); + } + start++; + } + + if (width > height) { + if (height == 1) { + // 横向填充 + for (; i < width - start; i++) { + s.add(matrix[start][i]); + } + }else if (height % 2 == 1) { + // 横向填充 + for (; i < width - start-1; i++) { + s.add(matrix[start][i + 1]); + } + } + + } else { + // 纵向填充 + if (width == 1) { + for (; j < height - start; j++) { + s.add(matrix[j][i]); + } + } else if (width % 2 == 1 ) { + for (; j < height - start - 1; j++) { + s.add(matrix[j+1][i + 1]); + } + } + } + + return s; + + } + + + /** + * 时间复杂度:O(mn)O(mn)O(mn),其中 mmm 和 nnn 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。 + * + * 空间复杂度:O(1)O(1)O(1)。除了输出数组以外,空间复杂度是常数。 + * + * @param matrix + * @return + */ + + public List spiralOrder1(int[][] matrix) { + int width = matrix[0].length; + int height = matrix.length; + List s = new ArrayList<>(width * height); + + if (height == 1) { + int[] line = matrix[0]; + for (int i : line) { + s.add(i); + } + return s; + } else if (width == 1) { + for (int[] ints : matrix) { + s.add(ints[0]); + } + return s; + } + + int loop = Math.min(width, height) / 2; + int start = 0; + int i = 0, j = 0; + while (start < loop) { + + for (i = start; i < width - start - 1; i++) { + s.add(matrix[start][i]); + } + + for (j = start; j < height - start - 1; j++) { + s.add(matrix[j][i]); + } + + for (; i >= start + 1; i--) { + s.add(matrix[j][i]); + } + + for (; j >= start + 1; j--) { + s.add(matrix[j][i]); + } + start++; + } + + if (width > height) { + if (height % 2 == 1) { + // 横向填充 + for (; i < width - start-1; i++) { + s.add(matrix[start][i + 1]); + } + } + } else { + if (width % 2 == 1) { + for (; j < height - start - 1; j++) { + s.add(matrix[j+1][i + 1]); + } + } + } + + return s; + + } + @Test + public void test() { + spiralOrder1(new int[][]{ + {1,2}, + {1,3}, + {1,3} + }).forEach(System.out::println); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode541.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode541.java new file mode 100644 index 0000000..1bdb79b --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode541.java @@ -0,0 +1,42 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * 反转字符串 II + * 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。 + * 如果剩余字符少于 k 个,则将剩余字符全部反转。 + */ +public class LeetCode541 { + + @Test + public void test() { + String s = "1234567890"; + int k = 4; + System.out.println(new Solution().reverseStr(s, k)); + } + + class Solution { + public String reverseStr(String s, int k) { + char[] chars = s.toCharArray(); + for (int i = 0; i < chars.length; i = i + k * 2) { + reverse(chars, i, i + k - 1); + } + return new String(chars); + } + + public void reverse(char[] chars, int start, int end) { + // 边界判断, 如果要逆转的区间越界,就把后面这一段都逆转了,取最大值就好了 + if (end > chars.length - 1) { + end = chars.length - 1; + } + while (start < end) { + char tmp = chars[start]; + chars[start] = chars[end]; + chars[end] = tmp; + start++; + end--; + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode55.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode55.java new file mode 100644 index 0000000..5dc3f51 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode55.java @@ -0,0 +1,90 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/26 11:33 + * @注释 + */ +public class LeetCode55 { + + @Test + public void test() { + System.out.println(new Solution().canJump(new int[]{2,0,0})); + + char c = 10 + 90; + System.out.println(c); + long g = 9999999999L; + System.out.println(g); + + } + + public static void main(String[] args) { + System.out.println(i()); + + } + + public static int i() { + try { + + return 1; + } catch (Exception e) { + + } finally { + return 0; + } + } + + + + + + class CustomClassLoader extends ClassLoader { + public CustomClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] res = getClassFromCustomClass(name); + if (res != null) { + return defineClass(name, res, 0, res.length); + } else { + throw new ClassNotFoundException(name); + } + } + + private byte[] getClassFromCustomClass(String name) { + //自定义路径加载指定类 + // 加密解密 + return null; + } + } + + class Solution { + /** + * 每个index都有一个cover覆盖范围,一旦这个范围可以覆盖nums,就能够返回 + * @param nums + * @return + */ + public boolean canJump(int[] nums) { + if (nums.length == 1) { + return true; + } + + // cover表示最远能到哪里 + int cover = 0; + // 注意这里cover表示能够覆盖的最远范围,不能超过他 + for (int i = 0; i <= cover; i++) { + cover = Math.max(i + nums[i], cover); + if (cover >= nums.length - 1) { + return true; + } + } + return false; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode559.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode559.java new file mode 100644 index 0000000..05a517c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode559.java @@ -0,0 +1,79 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.Node; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/21 20:20 + * @注释 + */ +public class LeetCode559 { + + @Test + public void test() { + Node node = new Node(1); + node.children = new LinkedList<>(); + node.children.add(new Node(2)); + node.children.add(new Node(3)); + node.children.add(new Node(4)); + node.children.get(2).children = new ArrayList<>(); + node.children.get(2).children.add(new Node(6)); + node.children.get(2).children.add(new Node(7)); + + System.out.println(new Solution1().maxDepth(node)); + } + + class Solution { + public int maxDepth(Node root) { + return getDepth(root); + } + + public int getDepth(Node root) { + if (root == null) { + return 0; + } + int max = 1; + + List children = root.children; + if (children != null) { + for (Node child : children) { + max = Math.max(getDepth(child) + 1, max); + } + } + return max; + } + } + + class Solution1 { + int max = 0; + public int maxDepth(Node root) { + if (root == null) { + return 0; + } + getDepth(root, 1); + return max; + } + + public void getDepth(Node root,int level) { + if (root == null) { + return; + } + if (level > max) { + max = level; + } + List children = root.children; + if (children != null) { + for (Node child : children) { + getDepth(child, level + 1); + } + } + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode56.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode56.java new file mode 100644 index 0000000..e9f9d74 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode56.java @@ -0,0 +1,60 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/5 12:09 + * @注释 + */ +public class LeetCode56 { + + @Test + public void test() { + int[][] intervals = new int[][]{{1, 3}, {5, 6}}; + for (int[] ints : new Solution().merge(intervals)) { + System.out.println(Arrays.toString(ints)); + } + } + + class Solution { + public int[][] merge(int[][] intervals) { + + Arrays.sort(intervals, new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o1[0] - o2[0]; + } + }); + + + List res = new ArrayList<>(); + for (int i = 1; i < intervals.length; i++) { + if (intervals[i - 1][1] < intervals[i][0]) { + res.add(intervals[i - 1]); + } else { + intervals[i][0] = intervals[i - 1][0]; // 已经排序过了,所以前一个的pre一定比这个的pre大 + intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]); + } + } + res.add(intervals[intervals.length - 1]); + +// int[][] result = new int[res.size()][2]; +// for (int i = 0; i < res.size(); i++) { +// result[i] = res.get(i); +// } +// return result; + + return res.toArray(new int[res.size()][2]); + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode567.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode567.java new file mode 100644 index 0000000..25f0d19 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode567.java @@ -0,0 +1,129 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/21 14:13 + * @注释 + */ +public class LeetCode567 { + + /** + * 超时 + */ + @Test + public void test() { + String s1 = "adc"; + String s2 = "dcda"; + boolean result = new Solution().checkInclusion(s1, s2); + System.out.println(result); + } + + class Solution { + + + /** + * @param s1 + * @param s2 + * @return + */ + public boolean checkInclusion(String s1, String s2) { + // 获取s1的全部排列,再到s2中找有没有对于的子串 + List stringSub = getStringSub(s1); + for (String s : stringSub) { + int len = s1.length(); + for (int i = 0; i <= s2.length() - len; i++) { + if (s2.substring(i, i + len).equals(s)) { + return true; + } + } + } + return false; + } + + public List getStringSub(String s1) { + ArrayList res = new ArrayList<>(); + backTracking(res, s1); + return res; + } + + StringBuilder path = new StringBuilder(); + Set set = new HashSet<>(); + public void backTracking(List res, String s) { + if (path.length() >= s.length()) { + res.add(path.toString()); + return; + } + for (int i = 0; i < s.length(); i++) { + if (set.contains(i)) { + continue; + } + set.add(i); + path.append(s.charAt(i)); + backTracking(res, s); + path.deleteCharAt(path.length() - 1); + set.remove(i); + } + } + } + + @Test + public void test1() { + String s1 = "ab"; + String s2 = "eidboaooo"; + boolean result = new Solution1().checkInclusion(s1, s2); + System.out.println(result); + } + + class Solution1 { + /** + * 需要同时考虑 s1的map和s2的map匹配,同时还有已经完全匹配的个数; + * @param s1 + * @param s2 + * @return + */ + public boolean checkInclusion(String s1, String s2) { + Map need = new HashMap<>(); + for (int i = 0; i < s1.length(); i++) { + need.put(s1.charAt(i), need.getOrDefault(s1.charAt(i), 0) + 1); + } + int left = 0; + int right = 0; + Map window = new HashMap<>(); + + int validCount = 0; // 记录有效个数(某个字符对应的数量和need一致),如果==need.size直接返回 + char[] s2CharArray = s2.toCharArray(); + while (right < s2.length()) { + // 右边指针不断探,加入window统计出现个数 + char c = s2CharArray[right]; + right++; + if (need.containsKey(c)) { + window.put(c, window.getOrDefault(c, 0) + 1); + if (window.get(c).equals(need.get(c))) { + validCount++; + if (validCount == need.size()) { + return true; + } + } + } + // 左边指针收缩 关键在于找到进入while left 的循环条件 + while (right - left >= s1.length()) { + char cha = s2CharArray[left]; + left++; + if (need.containsKey(cha)) { + if (window.get(cha).equals(need.get(cha))) { + validCount--; + } + window.put(cha, window.get(cha) - 1); + } + } + + } + return false; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode57.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode57.java new file mode 100644 index 0000000..6134c9d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode57.java @@ -0,0 +1,80 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/18 23:37 + * @注释 + */ +public class LeetCode57 { + + @Test + public void test() { + Solution solution = new Solution(); + int[][] insert = solution.insert(new int[][]{{1, 3}, {6, 9}}, new int[]{2, 5}); + for (int[] ints : insert) { + System.out.println(Arrays.toString(ints)); + } + // [[1,2],[3,5],[6,7],[8,10],[12,16]] + int[][] insert1 = solution.insert(new int[][]{{1, 2}, {3, 5}, {6, 7}, {8, 10}, {12, 16}}, new int[]{4, 8}); + for (int[] ints : insert1) { + System.out.println(Arrays.toString(ints)); + } + } + + class Solution { + /** + * | | | | + | | + * + * | | | | + * | | + * + * | | | | + * | | + * + * | | | | + * | | + * + * + * | | + * | | + * | | + * | | + * | | + * | | + * @param intervals + * @param newInterval + * @return + */ + public int[][] insert(int[][] intervals, int[] newInterval) { + + List list = new ArrayList<>(Arrays.asList(intervals)); + list.add(newInterval); + list.sort(new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o1[0] - o2[0]; + } + }); + + for (int i = 1; i < list.size(); i++) { + int[] now = list.get(i); + int[] before = list.get(i - 1); + if (now[0] <= before[1]) { + before[1] = Math.max(before[1], now[1]); + list.remove(i); + i--; + } + } + return list.toArray(new int[list.size()][2]); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode58.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode58.java new file mode 100644 index 0000000..76c8fc6 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode58.java @@ -0,0 +1,42 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/18 22:04 + * @注释 + */ +public class LeetCode58 { + @Test + public void test() { + Solution1 solution = new Solution1(); + int i = solution.lengthOfLastWord(" fly me to the moon "); + System.out.println(i); + } + + class Solution { + public int lengthOfLastWord(String s) { + String trim = s.trim(); + String[] split = trim.split(" "); + return split[split.length - 1].length(); + } + } + + class Solution1 { + public int lengthOfLastWord(String s) { + s = s.trim(); + int len = 0; + for (int i = s.length() - 1; i >= 0; i--) { + if (s.charAt(i) != ' ') { + len++; + }else { + break; + } + } + return len; + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode583.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode583.java new file mode 100644 index 0000000..705f096 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode583.java @@ -0,0 +1,102 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/5/2 11:14 + * @注释 + */ +public class LeetCode583 { + @Test + public void test() + { + + // "leetcode", word2 = "etco" + int i = new Solution1().minDistance("leetcode", "etco"); + System.out.println(i); + } + + class Solution { + /** + * 最长子序列的长度 + * word1.len - dp + * word2.len - dp + * @param word1 + * @param word2 + * @return + */ + public int minDistance(String word1, String word2) { + /** + * dp[i][j] 表示 word1的0-i word2的0-j 最长公共子序列的长度 + * + * '' s e a + * '' 0 0 0 0 + * e 0 0 1 1 + * a 0 0 1 2 + * t 0 0 1 2 + * + */ + + int len2 = word2.length(); + int len1 = word1.length(); + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 1; i <= len1; i++) { + for (int j = 1; j <= len2; j++) { + if (word1.charAt(i - 1) == word2.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + return len1 + len2 - (dp[len1][len2] << 1); + } + + } + + class Solution1 { + /** + * dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。 + * '' s e a + * '' 0 1 2 3 + * e 1 2 1 2 + * a 2 3 2 1 + * t 3 4 3 2 + * 等 dp[i-1][j-1] + * 不等 min(dp[i-1][j], dp[i][j-1]) + 1 + * 1. 删word1[i - 1],最少操作次数为dp[i - 1][j] + 1 + * 2. 删word2[j - 1],最少操作次数为dp[i][j - 1] + 1 + * 3. 同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2 + * dp[i][j - 1] + 1 = dp[i - 1][j - 1] + 2 + * @param word1 + * @param word2 + * @return + */ + public int minDistance(String word1, String word2) { + int len2 = word2.length(); + int len1 = word1.length(); + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 1; i <= len1; i++) { + dp[i][0] = i; + } + for (int j = 1; j <= len2; j++) { + dp[0][j] = j; + } + + for (int i = 1; i <= len1; i++) { + for (int j = 1; j <= len2; j++) { + if (word1.charAt(i - 1) == word2.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1; + } + } + } + return dp[len1][len2]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode59.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode59.java new file mode 100644 index 0000000..510441b --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode59.java @@ -0,0 +1,74 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 + * + * + * + * 示例 1: + * + * + * 输入:n = 3 + * 输出:[[1,2,3],[8,9,4],[7,6,5]] + * 示例 2: + * + * 输入:n = 1 + * 输出:[[1]] + * + * + * 提示: + * + * 1 <= n <= 20 + */ +public class LeetCode59 { + + public int[][] generateMatrix(int n) { + int cycle = 0; // 循环次数 + int start = 0; // 本次循环的开始 + int[][] ints = new int[n][n]; + int fillNumber = 1; + int i, j; + while (cycle++ < n / 2) { + // 每个边填充数字 + int path = n - cycle; + for (i = start; i < path; i++) { + ints[start][i]=fillNumber++; + } + for (j = start; j < path; j++) { + ints[j][i] = fillNumber++; + } + for (; i >= n - path; i--) { + ints[j][i] = fillNumber++; + } + for (; j >= n - path; j--) { + ints[j][i]=fillNumber++; + } + start++; + } + if (n % 2 == 1) { + ints[start][start] = fillNumber++; + } + return ints; + } + + @Test + public void test() { + int[][] ints = generateMatrix(11); + for (int[] anInt : ints) { + for (int i : anInt) { + System.out.print(i+" "); + } + System.out.println(); + } + + /* [[1,2,3,4,5,6,7], + [24,25,26,27,28,29,8], + [23,40,41,42,43,30,9], + [22,39,48,49,44,31,10], + [21,38,47,46,45,32,11], + [20,37,36,35,34,33,12], + [19,18,17,16,15,14,13]]*/ + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode6.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode6.java new file mode 100644 index 0000000..951fbf8 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode6.java @@ -0,0 +1,101 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/18 22:25 + * @注释 + */ +public class LeetCode6 { + + @Test + public void test() { + Solution solution = new Solution(); + String s = solution.convert("AB", 1); + System.out.println(s); + } + + class Solution { + /** + * 4 + * + * 1234321234321 + * @param s + * @param numRows + * @return + */ + public String convert(String s, int numRows) { + if (numRows == 1) { + return s; + } + + List lines = new ArrayList<>(); + for (int i = 0; i < numRows; i++) { + lines.add(new StringBuilder()); + } + + + int i = 0, flag = -1; + for(char c : s.toCharArray()) { + lines.get(i).append(c); + if(i == 0 || i == numRows -1) flag = - flag; + i += flag; + } + + StringBuilder res = new StringBuilder(); + for (StringBuilder row : lines) { + res.append(row); + } + + return res.toString(); + + + + } + } + + class Solution1 { + /** + * 4 + * + * 1234321234321 + * @param s + * @param numRows + * @return + */ + public String convert(String s, int numRows) { + if (numRows == 1) { + return s; + } + int[] nums = new int[s.length()]; + boolean up = true; + int index = 1; + for (int i = 0; i < nums.length; i++) { + if (index == numRows|| index == 1) { + up = !up; + } + nums[i] = index; + + if (up) { + index--; + }else { + index++; + } + } + StringBuilder sb = new StringBuilder(); + for (int i = 1; i <= numRows; i++) { + for (int j = 0; j < nums.length; j++) { + if (nums[j] == i) { + sb.append(s.charAt(j)); + } + } + } + return sb.toString(); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode61.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode61.java new file mode 100644 index 0000000..17f4114 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode61.java @@ -0,0 +1,107 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/23 14:25 + * @注释 + */ +public class LeetCode61 { + @Test + public void test() { + ListNode head = ListNode.listNodeFromArray(new int[]{1,2,3}); + new Solution().rotateRight(head, 3).printList(); + } + class Solution { + public ListNode rotateRight(ListNode head, int k) { + if (head == null) { + return null; + } + int len = 0; + ListNode tmpHead = head; + while (tmpHead!= null) { + len++; + tmpHead = tmpHead.next; + } + + k %= len; + if (k == 0) { + return head; + } + + ListNode pre = new ListNode(-1, head); + ListNode indexPre = pre; + ListNode indexAfter = pre; + for (int i = 0; i < k ; i++) { + indexAfter = indexAfter.next; + } + while (indexAfter.next != null) { + indexAfter = indexAfter.next; + indexPre = indexPre.next; + } + ListNode tmp = indexPre.next; + indexPre.next = null; + indexAfter.next = pre.next; + pre.next = tmp; + return pre.next; + } + } + + @Test + public void tes1t() { + ListNode listNode = ListNode.listNodeFromArray(new int[]{1,2,3}); + new Solution2().rotateRight(listNode, 4).printList(); + } + + + class Solution1 { +// public ListNode rotateRight(ListNode head, int k) { +// ListNode pre = new ListNode(-1, head); +// ListNode preIndex = pre; +// ListNode afterIndex = pre; +// for (int i = 0; i < k && afterIndex != null; i++) { +// afterIndex = afterIndex.next; +// } +// while (afterIndex.next != null) { +// afterIndex = afterIndex.next; +// preIndex = preIndex.next; +// } +// afterIndex.next = pre.next; +// ListNode next = preIndex.next; +// preIndex.next = null; +// return next; +// } + } + + class Solution2 { + public ListNode rotateRight(ListNode head, int k) { + if (head == null) { + return head; + } + ListNode pre = new ListNode(-1, head); + int len = 0; + ListNode index = pre; + while (index.next != null) { + len++; + index = index.next; + } + + int add = len - k % len; // |a|k| 中的a部分 + if (add == 0) { + return head; + } + + index.next = pre.next; + ListNode tmp = pre; + for (int i = 0; i < add; i++) { + tmp = tmp.next; + } + ListNode cd = tmp.next; + tmp.next = null; + return cd; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode617.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode617.java new file mode 100644 index 0000000..79ed48c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode617.java @@ -0,0 +1,109 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.Deque; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/28 15:07 + * @注释 + */ +public class LeetCode617 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(1, 3, 2, 5); + TreeNode treeNode1 = TreeNode.constructTreeByArray(2, 1, 3, null, 4, null, 7); + new Solution2().mergeTrees(treeNode, treeNode1).printTree(); + } + + class Solution { + + public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { + return merge(root1, root2); + } + + public TreeNode merge(TreeNode root1, TreeNode root2) { + if (root1 == null && root2 == null) { + return null; + } else if (root1 != null && root2 == null) { + TreeNode treeNode = new TreeNode(root1.val, root1.left, root1.right); + return treeNode; + } else if (root2 != null && root1 == null) { + TreeNode treeNode = new TreeNode(root2.val, root2.left, root2.right); + return treeNode; + } + TreeNode treeNode = new TreeNode(root1.val + root2.val); + treeNode.right = merge(root1.right, root2.right); + treeNode.left = merge(root1.left, root2.left); + return treeNode; + } + } + + class Solution1 { + + public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { + return merge(root1, root2); + } + + public TreeNode merge(TreeNode root1, TreeNode root2) { + // 其中一边为空,直接返回另一半 + if (root2 == null) { + return root1; + } + if (root1 == null) { + return root2; + } + + root1.val = root1.val + root2.val; + root1.right = merge(root1.right, root2.right); + root1.left = merge(root1.left, root2.left); + return root1; + } + } + + class Solution2 { + + public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { + + if (root1 == null) { + return root2; + } + if (root2 == null) { + return root1; + } + + Deque deque = new java.util.ArrayDeque<>(); + deque.add(root1); + deque.add(root2); + while (!deque.isEmpty()) { + TreeNode pop1 = deque.pop(); + TreeNode pop2 = deque.pop(); + + pop1.val += pop2.val; + + // 出来的两个节点,判断左右是否为空 + if (pop1.left != null && pop2.left != null) { + deque.add(pop1.left); + deque.add(pop2.left); + } + if (pop1.right != null && pop2.right != null) { + deque.add(pop1.right); + deque.add(pop2.right); + } + if (pop1.left == null && pop2.left != null) { + pop1.left = pop2.left; + } + if (pop1.right == null && pop2.right != null) { + pop1.right = pop2.right; + } + } + + return root1; + } + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode62.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode62.java new file mode 100644 index 0000000..f7ba734 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode62.java @@ -0,0 +1,45 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * TODO 还没写完 + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/8 12:58 + * @注释 + */ +public class LeetCode62 { + + @Test + public void test( + ) { + System.out.println(new Solution().uniquePaths(3, 3)); + } + + class Solution { + /** + * 确定dp[i,j] 该点可能的路径数 + * 递推公式 dp[i,j]= dp[i-1,j] + dp[i,j-1] + * 初始化 dp[0,0]=1 + * 推 + * 0 1 1 1 1 1 1 + * 1 2 3 4 5 6 7 + * 1 3 6 10 15 21 28 + * @param m + * @param n + * @return + */ + public int uniquePaths(int m, int n) { + int[][] dp = new int[m][n]; + dp[0][0] = 1; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (i>=1) dp[i][j] += dp[i - 1][j]; + if (j>=1) dp[i][j] += dp[i][j - 1]; + } + } + return dp[m - 1][n - 1]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode63.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode63.java new file mode 100644 index 0000000..3ea22b0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode63.java @@ -0,0 +1,57 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/9 12:04 + * @注释 + */ +public class LeetCode63 { + + @Test + public void test() { + int[][] ints = new int[][]{{0,0,0,0},{0,1,0,0},{0,0,0,0}}; + System.out.println(new Solution().uniquePathsWithObstacles(ints)); + } + + class Solution { + /** + * dp[i][j] 表示 i,j出可能的路径 + * dp[i][j] = dp[i-1][j] + dp[i][j-1] 且如果该点有障碍,直接continue + * 初始化 dp【0,0】=0 + * @param obstacleGrid + * @return + */ + public int uniquePathsWithObstacles(int[][] obstacleGrid) { + + if (obstacleGrid[0][0] == 1) { + return 0;//起点就有障碍,不可能过去 + } + + int h = obstacleGrid.length; + int w = obstacleGrid[0].length; + int[][] dp = new int[h][w]; + dp[0][0] = 1; + for (int i = 0; i < dp.length; i++) { + for (int j = 0; j < dp[i].length; j++) { + if (i == 0 && j == 0) { + continue; + } + + if (obstacleGrid[i][j] == 0) { + int tmp = 0; + if (i >= 1) tmp += dp[i - 1][j]; + if (j >= 1) tmp += dp[i][j - 1]; + dp[i][j] = tmp; + } + } + } + + return dp[h-1][w-1]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode637.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode637.java new file mode 100644 index 0000000..c1c5579 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode637.java @@ -0,0 +1,87 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Consumer; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/17 16:41 + * @注释 + */ +public class LeetCode637 { + + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTree(new Integer[]{1,2,3}); + System.out.println(new Solution1().averageOfLevels(treeNode)); + } + + class Solution { + + + public List averageOfLevels(TreeNode root) { + + List res = new ArrayList<>(); + Deque queue = new LinkedList<>(); + queue.add(root); + + while (!queue.isEmpty()) { + + int size = queue.size(); + double sum = 0; + for (int i = 0; i < size; i++) { + TreeNode pop = queue.pop(); + sum += pop.val; + if(pop.left!=null) queue.add(pop.left); + if(pop.right!=null) queue.add(pop.right); + } + res.add((sum / size)); + } + return res; + } + } + + + class Solution1 { + + List res = new ArrayList<>(); + List count = new ArrayList<>(); + + + public List averageOfLevels(TreeNode root) { + + level(root, 0); + for (int i = 0; i < res.size(); i++) { + res.set(i, res.get(i) / count.get(i)); + } + return res; + } + + void level(TreeNode treeNode, int level) { + + if (treeNode == null) { + return; + } + + if (res.size() <= level) { + res.add(0d); + count.add(0); + } + res.set(level, res.get(level) + treeNode.val); + count.set(level, count.get(level) + 1); + if (treeNode.left != null) { + level(treeNode.left, level + 1); + } + if (treeNode.right != null) { + level(treeNode.right, level + 1); + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode64.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode64.java new file mode 100644 index 0000000..714ecc0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode64.java @@ -0,0 +1,59 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/16 11:22 + * @注释 + */ +public class LeetCode64 { + + @Test + public void test() + { + int[][] grid = new int[][] { {1,2,3}, {4,5,6} }; + Solution solution = new Solution(); + int i = solution.minPathSum(grid); + System.out.println(i); + } + + class Solution { + /** + * dp + * int[i][j]表示到该点所需的最最小数字总和 + * + * @param grid + * @return + */ + public int minPathSum(int[][] grid) { + + int h = grid.length; + int w = grid[0].length; + int[][] dp = new int[h][w]; + dp[0][0] = grid[0][0]; + + // dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j] + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + if (i == 0 && j == 0) { + continue; + } + if (j == 0 && i != 0) { + dp[i][j] = dp[i - 1][j] + grid[i][j]; + continue; + } + if (i == 0 && j != 0) { + dp[i][j] = dp[i][j - 1] + grid[i][j]; + continue; + } + dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]; + } + } + return dp[h - 1][w - 1]; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode647.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode647.java new file mode 100644 index 0000000..003bafd --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode647.java @@ -0,0 +1,98 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/22 12:36 + * @注释 + */ +public class LeetCode647 { + + class Solution { + /** + * 判断一个子字符串(字符串的下表范围[i,j])是否回文, + * 依赖于子字符串(下表范围[i + 1, j - 1])) 是否是回文。 + * + * 布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串 + * + * ij两个循环,能够覆盖所有循环 + * - dp[i][j] 判断是否回文的时候,只需要dp[i+1][j-1]是否回文,并且s[i]==s[j] + * 当s[i]=s[j] + * 1. i=j 回文 + * 2. i+1=j 回文 + * 3. dp[i+1][j-1]==true 回文 + * + * + * + * dp[i][j]由dp[i+1][j-1]过来,所以必须从下到上,左到右 + * + * @param s + * @return + */ + public int countSubstrings(String s) { + + char[] chars = s.toCharArray(); + + boolean[][] dp = new boolean[chars.length][chars.length]; + int res = 0; + for (int i = s.length() - 1; i >= 0; i--) { + for (int j = i; j < s.length(); j++) { + if (chars[i] == chars[j]) { + if (j - i == 1|| i==j || dp[i + 1][j - 1]) { + dp[i][j] = true; + res++; + } + } + } + } + + + return res; + } + + } + + + class Solution1 { + public int countSubstrings(String s) { + // 中心点向外扩充 + // 1个元素可以作为中心点 + // 2个元素也能作为中心点 + char[] chars = s.toCharArray(); + int res = 0; + for (int i = 0; i < chars.length; i++) { + res += subString(chars, i, i); + res += subString(chars, i, i + 1); + } + return res; + } + + /** + * + * @param chars + * @param center1 向左扩展的指针 + * @param center2 向右扩展的指针 + * @return 有几个子串 + */ + public int subString(char[] chars, int center1, int center2) { + int res = 0; + while (center1 >= 0 && center2 < chars.length && chars[center1] == chars[center2]) { + center1--; + center2++; + res++; + } + return res; + } + } + + @Test + public void test() + { + Solution1 solution = new Solution1(); + String s = "aaa"; + int res = solution.countSubstrings(s); + System.out.println(res); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode647_1.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode647_1.java new file mode 100644 index 0000000..bf92c33 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode647_1.java @@ -0,0 +1,65 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/5/2 12:00 + * @注释 + */ +public class LeetCode647_1 { + @Test + public void test() + { + String s = "abc"; + System.out.println(new Solution().countSubstrings(s)); + } + + class Solution { + /** + * + * 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目 + * + * dp[i][j] 表示 i-j回文字符串的数量 + * + * dp[i][j] 由 dp[i+1][j-1]推出 + * if n[i]==n[j] + * dp[i][j] = dp[i-1][j-1]+2 + * else + * dp[i][j] = dp[i][j-1]+dp[i+1][j] + * + * abac + * '' 0 1 2 3 + * '' 0 0 0 0 0 + * 0 0 1 + * 1 0 0 1 + * 2 0 1 0 1 + * 3 0 0 0 0 1 + * + * + * @param s + * @return + */ + public int countSubstrings(String s) { + boolean[][] dp = new boolean[s.length()][s.length()]; + int res = 0; + for (int i = 0; i < s.length(); i++) { + for (int j = i; j >= 0; j--) { + if (i == j ) { + dp[i][j] = true; + res++; + continue; + } + if ((s.charAt(i) == s.charAt(j)) && (i == j + 1 || dp[i - 1][j + 1])) { + dp[i][j] = true; + res++; + } + } + } + return res; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode654.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode654.java new file mode 100644 index 0000000..ebcb430 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode654.java @@ -0,0 +1,51 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/28 13:56 + * @注释 + */ +public class LeetCode654 { + + @Test + public void test() { + new Solution().constructMaximumBinaryTree(new int[]{3, 2, 1, 6, 0, 5}).printTree(); + } + + class Solution { + public TreeNode constructMaximumBinaryTree(int[] nums) { + return circle(nums, 0, nums.length-1); + } + + private TreeNode circle(int[] nums, int start, int end) { + if (start > end) { + return null; + } + // 只有一个元素,直接构造即可 + if (end == start) { + return new TreeNode(nums[end]); + } + int maxIndex = findMax(nums, start, end); + TreeNode treeNode = new TreeNode(nums[maxIndex]); + treeNode.left = circle(nums, start, maxIndex - 1); + treeNode.right = circle(nums, maxIndex + 1, end); + return treeNode; + } + + private int findMax(int[] nums, int start, int end) { + int maxIndex = start; + while (start < end) { + start++; + if (nums[start] > nums[maxIndex]) { + maxIndex = start; + } + } + return maxIndex; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode669.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode669.java new file mode 100644 index 0000000..d93ce75 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode669.java @@ -0,0 +1,40 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/31 14:01 + * @注释 + */ +public class LeetCode669 { + + @Test + public void test() { + new Solution().trimBST(TreeNode.constructTreeByArray(3,0,4,null,2,null,null,1), 1, 3).printTree(); + } + + class Solution { + + public TreeNode trimBST(TreeNode root, int low, int high) { + if (root == null) { + return null; + } + + root.left = trimBST(root.left, low, high); + root.right = trimBST(root.right, low, high); + + if (root.val < low) { + return root.right; + } + + if (root.val > high) { + return root.left; + } + + return root; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode674.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode674.java new file mode 100644 index 0000000..980372d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode674.java @@ -0,0 +1,95 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/23 11:56 + * @注释 + */ +public class LeetCode674 { + @Test + public void test() + { + + int[] nums = new int[]{1,1,1,1}; + int lengthOfLCIS = new Solution1().findLengthOfLCIS(nums); + System.out.println(lengthOfLCIS); + } + + class Solution2 { + /** + * 如果当前元素大于前一个元素,则递增计数,并将计数与结果中的最大值进行比较更新。 + * 如果当前元素不大于前一个元素,则将计数重置为1。 + * @param nums + * @return + */ + public int findLengthOfLCIS(int[] nums) { + int res = 1; + int count = 1; + for (int i = 1; i < nums.length; i++) { + if (nums[i] > nums[i - 1]) { + count++; + res = Math.max(res, count); + } else { + count = 1; + } + } + return res; + } + } + + class Solution { + + + /** + * 最长且 连续递增的子序列 + * @param nums + * @return + */ + public int findLengthOfLCIS(int[] nums) { + // 找到所有递增区间 + int left = 0; + int right = 0; + int maxLength = 0; + while (right < nums.length - 1) { + if (nums[right + 1] <= nums[right]) { + maxLength = Math.max(maxLength, right - left + 1); + right++; + left = right; + }else { + right++; + } + } + + return Math.max(maxLength, right - left + 1); + } + } + + class Solution1 { + public int findLengthOfLCIS(int[] nums) { + /** + * dp[i] 表示可包含i的最长子序列长度 + * if nums[i] > nums[i-1] 递增 + * dp[i] = dp[i-1]+1 + * else + * dp[i] = 1 一旦出现递减,因为前面的连续递增是不能用的,需要直接重置 + */ + int[] dp = new int[nums.length]; + dp[0] = 1; + int ans = 1; + for (int i = 1; i < nums.length; i++) { + if (nums[i] > nums[i-1]) { + dp[i] = dp[i-1] + 1; + }else { + dp[i] = 1; + } + ans = Math.max(ans, dp[i]); + } + return ans; + } + + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode69.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode69.java new file mode 100644 index 0000000..ed27632 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode69.java @@ -0,0 +1,85 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * 69. x 的平方根 + * 简单 + * 相关标签 + * 相关企业 + * 提示 + * 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 + * + * 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 + * + * 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。 + * + * + * + * 示例 1: + * + * 输入:x = 4 + * 输出:2 + * 示例 2: + * + * 输入:x = 8 + * 输出:2 + * 解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。 + * + * + * 提示: + * + * 0 <= x <= 231 - 1 + */ +public class LeetCode69 { + + + /** + * 二分法 + * @param x + * @return + */ + public int mySqrt(int x) { + int left = 0; + int right = x; + int ans = 0; + while (left <= right) { + int middle = (left + right) / 2; + // 防止过长 + if ((long) middle * middle <= x) { + // 真正的x只会小于等于x + ans = middle; + left = middle + 1; + } else { + right = middle - 1; + } + } + return ans; + } + + /** + * 数学法 + * x^(1/2) = e^((lnx)/2) + * @param x + * @return + */ + public int mySqrt1(int x) { + if (x == 0) { + return 0; + } + // 获取到的是>=正确的开方根 + double log = Math.log(x); + int ans = (int) Math.exp(0.5 * log); + if ((long) (ans + 1) * (ans + 1) <= x) { + return ans + 1; + } + return ans; + } + + @Test + public void testSearch1() { + for (int i = 0; i < 100; i++) { + mySqrt1(i); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode698.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode698.java new file mode 100644 index 0000000..d1cc9ee --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode698.java @@ -0,0 +1,67 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/15 14:51 + * @注释 + */ +public class LeetCode698 { + + @Test + public void test() { + int[] nums = {4, 3, 2, 3, 5, 2, 1}; + int k = 4; + System.out.println(new Solution().canPartitionKSubsets(nums, k)); + } + + class Solution { + + public int[] numUsed; + public boolean canPartitionKSubsets(int[] nums, int k) { + numUsed = new int[nums.length]; + Arrays.sort(nums); + int sum = Arrays.stream(nums).sum(); + if (sum % k != 0 || nums[nums.length - 1] > sum / k) + return false; + + return divideGroups(nums, nums.length - 1, sum / k, 0, k); + } + + /** + * + * @param nums + * @param start + * @param target + * @param current + * @param k + * @return + */ + public boolean divideGroups(int[] nums, int start, int target, int current, int k) { + if (k == 1) + return true; // 分组操作执行k-1次之后,最后剩余的元素,就是最后一组了,不需要再匹配 + if (current == target) + return divideGroups(nums, nums.length - 1, target, 0, k - 1); // 分组操作执行k-1次后,最后剩余的元素,就是最后一组了,不需要再匹配 + for (int i = start; i >= 0; i--) { + if (numUsed[i] == 1 || current + nums[i] > target) continue; // 被使用的元素,不能再次使用;总和大于目标值,也不能使用 + + + numUsed[i] = 1; // 标记占用 + if (divideGroups(nums, i - 1, target, current + nums[i], k)) return true; + numUsed[i] = 0; // 撤销标记 + + + while (i > 0 && nums[i - 1] == nums[i]) i--; // 例如“12333333...”,假如最右侧的“3”这个值没有匹配上,那么它左侧的剩余五个“3”都不需要再匹配了。 + } + return false; + } + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode7.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode7.java new file mode 100644 index 0000000..ab54b4c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode7.java @@ -0,0 +1,80 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/28 9:52 + * @注释 + */ +public class LeetCode7 { + @Test + public void test() { + Solution solution = new Solution(); + int res = solution.reverse(1534236469); + System.out.println(res); + res = solution.reverse(-123); + System.out.println(res); + res = solution.reverse(120); + System.out.println(res); + res = solution.reverse(0); + System.out.println(res); + } + + class Solution { + public int reverse(int x) { + String s = String.valueOf(x); + char[] charArray = s.toCharArray(); + int left = 0; + if (charArray[0] == '-') { + left = 1; + } + + int right = charArray.length - 1; + StringBuilder sb = new StringBuilder(); + while (right >= left) { + sb.append(charArray[right]); + right--; + } + try { + int res = Integer.parseInt(sb.toString()); + if (left == 1) { + res = -res; + } + + return res; + } catch (NumberFormatException e) { + return 0; + } + + } + } + + + @Test + public void test1() { + Solution1 solution1 = new Solution1(); + int res = solution1.reverse(-134236469); + System.out.println(res); + } + + class Solution1 { + public int reverse(int x) { + + int res = 0; + while (x != 0) { // 正负都可以进入 + if (res > Integer.MAX_VALUE / 10) { + return 0; + } + if (res < Integer.MIN_VALUE / 10) { + return 0; + } + int retail = x % 10; // 余数 + x /= 10; + res = res * 10 + retail; + } + return res; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode70.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode70.java new file mode 100644 index 0000000..1347766 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode70.java @@ -0,0 +1,42 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/8 12:11 + * @注释 + */ +public class LeetCode70 { + + @Test + public void test() { + System.out.println(new Solution().climbStairs(0)); + } + + class Solution { + /** + * 1. 确定dp数组含义 dp[i] 表示到这里的方法数 + * 2. 地推公式 dp[i] = dp[i-1]+dp[i-2] + * 3. 初始化 dp[0] = 1;dp[1]=1 + * 4. 模拟推导1 1 2 3 5 8 + * 0 1 2 3 4 5 + * @param n + * @return + */ + public int climbStairs(int n) { + if (n <= 1) { + return n; + } + int[] dp = new int[n]; + dp[0] = 1; + dp[1] = 2; + for (int i = 2; i < n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n-1]; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode700.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode700.java new file mode 100644 index 0000000..5915eca --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode700.java @@ -0,0 +1,49 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/28 15:53 + * @注释 + */ +public class LeetCode700 { + @Test + public void test() { + TreeNode treeNode = TreeNode.constructTreeByArray(4, 2, 7, 1, 3); + new Solution1().searchBST(treeNode, 2).printTree(); + } + + class Solution { + public TreeNode searchBST(TreeNode root, int val) { + TreeNode index = root; + while (index != null) { + if (index.val > val) { + index = index.left; + } else if (index.val < val) { + index = index.right; + } else if (index.val == val) { + return index; + } + } + return null; + } + } + + class Solution1 { + public TreeNode searchBST(TreeNode root, int val) { + if (root == null) { + return null; + } + if (root.val > val) { + return searchBST(root.left, val); + } + if (root.val < val) { + return searchBST(root.right, val); + } + return root; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode701.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode701.java new file mode 100644 index 0000000..fa80ada --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode701.java @@ -0,0 +1,88 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/31 9:13 + * @注释 + */ +public class LeetCode701 { + + @Test + public void test() { + new Solution2().insertIntoBST(TreeNode.constructTreeByArray(5,null,14,10,77,null,null,null,95,null,null), 4).printTree(); + + } + + class Solution { + public TreeNode insertIntoBST(TreeNode root, int val) { + if (root == null) { + return new TreeNode(val); + } + insert(root, val); + return root; + } + + public void insert(TreeNode root, int val) { + if (root == null) { + return; + } + + + if (root.val < val) { + insert(root.right, val); + if (root.right == null) { + root.right = new TreeNode(val); + } + } else { + insert(root.left, val); + if (root.left == null) { + root.left = new TreeNode(val); + } + } + } + } + + class Solution1 { + public TreeNode insertIntoBST(TreeNode root, int val) { + // 找到了叶子节点,该位置就是要插入的地方 + if (root == null) { + return new TreeNode(val); + } + + if (root.val < val) { + root.right = insertIntoBST(root.right, val); + }else if (root.val > val){ + root.left = insertIntoBST(root.left, val); + } + return root; + } + } + class Solution2 { + public TreeNode insertIntoBST(TreeNode root, int val) { + if (root==null) return new TreeNode(val); + TreeNode pre = null; + TreeNode index = root; + while (index != null) { + pre = index; + if (index.val > val) { + index = index.left; + } else { + index = index.right; + } + } + if (pre.val > val) { + pre.left = new TreeNode(val); + } else { + pre.right = new TreeNode(val); + } + return root; + + + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode703.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode703.java new file mode 100644 index 0000000..e2dda66 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode703.java @@ -0,0 +1,51 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.PriorityQueue; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/22 15:14 + * @注释 + */ +public class LeetCode703 { + + @Test + public void test() { + KthLargest kthLargest = new KthLargest(3, new int[]{}); + System.out.println(kthLargest.add(3)); + System.out.println(kthLargest.add(5)); + System.out.println(kthLargest.add(10)); + System.out.println(kthLargest.add(9)); + System.out.println(kthLargest.add(4)); + } + + class KthLargest { + + PriorityQueue priorityQueue = null; + int size = 0; + + // 小顶堆 第k + public KthLargest(int k, int[] nums) { + priorityQueue = new PriorityQueue<>(); + this.size = k; + for (int num : nums) { + priorityQueue.offer(num); + if (priorityQueue.size() > k) { + priorityQueue.poll(); + } + } + } + + public int add(int val) { + priorityQueue.offer(val); + if (priorityQueue.size() > size) { + priorityQueue.poll(); + } + return priorityQueue.peek(); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode704.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode704.java new file mode 100644 index 0000000..e4b863c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode704.java @@ -0,0 +1,141 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Assert; +import org.junit.Test; + +/** + * + * 二分查找 + * + * + 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 + 示例 1: + + 输入: nums = [-1,0,3,5,9,12], target = 9 + 输出: 4 + 解释: 9 出现在 nums 中并且下标为 4 + 示例 2: + + 输入: nums = [-1,0,3,5,9,12], target = 2 + 输出: -1 + 解释: 2 不存在 nums 中因此返回 -1 + + + 提示: + + 你可以假设 nums 中的所有元素是不重复的。 + n 将在 [1, 10000]之间。 + nums 的每个元素都将在 [-9999, 9999]之间。 + + + 相关题目推荐 + 35.搜索插入位置(opens new window) + 34.在排序数组中查找元素的第一个和最后一个位置(opens new window) + 69.x 的平方根(opens new window) + 367.有效的完全平方数(opens new window) + #其他语言版本 + + */ +public class LeetCode704 { + + + /** + * 二分查找 [left,right] + * @param nums + * @param target + * @return + */ + public static int search(int[] nums, int target) { + if (nums.length == 0) { + return -1; + } + // 初始化指针 + int left = 0; + int right = nums.length - 1; + int index = 0; + while (left < right) { + // 计算中间索引 + index = (right + left) / 2; + if (nums[index] >= target) { + right = index; + } else{ + left = index + 1; + } + } + if (nums[(right + left) / 2] == target) { + return (right + left) / 2; + } + + + return -1; + + } + + public int search1(int[] nums, int target) { + int left = 0; // 左指针,初始指向数组最左边的位置 + int right = nums.length - 1; // 右指针,初始指向数组最右边的位置 + while (left <= right) { // 当左指针小于等于右指针时,循环执行 + int mid = left + (right - left) / 2; // 中间指针,计算左指针和右指针的中间位置 + if (nums[mid] == target) { // 如果中间位置的数值等于目标数值 + return mid; // 返回中间位置的索引 + } else if (nums[mid] < target) { // 如果中间位置的数值小于目标数值 + left = mid + 1; // 将左指针移动到中间位置的右边 + } else { // 如果中间位置的数值大于目标数值 + right = mid - 1; // 将右指针移动到中间位置的左边 + } + } + return -1; // 没有找到目标数值,返回-1 + } + + + /** + * 二分查找 [left,right) + * @param nums + * @param target + * @return + */ + public int search2(int[] nums, int target) { + int left = 0; + int right = nums.length; + while (left < right) { + int middle = (left + right) / 2; + if (nums[left] == target) { + return left; + } else if (nums[middle] >= target) { + right = middle; + } else { + left = middle+1; + } + } + + return -1; + + } + + + + + + @Test + public void testSearch1() { + LeetCode704 solution = new LeetCode704(); + + int[] nums = {1}; + int target = 5; + Assert.assertEquals(-1, solution.search2(nums, target)); + + nums = new int[]{10, 20, 30, 40}; + target = 30; + Assert.assertEquals(2, solution.search1(nums, target)); + + nums = new int[]{1, 2, 3}; + target = 4; + Assert.assertEquals(-1, solution.search1(nums, target)); + + + nums = new int[]{1}; + target = 1; + Assert.assertEquals(0, solution.search1(nums, target)); + + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode707.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode707.java new file mode 100644 index 0000000..3680095 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode707.java @@ -0,0 +1,268 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * 707. 设计链表 + * 中等 + * 相关标签 + * 相关企业 + * 你可以选择使用单链表或者双链表,设计并实现自己的链表。 + * + * 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。 + * + * 如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。 + * + * 实现 MyLinkedList 类: + * + * MyLinkedList() 初始化 MyLinkedList 对象。 + * int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。 + * void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。 + * void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。 + * void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。 + * void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。 + * + * + * 示例: + * + * 输入 + * ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"] + * [[], [1], [3], [1, 2], [1], [1], [1]] + * 输出 + * [null, null, null, null, 2, null, 3] + * + * 解释 + * MyLinkedList myLinkedList = new MyLinkedList(); + * myLinkedList.addAtHead(1); + * myLinkedList.addAtTail(3); + * myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3 + * myLinkedList.get(1); // 返回 2 + * myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3 + * myLinkedList.get(1); // 返回 3 + */ +public class LeetCode707 { + + @Test + public void test() { + MyLinkedList myLinkedList = new MyLinkedList(); + myLinkedList.addAtHead(4); + myLinkedList.get(1); + myLinkedList.addAtHead(1); + myLinkedList.addAtHead(5); + myLinkedList.deleteAtIndex(3); + myLinkedList.addAtHead(7); + myLinkedList.get(3); + myLinkedList.get(3); + myLinkedList.get(3); + + myLinkedList.addAtHead(1); + myLinkedList.deleteAtIndex(4); + } + +} + +class ListNode1{ + int val; + ListNode1 next; + + public ListNode1() { + } + + public ListNode1(int val, ListNode1 next) { + this.val = val; + this.next = next; + } +} + +/** + * 过了 但效果不好 + * + * 执行用时分布11ms + * 击败12.61%使用 Java 的用户 + * + * 消耗内存分布44.49MB + * 击败5.02%使用 Java 的用户 + */ +class MyLinkedList1 { + + ListNode1 head; + public MyLinkedList1() { + head = null; + } + + // 0 + public int get(int index) { + if (index < 0) { + return -1; + } + ListNode1 node = head; + int i = 0; + while (node != null) { + if (i++ == index) { + return node.val; + } + node = node.next; + } + return -1; + } + + public void addAtHead(int val) { + head = new ListNode1(val, head); + } + + public void addAtTail(int val) { + if (head == null) { + head = new ListNode1(val, null); + return; + } + ListNode1 node = head; + while (node.next != null) { + node = node.next; + } + node.next = new ListNode1(val, null); + } + + public void addAtIndex(int index, int val) { + if (index == 0) { + addAtHead(val); + return; + } + ListNode1 node = head; + int i = 0; + while (node != null) { + if (i++ == index - 1) { + node.next = new ListNode1(val, node.next); + return; + } + node = node.next; + } + } + + public void deleteAtIndex(int index) { + if (index == 0) { + // 头删 + head = head.next; + return; + } + ListNode1 node = head; + int i = 0; + while (node != null) { + if (i++ == index - 1 && node.next != null) { + node.next = node.next.next; + } + node = node.next; + } + } +} + +//class ListNode{ +// int val; +// ListNode next; +// +// public ListNode() { +// } +// +// public ListNode(int val, ListNode next) { +// this.val = val; +// this.next = next; +// } +//} + +/** + * 执行用时分布9ms + * 击败88.60%使用 Java 的用户 + * + * 消耗内存分布44.44MB + * 击败5.02%使用 Java 的用户 + */ +class MyLinkedList { + + int size; + ListNode head; + + public MyLinkedList() { + head = null; + size = 0; + } + + public int get(int index) { + if (index < 0 || index > size - 1) { + return -1; + } + ListNode node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node.val; + } + + public void addAtHead(int val) { + head = new ListNode(val, head); + size++; + } + + public void addAtTail(int val) { + addAtIndex(size, val); + } + + public void addAtIndex(int index, int val) { + if (index == 0) { + // 头插 + head = new ListNode(val, head); + size++; + return; + } + if (index < 0 || index > size) { + return; + } + + ListNode node = head; + int i = 0; + while (i++ < index - 1) { + node = node.next; + } + node.next = new ListNode(val, node.next); + size++; + } + + public void deleteAtIndex(int index) { + if (index < 0 || index > size - 1) { + return; + } + if (index == 0) { + // 头删 + head = head.next; + size--; + return; + } + + ListNode node = head; + int i = 0; + while (i++ < index - 1) { + node = node.next; + } + node.next = node.next.next; + size--; + } +} + +/** + * Your MyLinkedList object will be instantiated and called as such: + * MyLinkedList obj = new MyLinkedList(); + * int param_1 = obj.get(index); + * obj.addAtHead(val); + * obj.addAtTail(val); + * obj.addAtIndex(index,val); + * obj.deleteAtIndex(index); + */ + +/** + * Your MyLinkedList object will be instantiated and called as such: + * MyLinkedList obj = new MyLinkedList(); + * int param_1 = obj.get(index); + * obj.addAtHead(val); + * obj.addAtTail(val); + * obj.addAtIndex(index,val); + * obj.deleteAtIndex(index); + */ diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode707_2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode707_2.java new file mode 100644 index 0000000..66d601e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode707_2.java @@ -0,0 +1,166 @@ +package cn.whaifree.leetCode.LinkedList; + +import org.junit.Test; + +public class LeetCode707_2 { + + @Test + public void test() { + MyLinkedList myLinkedList = new MyLinkedList(); + myLinkedList.addAtHead(1); + myLinkedList.addAtHead(2); + myLinkedList.addAtHead(3); + myLinkedList.addAtHead(4); + myLinkedList.addAtHead(5); +// myLinkedList.addAtIndex(4, 99); + System.out.println(myLinkedList.get(0)); + System.out.println(myLinkedList.get(1)); + System.out.println(myLinkedList.get(2)); + System.out.println(myLinkedList.get(3)); + System.out.println(myLinkedList.get(4)); + System.out.println(myLinkedList.get(-1)); + +// myLinkedList.deleteAtIndex(4); + } + + class ListNode { + ListNode pre; + ListNode next; + int val; + + public ListNode(ListNode pre, ListNode next, int val) { + this.pre = pre; + this.next = next; + this.val = val; + } + } + + + class MyLinkedList { + ListNode head; + ListNode tail; + int size; + + public MyLinkedList() { + head = new ListNode(null, null, 0); + tail = new ListNode(head, null, 0); + head.next = tail; + size = 0; + } + + public int get(int index) { + if (index >= size || index < 0) { + return -1; + } + if (index <= size / 2) { + ListNode trueIndex = head.next; + for (int i = 0; i < index; i++) { + trueIndex = trueIndex.next; + } + return trueIndex.val; + } else { + ListNode trueIndex = tail.pre; + for (int i = size - 1; i > index; i--) { + trueIndex = trueIndex.pre; + } + return trueIndex.val; + } + } + + public void addAtHead(int val) { + ListNode listNode = new ListNode(head, head.next, val); + head.next.pre = listNode; + head.next = listNode; + size++; + } + + public void addAtTail(int val) { + ListNode listNode = new ListNode(tail.pre, tail, val); + tail.pre.next = listNode; + tail.pre = listNode; + size++; + } + + public void addAtIndex(int index, int val) { + if (index > size) { + return; + } + + if (index == 0) { + addAtHead(val); + return; + } + if (index == size) { + addAtTail(val); + return; + } + + if (index <= size / 2) { + ListNode trueIndex = head.next; + for (int i = 0; i < index; i++) { + trueIndex = trueIndex.next; + } + ListNode listNode = new ListNode(trueIndex.pre, trueIndex, val); + trueIndex.pre.next = listNode; + trueIndex.pre = listNode; + } else { + ListNode trueIndex = tail.pre; + for (int i = size - 1; i > index; i--) { + trueIndex = trueIndex.pre; + } + ListNode listNode = new ListNode(trueIndex.pre, trueIndex, val); + trueIndex.pre.next = listNode; + trueIndex.pre = listNode; + } + size++; + } + + public void deleteAtIndex(int index) { + if (index >= size || index < 0) { + return; + } + if (index == 0) { + head.next.next.pre = head; + head.next = head.next.next; + size--; + return; + } + if (index == size - 1) { + tail.pre.pre.next = tail; + tail.pre = tail.pre.pre; + size--; + return; + } + + if (index < size / 2) { + ListNode trueIndex = head.next; + for (int i = 0; i < index; i++) { + trueIndex = trueIndex.next; + } + trueIndex.pre.next = trueIndex.next; + trueIndex.next.pre = trueIndex.pre; + + } else { + ListNode trueIndex = tail.pre; + for (int i = size - 1; i > index; i--) { + trueIndex = trueIndex.pre; + } + trueIndex.next.pre = trueIndex.pre; + trueIndex.pre.next = trueIndex.next; + } + size--; + } + } + +/** + * Your MyLinkedList object will be instantiated and called as such: + * MyLinkedList obj = new MyLinkedList(); + * int param_1 = obj.get(index); + * obj.addAtHead(val); + * obj.addAtTail(val); + * obj.addAtIndex(index,val); + * obj.deleteAtIndex(index); + */ +} + + diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode71.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode71.java new file mode 100644 index 0000000..e399c06 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode71.java @@ -0,0 +1,92 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/22 15:29 + * @注释 + */ +public class LeetCode71 { + + public static void main(String[] args) { + + new Thread(new Runnable() { + @Override + public void run() { + List res = new ArrayList<>(); + while (true) { + System.out.println("ADD"); + res.add(new int[100000]); + } + } + }).start(); + new Thread(new Runnable() { + @Override + public void run() { + List res = new ArrayList<>(); + while (true) { + System.out.println(1000); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + } + } + }).start(); + + } + + @Test + public void test() { + System.out.println(new Solution().simplifyPath("/.../../..")); + } + + class Solution { + /** + * + * . 当前目录 + * .. 父亲目录 + * ///*n /// // / 变为/ + * + * + * - 碰到.. 出栈 + * - 碰到. 忽略 + * - N*\// 都忽略 + * + * + * @param path + * @return + */ + public String simplifyPath(String path) { + Deque stack = new LinkedList<>(); + String[] split = path.split("/"); + for (int i = 0; i < split.length; i++) { + String s = split[i]; + if (s.equals("/")||s.isEmpty()||s.equals(".")) { + continue; + } else if (s.equals("..")) { + if (!stack.isEmpty()) { + stack.pop(); + } + continue; + } + stack.push(s); + } + StringBuilder stringBuilder = new StringBuilder(); + while (!stack.isEmpty()) { + stringBuilder.append("/"); + stringBuilder.append(stack.pollLast()); + } + return stringBuilder.isEmpty() ? "/" : stringBuilder.toString(); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode713.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode713.java new file mode 100644 index 0000000..6bee3ed --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode713.java @@ -0,0 +1,64 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/23 16:13 + * @注释 + */ +public class LeetCode713 { + + @Test + public void test() { + int[] nums = {1,2,3}; + int k = 0; + int res = new Solution1().numSubarrayProductLessThanK(nums, k); + System.out.println(res); + } + + class Solution { + public int numSubarrayProductLessThanK(int[] nums, int k) { + + + int res = 0; + int pro = 1; + for (int left = 0, right = 0; right < nums.length; right++) { + pro *= nums[right]; + while (pro >= k) { + // 一旦 找到比k小的,左边就往前,并且pro得到最新的 + pro /= nums[left++]; + } + res += right - left + 1; + + } + + return res; + + } + } + + class Solution1 { + public int numSubarrayProductLessThanK(int[] nums, int k) { + if (k <= 1) return 0; //1 <= nums[i] <= 1000 + int res = 0; + int pro = 1; + + int left = 0; + int right = 0; + while (right < nums.length) { + pro *= nums[right]; + // 直到总乘积大于k,左边才左移 + while (pro >= k) { + pro /= nums[left]; + left++; + } + res += right - left + 1; + right++; + } + return res; + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode714.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode714.java new file mode 100644 index 0000000..0e9c28d --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode714.java @@ -0,0 +1,69 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/19 12:27 + * @注释 + */ +public class LeetCode714 { + + @Test + public void test() + { + int[] prices = {1, 3, 2, 8, 4, 9}; + int maxProfit = new Solution1().maxProfit(prices, 2); + System.out.println(maxProfit); + } + + class Solution { + /** + * dp[i][0] 表示手里没有股票的最大手头持有 + * - i-1 就没有 dp[i-1][0] + * - i刚刚卖出 dp[i-1][1] + price[i] - fee + * dp[i][1] 表示手里有股票的最大手头持有 + * - i-1 有 dp[i-1][1] + * - i刚刚买入 dp[i-1][0] - price[i] - fee + * @param prices + * @param fee + * @return + */ + public int maxProfit(int[] prices, int fee) { + int[][] dp = new int[prices.length][2]; + dp[0][1] = -prices[0] - fee; + for (int i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i] - fee); + } + return dp[prices.length - 1][0]; + } + } + + class Solution1 { + /** + * dp[i][0] 表示手里没有股票的最大手头持有 + * - i-1 就没有 dp[i-1][0] + * - i刚刚卖出 dp[i-1][1] + price[i] - fee + * dp[i][1] 表示手里有股票的最大手头持有 + * - i-1 有 dp[i-1][1] + * - i刚刚买入 dp[i-1][0] - price[i] - fee + * @param prices + * @param fee + * @return + */ + public int maxProfit(int[] prices, int fee) { + int[] dp = new int[2]; + dp[1] = -prices[0] - fee; + for (int i = 1; i < prices.length; i++) { + dp[0] = Math.max(dp[0], dp[1] + prices[i]); + dp[1] = Math.max(dp[1], dp[0] - prices[i] - fee); + } + return dp[0]; + } + } + + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode718_2.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode718_2.java new file mode 100644 index 0000000..d9e8d4e --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode718_2.java @@ -0,0 +1,78 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/23 12:22 + * @注释 + */ + +public class LeetCode718_2 { + @Test + public void test() + { + int[] nums1 = {1,2,3,2,1}; + int[] nums2 = {3,2,1,4,7}; + + int i = new Solution1().findLength(nums1, nums2); + System.out.println(i); + } + + class Solution { + public int findLength(int[] nums1, int[] nums2) { + + /** + * 用二维数组可以记录两个字符串的所有比较情况 + * dp[i][j] 表示 以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度 + * dp[i][j] 可以由dp[i-1][j-1] + 1 和 0 两种情况推出 + * + * dp[i][j] + * if nums1[i]==nums[j] + * dp[i][j] = dp[i-1][j-1] + 1 + * else + * dp[i][j] = 0 + */ + int[][] dp = new int[nums1.length + 1][nums2.length + 1]; + int res = 0; + for (int i = 1; i <= nums1.length; i++) { + for (int j = 1; j <= nums2.length; j++) { + if (nums1[i - 1] == nums2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = 0; + } + res = Math.max(res, dp[i][j]); + } + } + + return res; + } + } + + class Solution1 { + public int findLength(int[] nums1, int[] nums2) { + + /** + * dp[i][j]都是由dp[i - 1][j - 1]推出。那么压缩为一维数组,也就是dp[j]都是由dp[j - 1]推出。 + * + */ + int[] dp = new int[nums1.length + 1]; + int res = 0; + for (int i = 1; i <= nums1.length; i++) { + for (int j = nums2.length; j > 0; j--) { // 从后面开始比较,避免重复覆盖dp[i] + if (nums1[i - 1] == nums2[j - 1]) { + dp[j] = dp[j - 1] + 1; + } else { + dp[j] = 0; + } + res = Math.max(res, dp[j]); + } + } + + return res; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode73.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode73.java new file mode 100644 index 0000000..428e6a3 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode73.java @@ -0,0 +1,52 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/23 9:18 + * @注释 + */ +public class LeetCode73 { + + @Test + public void test() { + int[][] matrix = new int[][]{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}; + new Solution().setZeroes(matrix); + for (int[] ints : matrix) { + System.out.println(Arrays.toString(ints)); + } + } + + + class Solution { + public void setZeroes(int[][] matrix) { + + int yLen = matrix.length; + boolean[] row = new boolean[yLen]; + int xLen = matrix[0].length; + boolean[] col = new boolean[xLen]; + + + for (int y = 0; y < yLen; y++) { + for (int x = 0; x < xLen; x++) { + if (matrix[y][x] == 0) { + row[y] = true; + col[x] = true; + } + } + } + + for (int y = 0; y < yLen; y++) { + for (int x = 0; x < xLen; x++) { + if (row[y] || col[x]) { + matrix[y][x] = 0; + } + } + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode738.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode738.java new file mode 100644 index 0000000..57b4771 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode738.java @@ -0,0 +1,65 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/6 15:24 + * @注释 + */ +public class LeetCode738 { + + @Test + public void test() { + System.out.println(new Solution().monotoneIncreasingDigits(65832)); + } + + + class Solution { + + /** + * 98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]减一,strNum[i]赋值9(因为要最大的数,用9一定满足非递减),这样这个整数就是89 + * @param N + * @return + */ + public int monotoneIncreasingDigits(int N) { + String[] strings = (N + "").split(""); + + int start = strings.length; + + // 出现递减的两个 前一个-1,找到最先递减的的index,index后面全部为9 + for (int i = strings.length - 1; i > 0; i--) { + if (Integer.parseInt(strings[i]) < Integer.parseInt(strings[i - 1])) { + strings[i - 1] = (Integer.parseInt(strings[i - 1]) - 1) + ""; + start = i; + } + } + + + for (int i = start; i < strings.length; i++) { + strings[i] = "9"; + } + return Integer.parseInt(String.join("",strings)); + } + } + + class Solution1 { + public int monotoneIncreasingDigits(int n) { + String s = String.valueOf(n); + char[] chars = s.toCharArray(); + int start = s.length(); + for (int i = s.length() - 2; i >= 0; i--) { + if (chars[i] > chars[i + 1]) { + chars[i]--; + start = i+1; + } + } + for (int i = start; i < s.length(); i++) { + chars[i] = '9'; + } + return Integer.parseInt(String.valueOf(chars)); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode739.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode739.java new file mode 100644 index 0000000..7b1a565 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode739.java @@ -0,0 +1,58 @@ +package cn.whaifree.leetCode.MonotoneStack; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/8 11:48 + * @注释 + */ +public class LeetCode739 { + + @Test + public void test() + { + int[] temperatures = {73,74,75,71,69,72,76,73}; + Solution solution = new Solution(); + int[] res = solution.dailyTemperatures(temperatures); + System.out.println(Arrays.toString(res)); + } + + class Solution { + /** + * 单调栈 + * + * 不断把i放入栈 + * if nums[i] > stack.peek + * pop = stack.pop + * res[] = i - pop + * else + * stack.push(i) + * + * @param temperatures + * @return + */ + public int[] dailyTemperatures(int[] temperatures) { + int[] res = new int[temperatures.length]; + Deque stack = new LinkedList<>(); + stack.push(0); + for (int i = 1; i < temperatures.length ; i++) { + if (temperatures[i] > temperatures[stack.peek()]) { + // 如果当前比遍历元素比 栈顶的大,证明该元素就是栈顶元素右边第一个大于他的值 + // 并且需要判断一下,当前元素是不是 新栈顶 的下一个大于他的 + while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) { + res[stack.peek()] = i - stack.peek(); + stack.pop(); + } + } + stack.push(i); + } + return res; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode746.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode746.java new file mode 100644 index 0000000..3dd9024 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode746.java @@ -0,0 +1,46 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/8 12:24 + * @注释 + */ +public class LeetCode746 { + + @Test + public void test() { + System.out.println(new Solution().minCostClimbingStairs(new int[]{1,1001})); + } + + class Solution { + + /** + * 含义 dp[i] 走到这最少支出的花费 + * 递推公式 + * dp[i] = min{dp[i-2]+cost[i-2] , dp[i-1]+cost[i-1]} + * 初始化 dp[0]=0 dp[1]=0 + * 模拟推导 + * 1,100,1,1,1,100,1,1,100,1 + * 0 0 1 2 + * + * @param cost + * @return + */ + public int minCostClimbingStairs(int[] cost) { + //一旦你支付此费用,即可选择向上爬一个或者两个台阶。 + int length = cost.length; + int[] dp = new int[length+1]; + dp[0] = 0; + dp[1] = 0; + + for (int i = 2; i <= length; i++) { + // 前面两个数有可能跳到本数,判断前两个数跳本数的代价 + dp[i] = Math.min(dp[i - 2] + cost[i - 2], dp[i - 1] + cost[i - 1]); + } + return dp[length]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode763.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode763.java new file mode 100644 index 0000000..93fa2f9 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode763.java @@ -0,0 +1,113 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/5 11:03 + * @注释 + */ +public class LeetCode763 { + @Test + public void test() { + new Solution1().partitionLabels("ababcbacadefegdehijhklij").forEach( + i -> { + System.out.println(i); + } + ); + + } + // 即最多能砍s多少刀?使得同一字母都出现在一个片段。 + public List partitionLabels(String s) { + // 统计 每个字符最远出现的位置, + char[] chars = s.toCharArray(); + int[] map = new int[26]; + for (int i = 0; i < chars.length; i++) { + map[chars[i] - 'a'] = i; + } + + List res = new ArrayList<>(); + + // 再遍历idx(最远的下标)前面找到最远出现的位置==当前i 就是一个切断点 + int left = -1; // 标记左边界 + int far = 0; // 标记最远出现的 + for (int i = 0; i < chars.length; i++) { + far = Math.max(far, map[chars[i] - 'a']); // far 表示最远边界, + // 最远出现的 和 当前索引一样,证明找到分割点 + if (far == i) { + res.add(i - left); + left = i; + } + } + + return res; + } + + + class Solution1 { + + /** + * 先统计每个字符最早最晚出现的位置 + * @param s + * @return + */ + public List partitionLabels(String s) { + int[][] partitions = staticLabel(s.toCharArray()); + List res = new ArrayList<>(); + Arrays.sort(partitions, (o1, o2) -> Integer.compare(o1[0], o2[0])); + int right = partitions[0][1]; + int left = 0; + for (int i = 0; i < partitions.length; i++) { + if (partitions[i][0] > right) { + //左边界大于右边界即可纪委一次分割 + res.add(right - left + 1); + left = partitions[i][0]; + } + right = Math.max(right, partitions[i][1]); + + } + //最右端 + res.add(right - left + 1); + return res; + } + + public int[][] staticLabel(char[] chars) { + int[][] map = new int[26][2]; + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + if (map[c - 'a'][0] == 0) { + map[c - 'a'][0] = i; + } + map[c - 'a'][1] = i;//最远出现 + + //第一个元素区别对待一下 + map[chars[0] - 'a'][0] = 0; + } + + // 去除字符串中未出现的字母所占用区间 + List temp = new ArrayList<>(); + List> h = new LinkedList<>(); + //组装区间 + for (int i = 0; i < 26; i++) { + temp.clear(); + temp.add(map[i][0]); + temp.add(map[i][1]); + h.add(new ArrayList<>(temp)); + } + int[][] res = new int[h.size()][2]; + for (int i = 0; i < h.size(); i++) { + List list = h.get(i); + res[i][0] = list.get(0); + res[i][1] = list.get(1); + } + + return map; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode77.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode77.java new file mode 100644 index 0000000..1524f8c --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode77.java @@ -0,0 +1,57 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/31 20:24 + * @注释 + */ +public class LeetCode77 { + + @Test + public void test() { + new Solution().combine(4, 4).forEach( + list -> { + list.forEach(System.out::print); + System.out.println(); + } + ); + } + + + class Solution { + List> res = new LinkedList<>(); + + List path = new ArrayList<>(); + + public List> combine(int n, int k) { + circle(1, n, k); + return res; + } + + void circle(int start, int end, int k) { + if (path.size() == k) { + res.add(new ArrayList<>(path)); + return; + } + + // 剪枝,可以选择的个数不满足最小需要的个数 + // 已经选择的个数 path.size + // 还需要的个数 k-path.size + // 可以选择的个数<还需要的个数 end-ik-path.size时正常执行 i> res = new ArrayList<>(); + List temp = new ArrayList<>(); + public List> subsets(int[] nums) { + backTracking(nums, 0); + return res; + } + + void backTracking(int[] nums, int start) { + res.add(new ArrayList<>(temp)); + if (start >= nums.length) { + return; + } + + for (int i = start; i < nums.length ; i++) { + temp.add(nums[i]); + backTracking(nums,i+1); + temp.remove(temp.size() - 1); + } + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode797.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode797.java new file mode 100644 index 0000000..db960b1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode797.java @@ -0,0 +1,47 @@ +package cn.whaifree.leetCode.Graph; + +import org.junit.Test; + +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/17 18:09 + * @注释 + */ +public class LeetCode797 { + + @Test + public void test() { + int[][] graph = {{4,3,1},{3,2,4},{3},{4},{}}; + List> res = new Solution().allPathsSourceTarget(graph); + res.forEach(System.out::println); + } + + class Solution { + List> res = null; + List path = null; + public List> allPathsSourceTarget(int[][] graph) { + res = new java.util.ArrayList<>(); + path = new java.util.ArrayList<>(); + path.add(0); + dfs(graph, 0); + return res; + } + + public void dfs(int[][] graph, int cur) { + if (!path.isEmpty() && graph.length - 1 == path.get(path.size() - 1)) { + res.add(new java.util.ArrayList<>(path)); + return; + } + + int[] ints = graph[cur]; + for (int i = 0; i < ints.length; i++) { + path.add(ints[i]); + dfs(graph, ints[i]); // 0-4 + path.remove(path.size() - 1); + } + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode8.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode8.java new file mode 100644 index 0000000..75f8241 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode8.java @@ -0,0 +1,58 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/28 11:06 + * @注释 + */ +public class LeetCode8 { + @Test + public void test() { + System.out.println(new Solution().myAtoi("999999224324")); + } + + class Solution { + public int myAtoi(String s) { + if (s == null || s.isEmpty()) { + return 0; + } + char[] strChar = s.toCharArray(); + + int left = 0; + while (left < s.length() && strChar[left] == ' ') { + left++; + } + if (left == s.length()) { + return 0; + } + boolean neg = false; + if (s.charAt(left) == '-') { + left++; + neg = true; + } else if (s.charAt(left) == '+') { + left++; + } + + long res = 0; + while (left < s.length() && isDigit(s.charAt(left))) { + res = res * 10 + (s.charAt(left) - '0'); + left++; + if (res > Integer.MAX_VALUE) { + return neg? Integer.MIN_VALUE : Integer.MAX_VALUE; + } + if (res < Integer.MIN_VALUE) { + return neg? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + } + return (int) (neg? -res : res); + } + + public boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode80.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode80.java new file mode 100644 index 0000000..4b9fca8 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode80.java @@ -0,0 +1,61 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/16 16:23 + * @注释 + */ +public class LeetCode80 { + + @Test + public void test() { + int[] nums = new int[]{0, 0, 1, 1, 1, 1, 2, 3, 3}; + System.out.println(new Solution().removeDuplicates(nums)); + } + + class Solution { + /** + * 双指针 + * - 跳跃判断,如果不一样就让left向前,并赋值 + * + * @param nums + * @return + */ + public int removeDuplicates(int[] nums) { + if (nums.length < 3) return nums.length; + int leftSlow = 0; + int rightFast = 2; + while (rightFast < nums.length) { + if (nums[rightFast] != nums[leftSlow]) { + nums[leftSlow + 2] = nums[rightFast]; + leftSlow++; + } + rightFast++; + } + return leftSlow + 2; + } + } + + + class Solution1 { + /** + * + * + * @param nums + * @return + */ + public int removeDuplicates(int[] nums) { + // 数组中的一号和二号元素肯定不用删除 + int index = 2; + for(int i = 2 ; i < nums.length ; i++) { + if(nums[i] != nums[index-2]) { + nums[index++] = nums[i]; + } + } + return index; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode86.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode86.java new file mode 100644 index 0000000..e45fbaf --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode86.java @@ -0,0 +1,48 @@ +package cn.whaifree.leetCode.Array; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/6 12:45 + * @注释 + */ +public class LeetCode86 { + + @Test + public void test() { + ListNode listNode = ListNode.listNodeFromArray(new int[]{1, 4, 3, 2, 5, 2}); + ListNode listNode1 = new Solution().partition(listNode, 3); + listNode1.printList(); + } + + /** + * + */ + + class Solution { + public ListNode partition(ListNode head, int x) { + ListNode pre = new ListNode(-1, head); + ListNode small = new ListNode(-1); + ListNode big = new ListNode(-1); + ListNode smallIndex = small; + ListNode bigIndex = big; + ListNode index = head; + while (index != null) { + if (index.val < x) { + smallIndex.next = index; + smallIndex = smallIndex.next; + } else { + bigIndex.next = index; + bigIndex = bigIndex.next; + } + index = index.next; + } + smallIndex.next = big.next; + bigIndex.next = null; + return small.next; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode860.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode860.java new file mode 100644 index 0000000..d59b095 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode860.java @@ -0,0 +1,61 @@ +package cn.whaifree.leetCode.Greedy; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/28 13:22 + * @注释 + */ +public class LeetCode860 { + + @Test + public void test() { + System.out.println(new Solution().lemonadeChange(new int[]{5, 5, 10, 10, 20})); + } + + class Solution { + + /** + * bills[i] 不是 5 就是 10 或是 20 + * + * @param bills + * @return + */ + public boolean lemonadeChange(int[] bills) { + + int fiveHave = 0; // 有5元的钞票数 + int tenHave = 0; // 10元钞票数 + for (int i = 0; i < bills.length; i++) { + + if (bills[i] == 5) { // 5元直接收下 + fiveHave++; + } else if (bills[i] == 10) { // 10元则找5元 + tenHave++; + fiveHave--; + } else if (bills[i] == 20) { // 20元可以选择给他10+5或者3个5元 + if (tenHave >= 1) { + tenHave--; + fiveHave--; + } else { + fiveHave -= 3; + } + } + // 如果钞票不够找 + if (fiveHave < 0 || tenHave < 0) { + return false; + } + } + return true; + } + + + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode88.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode88.java new file mode 100644 index 0000000..00f0205 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode88.java @@ -0,0 +1,48 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/16 16:11 + * @注释 + */ +public class LeetCode88 { + + @Test + public void test() + { + int[] nums1 = new int[]{1,2,3,0,0,0}; + int[] nums2 = new int[]{2,5,6}; + new Solution().merge(nums1, 3, nums2, 3); + System.out.println(Arrays.toString(nums1)); + } + + class Solution { + public void merge(int[] nums1, int m, int[] nums2, int n) { + int index = 0; + int[] res = new int[nums1.length]; + int index1 = 0; + int index2 = 0; + while (index1 < m && index2 < n) { + if (nums1[index1] < nums2[index2]) { + res[index++] = nums1[index1++]; + }else { + res[index++] = nums2[index2++]; + } + } + + while (index1 < m) { + res[index++] = nums1[index1++]; + } + while (index2 < n) { + res[index++] = nums2[index2++]; + } + + System.arraycopy(res, 0, nums1, 0, index); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode9.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode9.java new file mode 100644 index 0000000..cc26cb5 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode9.java @@ -0,0 +1,53 @@ +package cn.whaifree.leetCode.String; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/28 14:36 + * @注释 + */ +public class LeetCode9 { + + class Solution { + public boolean isPalindrome(int x) { + String s = String.valueOf(x); + int left = 0; + int right = s.length() - 1; + while (left < right) { + if (s.charAt(left) != s.charAt(right)) { + return false; + } + left++; + right--; + } + return true; + } + } + + @Test + public void test() { + Solution solution = new Solution(); + System.out.println(solution.isPalindrome(5)); + System.out.println(solution.isPalindrome(-121)); + } + + class Solution1 { + public boolean isPalindrome(int x) { + if (x < 0) { + return false; + } + + int A = x; + int res = 0; + while (A != 0) { + res = res * 10 + A % 10; + A /= 10; + } + return x == res; + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode90.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode90.java new file mode 100644 index 0000000..e07b6a0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode90.java @@ -0,0 +1,66 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/18 13:26 + * @注释 + */ +public class LeetCode90 { + + @Test + public void test() { + new Solution().subsetsWithDup(new int[]{1, 2, 2}).forEach( + list -> { + System.out.println(list); + } + ); + } + + class Solution { + + List> res = new ArrayList<>(); + List temp = new ArrayList<>(); + boolean[] used = null; + public List> subsetsWithDup(int[] nums) { + Arrays.sort(nums); + used = new boolean[nums.length]; + backTracking(nums, 0); + return res; + } + + void backTracking(int[] nums, int start) { + res.add(new ArrayList<>(temp)); + if (start >= nums.length) { + return; + } + + + + for (int i = start; i < nums.length ; i++) { + + // 1. u1 u2 相同,并且u1曾经被调用过,则不继续进行本次循环 +// if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) { +// continue; +// } + // 2. 不使用used数组,跳过当前树层使用过的、相同的元素 + if ( i > start && nums[i - 1] == nums[i] ) { + continue; + } + + temp.add(nums[i]); + used[i] = true; + backTracking(nums,i+1); + temp.remove(temp.size() - 1); + used[i] = false; + } + + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode912_SortArrays.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode912_SortArrays.java new file mode 100644 index 0000000..10d3003 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode912_SortArrays.java @@ -0,0 +1,288 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Random; + +/** + * + * 排序算法有这几种: + * 常见的排序算法包括但不限于以下这些: + * 冒泡排序:从第一个元素开始与右侧元素两两比较并交换,直到右侧成为有序部分。 + * 选择排序:有序部分在左侧,在剩余元素中找到最小的那个元素,并与剩余元素中第一个元素交换。 + * 插入排序:有序部分在左侧,将剩余元素中第一个元素不断向左交换,直到此元素处于有序部分恰当位置。 + * 希尔排序:取一个间隔值,距离为间隔值的元素为一组,将整个数组分为若干组。每组内进行插入排序。缩小间隔值并重复,直到间隔值为1,即所有元素在同一组。 + * + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/20 14:20 + * @注释 + */ +public class LeetCode912_SortArrays { + + @Test + public void test() { + + int[] nums = {5,1,1,2,0,0}; + +// int[] res = new Solution2().sortArray(nums); +// System.out.println(Arrays.toString(res)); +// +// int[] ints = Arrays.copyOf(res, res.length); +// Arrays.sort(nums); +// System.out.println(Arrays.equals(ints, nums)); + + int[] res2 = new MergeSort.Solution().sortArray(nums); + + System.out.println(Arrays.toString(res2)); + } + + + + class Solution { + /** + * 冒泡 + * @param nums + * @return + */ + public int[] sortArray(int[] nums) { + boolean isSwap = false; + for (int i = 0; i < nums.length; i++) { + for (int j = 1; j < nums.length - i; j++) { + if (nums[j] < nums[j - 1]) { + isSwap = true; + int tmp = nums[j]; + nums[j] = nums[j - 1]; + nums[j - 1] = tmp; + } + + } + if (!isSwap) { + return nums; + } + isSwap = false; + } + return nums; + } + } + + class Solution1 { + /** + * 选择排序 + * 选择右边区间的最小值与左边替换 + * @param nums + * @return + */ + public int[] sortArray(int[] nums) { + for (int i = 0; i < nums.length; i++) { + int minIndex = i; + for (int j = i+1; j < nums.length; j++) { + if (nums[minIndex] > nums[j]) { + minIndex = j; + } + } + // 交换min与i + int tmp = nums[i]; + nums[i] = nums[minIndex]; + nums[minIndex] = tmp; + } + return nums; + } + } + + class Solution2 { + /** + * 插入排序 j不断往前插入替换到合适位置 + * @param nums + * @return + */ + public int[] sortArray(int[] nums) { + for (int i = 1; i < nums.length; i++) { + int j = i; + while (j > 0 && nums[j] < nums[j - 1]) { + // 交换j和j-1 + int tmp = nums[j]; + nums[j] = nums[j - 1]; + nums[j - 1] = tmp; + j--; + } + } + return nums; + } + } + + class SolutionQuickSort { + /** + * 插入排序 j不断往前插入替换到合适位置 + * + * + * @param nums + * @return + */ + public int[] sortArray(int[] nums) { + + + return nums; + } + + public void part(int[] nums, int start, int end) { + if (start > end) { + return; + } + + + + + + } + + } +} + +class MergeSort{ + static class Solution { + + // 归并排序 + public int[] sortArray(int[] nums) { + if (nums.length <= 1) { + return nums; + } + int mid = nums.length / 2; + int[] left = Arrays.copyOfRange(nums, 0, mid); + int[] right = Arrays.copyOfRange(nums, mid, nums.length); + left = sortArray(left); + right = sortArray(right); + return merge(left, right); + } + + public int[] merge(int[] left, int[] right) { + int[] res = new int[left.length + right.length]; + int leftIndex = 0; + int rightIndex = 0; + int index = 0; + while (leftIndex < left.length && rightIndex < right.length) { + if (left[leftIndex] < right[rightIndex]) { + res[index] = left[leftIndex]; + leftIndex++; + }else { + res[index] = right[rightIndex]; + rightIndex++; + } + index++; + } + while (leftIndex < left.length) { + res[index] = left[leftIndex]; + leftIndex++; + index++; + } + while (rightIndex < right.length) { + res[index] = right[rightIndex]; + rightIndex++; + index++; + } + return res; + } + + + + } +} + +class QuickSort{ + + /** + * 快速排序 + */ + static class Solution4 { + public int[] sortArray(int[] nums) { + + quickSort(nums, 0, nums.length-1); + return nums; + } + + public int[] quickSort(int[] nums, int left,int right){ + //如果左指针大于右指针,怎退出循环 + if(left > right){ + return null; + } + + //! 随机挑选一个幸运儿 + int q = new Random().nextInt(right - left + 1) + left; + swap(nums, right, q); + + int base = nums[left]; + int i = left; + int j = right; + while(i != j){ + //从右往左遍历,当右指针指向的元素大于等于基数时,j--。右指针持续向左移动 + while(nums[j]>=base && i < j){ + j--; + } + //从左往右遍历,当左指针指向的元素小于等于基数时,i++。左指针持续向右移动 + while(nums[i]<=base && i < j){ + i++; + } + //当左右两个指针停下来时,交换两个元素 + swap(nums, i, j); + + } + swap(nums,i,left); + quickSort(nums,left, i-1); + quickSort(nums,i+1,right); + return nums; + } + + + + public void swap(int[] nums, int index1, int indexB) { + int tmp = nums[index1]; + nums[index1] = nums[indexB]; + nums[indexB] = tmp; + } + } + +// class Solution11 { +// public int[] sortArray(int[] nums) { +// quick_sort(nums, 0, nums.length - 1); +// return nums; +// } +// +// private void quick_sort(int[] nums, int left, int right) { +// if (left >= right) { +// return; +// } +// +// +// int i = left; +// int j = right; +// //! 随机挑选一个幸运儿 +// int q = new Random().nextInt(right - left + 1) + left; +// swap(nums, right, q); +// +// while (i < j) { +// while (nums[i] <= nums[right] && i < j) { +// i++; +// } +// while (nums[right] >= nums[left] && i < j) { +// j--; +// } +// swap(nums, i, j); +// } +// +// swap(nums, i, right); +// +// +// quick_sort(nums, left, i - 1); +// quick_sort(nums, i + 1, right); +// } +// +// +// +// private void swap(int[] nums, int i, int j) { +// int temp = nums[i]; +// nums[i] = nums[j]; +// nums[j] = temp; +// } +// } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode92.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode92.java new file mode 100644 index 0000000..1ccda67 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode92.java @@ -0,0 +1,64 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/9/21 14:11 + * @注释 + */ +public class LeetCode92 { + + @Test + public void test() { + new Solution().reverseBetween(ListNode.listNodeFromArray(new int[]{1, 2, 3, 4, 5} + ), 1, 5).printList(); + } + + class Solution { + public ListNode reverseBetween(ListNode head, int left, int right) { + if (left == right) { + return head; + } + ListNode pre = new ListNode(-1, head); + ListNode tmpLeft = pre; + ListNode tmpRight = pre; + for (int i = 0; i < left - 1; i++) { + tmpLeft = tmpLeft.next; + tmpRight = tmpRight.next; + } + for (int i = 0; i < right - left + 2; i++) { + tmpRight = tmpRight.next; + } + + ListNode tmpNext = tmpLeft.next; + tmpLeft.next = reverse(null, tmpNext, right - left + 1); + + tmpNext.next = tmpRight; + + return pre.next; + } + + + public ListNode reverse(ListNode pre, ListNode after, int k) { + if (k == 0) { + return pre; + } + if (after == null) { + return pre; + } + ListNode tmp = after.next; + after.next = pre; + return reverse(after, tmp, k - 1); + } + + } + + @Test + public void test2() { + ListNode pre = ListNode.listNodeFromArray(new int[]{1, 2, 3}); + new Solution().reverse(null, pre, 3).printList(); + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode93.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode93.java new file mode 100644 index 0000000..6096a72 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode93.java @@ -0,0 +1,176 @@ +package cn.whaifree.leetCode.BackTracking; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/2/18 9:27 + * @注释 + */ +public class LeetCode93 { + + @Test + public void test() { + for (String restoreIpAddress : new Solution1().restoreIpAddresses("101023")) { + System.out.println(restoreIpAddress); + } + } + + class Solution { + + List res = new ArrayList<>(); + List path = new ArrayList<>(); + public List restoreIpAddresses(String s) { + backTracking(s, 0, 0); + return res; + } + + /** + * + * @param s + * @param start 递归开始标记 + * @param number 这是第几个切片,4个切片为一组有效返回 + */ + public void backTracking(String s, int start,int number) { + // 如果 第5个切片了,则存在多余的字符,直接return + if (number > 4) { + return; + } + + if (start >= s.length() && path.size() == 4) { + res.add(String.join(".", path)); + +// StringBuilder stringBuilder = new StringBuilder(); +// for (int i = 0; i < path.size() - 1; i++) { +// stringBuilder.append(path.get(i)).append("."); +// } +// stringBuilder.append(path.get(path.size() - 1)); +// res.add(stringBuilder.toString()); + return; + } + + + + + for (int i = start; i < s.length() ; i++) { + + if (isValid(s, start, i + 1)) { + + path.add(s.substring(start, i + 1)); + backTracking(s, i + 1, number + 1); + path.remove(path.size() - 1); + }else { + // 2565 256无效,那么2565直接就无效了 + break; + } + } + } + + public boolean isValid(String s, int start, int end) { + String substring = s.substring(start, end); + // 子串最多不超过3个字符 + if (substring.length() > 3 ) { + return false; + } + // “01”为非法,"0"为合法 + if (substring.length() != 1 && substring.startsWith("0")) { + return false; + } + int integer = Integer.parseInt(substring); + if (integer >= 0 && integer <= 255) { + return true; + } + return false; + } + + /** + * 通过char进行字符串转为int + * @param s + * @param start + * @param end + * @return + */ + private boolean isValid(StringBuilder s, int start, int end){ + if(start > end) + return false; + if(s.charAt(start) == '0' && start != end) + return false; + int num = 0; + for(int i = start; i <= end; i++){ + int digit = s.charAt(i) - '0'; + num = num * 10 + digit; + if(num > 255) + return false; + } + return true; + } + } + class Solution1 { + + List res = new ArrayList<>(); + List path = new ArrayList<>(); + public List restoreIpAddresses(String s) { + backTracking(s, 0); + return res; + } + + /** + * + * @param s + * @param start 递归开始标记 + */ + public void backTracking(String s, int start) { + + if (start >= s.length() && path.size() == 4) { + res.add(String.join(".", path)); + +// StringBuilder stringBuilder = new StringBuilder(); +// for (int i = 0; i < path.size() - 1; i++) { +// stringBuilder.append(path.get(i)).append("."); +// } +// stringBuilder.append(path.get(path.size() - 1)); +// res.add(stringBuilder.toString()); + return; + } + + + + + for (int i = start; i < s.length() ; i++) { + + if (isValid(s, start, i + 1)) { + + path.add(s.substring(start, i + 1)); + backTracking(s, i + 1); + path.remove(path.size() - 1); + }else { + // 2565 256无效,那么2565直接就无效了 + break; + } + } + } + + public boolean isValid(String s, int start, int end) { + String substring = s.substring(start, end); + // 子串最多不超过3个字符 + if (substring.length() > 3 ) { + return false; + } + // “01”为非法,"0"为合法 + if (substring.length() != 1 && substring.startsWith("0")) { + return false; + } + int integer = Integer.parseInt(substring); + if (integer >= 0 && integer <= 255) { + return true; + } + return false; + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode94.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode94.java new file mode 100644 index 0000000..e8d2504 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode94.java @@ -0,0 +1,204 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.ListNode; +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/15 19:29 + * @注释 + */ +public class LeetCode94 { + + + + + @Test + public void test() { + TreeNode root = TreeNode.constructTree(new Integer[]{1, 2, 3, 4}); + TreeNode.printTree(root); + + System.out.println(new Solution2().inorderTraversal(root)); + System.out.println(new Solution2().preorderTraversal(root)); + System.out.println(new Solution2().postorderTraversal(root)); + + + } + + class Solution { + List res = new LinkedList<>(); + + public List inorderTraversal(TreeNode root) { + if (root == null) { + return res; + } + inorder(root); + return res; + } + + public void inorder(TreeNode root) { + if (root == null) { + return; + } + inorder(root.left); + res.add(root.val); + inorder(root.right); + } + + } + + class Solution1 { + + + public List inorderTraversal(TreeNode root) { + + List list = new LinkedList (); + if (root == null) { + return list; + } + Deque stack = new LinkedList<>(); + + TreeNode index = root; + while (!stack.isEmpty() || index != null) { + // 不断左边加入,弹出获取右边的 + // 每次循环处理一次节点,左边,右边和中间 + if (index != null) { + stack.push(index); + index = index.left; + } else { + index = stack.pop(); + list.add(index.val); + index = index.right; + } + } + return list; + } + + } + + class Solution2 { + + + /** + * 不能 前后序统一 + * 因为中间节点是在中间,每次经过他都不能判断是否是第一次进入 + * - 如果增加一个标记,标记Null入栈,判断到null时就证明他是已经走过的节点 + * @param root + * @return + */ + public List inorderTraversal(TreeNode root) { + + List list = new LinkedList (); + if (root == null) { + return list; + } + Deque stack = new LinkedList<>(); + + stack.push(root); + /** + * 右边进栈,再左边进栈,中间用空指针标记 + */ + while (!stack.isEmpty()) { + TreeNode pop = stack.pop(); + // 这个if处理中间节点是否处理过 + if (pop != null) { + if(pop.right!=null) stack.push(pop.right); + // 此处null 为标记已经处理过的节点,下次遇到这个节点就可以直接输出了 + stack.push(pop); + stack.push(null); + if (pop.left!=null) stack.push(pop.left); + } else { + TreeNode pop1 = stack.pop(); + list.add(pop1.val); + } + + } + return list; + } + + + /** + * 不能 前后序统一 + * 因为中间节点是在中间,每次经过他都不能判断是否是第一次进入 + * - 如果增加一个标记,标记Null入栈,判断到null时就证明他是已经走过的节点 + * @param root + * @return + */ + public List preorderTraversal(TreeNode root) { + + List list = new LinkedList (); + if (root == null) { + return list; + } + Deque stack = new LinkedList<>(); + + stack.push(root); + /** + * 右边进栈,再左边进栈,中间用空指针标记 + */ + while (!stack.isEmpty()) { + TreeNode pop = stack.pop(); + + if (pop != null) { + // 变更这三个的顺序就能 前中后序 + if (pop.right != null) { + stack.push(pop.right); + } + if (pop.left != null) { + stack.push(pop.left); + } + stack.push(pop); + stack.push(null); + } else { + TreeNode pop1 = stack.pop(); + list.add(pop1.val); + } + + } + return list; + } + + public List postorderTraversal(TreeNode root) { + + List list = new LinkedList (); + if (root == null) { + return list; + } + Deque stack = new LinkedList<>(); + + stack.push(root); + /** + * 右边进栈,再左边进栈,中间用空指针标记 + */ + while (!stack.isEmpty()) { + TreeNode pop = stack.pop(); + + if (pop != null) { + + stack.push(pop); + stack.push(null); + if (pop.right != null) { + stack.push(pop.right); + } + if (pop.left != null) { + stack.push(pop.left); + } + + } else { + TreeNode pop1 = stack.pop(); + list.add(pop1.val); + } + + } + return list; + + } + + } + + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode946.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode946.java new file mode 100644 index 0000000..ba23bec --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode946.java @@ -0,0 +1,37 @@ +package cn.whaifree.leetCode.Stack; + +import org.junit.Test; + +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/21 19:38 + * @注释 + */ +public class LeetCode946 { + + @Test + public void test() { + new Solution().validateStackSequences(new int[]{1, 2, 3, 4, 5}, new int[]{4, 5, 3, 2, 1}); + } + class Solution { + public boolean validateStackSequences(int[] pushed, int[] popped) { + return success(pushed, popped); + } + + public boolean success(int[] input, int[] output) { + LinkedList stack = new LinkedList<>(); + int index = 0; + for (int i : input) { + stack.push(i); + while (!stack.isEmpty() && stack.peek() == output[index]) { + index++; + stack.pop(); + } + } + return stack.isEmpty(); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode96.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode96.java new file mode 100644 index 0000000..320b890 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode96.java @@ -0,0 +1,64 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/11 13:08 + * @注释 + */ +public class LeetCode96 { + + @Test + public void test() { + int n = 5; + int result = new Solution().numTrees(n); + System.out.println(result); + } + + class Solution { + + /** + * + * dp[i] 表示有两个节点的可能数 + * + * 以n=3举例,二叉搜索树 + * 可能的方案: + * i表示以i为头节点 + * 1. 以1为头结点 右边2个子树+左边0个子树 + * 2. 以2为头节点 右边1个子树+左边1个子树 + * 3. 以3为头节点 右边0个子树+左边2个子树 + * + * dp[3] = 以1为头 dp[2] * dp[0] + + * 以2为头 dp[1] * dp[1] + + * 以3为头 dp[0] * dp[2] + * + * dp[i] = dp[i-1] * dp[0] + + * dp[i-2] * dp[1] + + * dp[i-3] * dp[02] + + * .... + * dp[0] * dp[i-1] + * @param n + * @return + */ + public int numTrees(int n) { + + if (n <= 1) { + return 1; + } + + int[] dp = new int[n + 1]; + dp[0] = 1; + dp[1] = 1; + dp[2] = 2; + for (int i = 3; i <= n; i++) { + for (int j = 1; j <= i; j++) { + dp[i] += (dp[i - j] * dp[j - 1]); + } + } + + return dp[n]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode968.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode968.java new file mode 100644 index 0000000..a4866b0 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode968.java @@ -0,0 +1,66 @@ +package cn.whaifree.leetCode.Greedy; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/6 16:34 + * @注释 + */ +public class LeetCode968 { + + @Test + public void test() { + System.out.println(new Solution().minCameraCover(TreeNode.constructTreeByArray(1, 2, null, 2, 4, 6))); + } + + + /** + * 我们分别有三个数字来表示: + * + * 0:该节点无覆盖 + * 1:本节点有摄像头 + * 2:本节点有覆盖 + */ + class Solution { + + int res = 0; + public int minCameraCover(TreeNode root) { + + // 根节点 + if (travel(root) == 0) { + res++; + } + return res; + } + + public int travel(TreeNode root) { + + if (root == null) { + return 2; + } + + + int left = travel(root.left); + int right = travel(root.right); + + // 左右节点都有覆盖 + if (left == 2 && right == 2) return 0; + + //左或右无覆盖,本节点要增加摄像头 + if (left == 0 || right == 0) { + res++; + return 1; + } + + // 左或右有摄像头,本节点被覆盖 + if (left == 1 || right == 1) { + return 2; + } + + return -1; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode977.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode977.java new file mode 100644 index 0000000..fd6652a --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode977.java @@ -0,0 +1,152 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * 977. 有序数组的平方 + * + * 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 + * + * 示例 1: + * + * 输入:nums = [-4,-1,0,3,10] + * 输出:[0,1,9,16,100] + * 解释:平方后,数组变为 [16,1,0,9,100] + * 排序后,数组变为 [0,1,9,16,100] + * + * 示例 2: + * + * 输入:nums = [-7,-3,2,3,11] + * 输出:[4,9,9,49,121] + * + * 提示: + * + * 1 <= nums.length <= 104 + * -104 <= nums[i] <= 104 + * nums 已按 非递减顺序 排序 + * + * + * 进阶: + * + * 请你设计时间复杂度为 O(n) 的算法解决本问题 + * + * 更多挑战 + * 88. 合并两个有序数组 + * 360. 有序转化数组 + */ +public class LeetCode977 { + + /** + * 找到第一个左边小于0,右边大于等于0的点 + * 左右两个指针 + * 平方后必然是,【递减 0 递增】 + * [-3,-1,0,2,5] + * [9,1,0,4,25] + * + * 让左边的循环插入到右边合适的位置 + * @param nums + * @return + */ + public int[] sortedSquares(int[] nums) { + + int middle = nums.length; + for (int i = 0; i < nums.length; i++) { + if (nums[i] >= 0) { + middle = i; + break; + } + } + // 此时就有两个数组了 + // [0,middle-1] 为递减的 + // [middle, length-1] 为递增的 + int[] ints = new int[nums.length]; + int leftIndex = middle -1; + int rightIndex = middle; + int intIndex = 0; + while (leftIndex >= 0 && rightIndex < nums.length) { + if (nums[leftIndex] * nums[leftIndex] < nums[rightIndex] * nums[rightIndex]) { + ints[intIndex++] = nums[leftIndex] * nums[leftIndex]; + leftIndex--; + } else { + ints[intIndex++] = nums[rightIndex] * nums[rightIndex]; + rightIndex++; + } + } + + while (leftIndex >= 0) { + ints[intIndex++] = nums[leftIndex] * nums[leftIndex]; + leftIndex--; + } + while (rightIndex <= nums.length-1) { + ints[intIndex++] = nums[rightIndex] * nums[rightIndex]; + rightIndex++; + } + + return ints; + } + + + /** + * 不考虑0的双指针 + * @param nums + * @return + */ + public int[] sortedSquares1(int[] nums) { + int[] ints = new int[nums.length]; + + int left = 0; + int right = nums.length - 1; + int index = 0; + while (left <= right) { + if (nums[left] * nums[left] < nums[right] * nums[right]) { + ints[index++] = nums[right] * nums[right]; + right--; + } else { + ints[index++] = nums[left] * nums[left]; + left++; + } + } + + // 逆序 + int value = 0; + for (int i = 0; i < ints.length / 2; i++) { + value = ints[i]; + ints[i] = ints[ints.length - i - 1]; + ints[ints.length - 1 - i] = value; + } + + return ints; + } + + public int[] sortedSquares2(int[] nums) { + int[] ints = new int[nums.length]; + + int left = 0; + int right = nums.length - 1; + // 存入新数组的索引,从大往小存 + int index = nums.length - 1; + while (left <= right) { + // 负数 + 正数 > 0 则 |负数| < |正数| + if (nums[left] + nums[right] > 0) { + ints[index--] = nums[right] * nums[right]; + right--; + } else { + ints[index--] = nums[left] * nums[left]; + left++; + } + } + + + return ints; + } + + + @Test + public void test() { + int[] ints = sortedSquares2(new int[]{-3,-1,4,10}); + for (int i = 0; i < ints.length; i++) { + System.out.println(ints[i]); + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode98.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode98.java new file mode 100644 index 0000000..a7d0d9a --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode98.java @@ -0,0 +1,61 @@ +package cn.whaifree.leetCode.Tree; + +import cn.whaifree.leetCode.model.Node; +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/1/28 16:05 + * @注释 + */ +public class LeetCode98 { + + + @Test + public void test() { + System.out.println(new Solution().isValidBST(TreeNode.constructTreeByArray(5,4,6,null,null,3,7))); + } + + class Solution { + + + long compare = Long.MIN_VALUE; + boolean res = true; + + public boolean isValidBST(TreeNode root) { + isValid(root); + return res; + } + public void isValid(TreeNode root) { + + if (root == null) { + return; + } + isValid(root.left); + if (root.val <= compare) { + res = false; + return; + } + compare = root.val; + isValid(root.right); + } + + } + + class Solution1 { + public boolean isValidBST(TreeNode root) { + return isValid(root, Integer.MIN_VALUE, Integer.MAX_VALUE); + } + public boolean isValid(TreeNode root,int min,int max) { + if (root == null) { + return true; + } + if (root.val <= min || root.val >= max) { + return false; + } + return isValid(root.left, min, root.val) && isValid(root.right, root.val, max); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode989.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode989.java new file mode 100644 index 0000000..6005480 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode989.java @@ -0,0 +1,98 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/20 12:41 + * @注释 + */ +public class LeetCode989 { + + @Test + public void test() throws IOException { + + // 创建一个RandomAccessFile对象,用于读取指定路径下的文件 + RandomAccessFile reader = new RandomAccessFile("D:\\Downloads\\a8d88f60-603e-405f-b67b-6774dd14a507.jpg", "r"); + // 获取文件通道 + FileChannel channel = reader.getChannel(); + // 分配读取指定文件大小的缓冲区 + ByteBuffer buffer = ByteBuffer.allocate((int) reader.length()); + // 从文件通道中读取数据到缓冲区 + channel.read(buffer); + + + // 创建一个RandomAccessFile对象,用于将缓冲区的数据写入到新的文件 + RandomAccessFile writer = new RandomAccessFile("D:\\Downloads\\new_file.jpg", "rw"); + // 获取文件通道 + FileChannel newChannel = writer.getChannel(); + // 将缓冲区的数据写入到新的文件 + newChannel.write(buffer); + // 关闭文件通道 + channel.close(); + newChannel.close(); + + byte[] array = ByteBuffer.allocate(8).putDouble(1.0).array(); + System.out.println(Arrays.toString(array)); + + int[] num = {9,9,9,9,9,9,9,9,9,9}; + int k = 1; + Solution solution = new Solution(); + List res = solution.addToArrayForm(num, k); + System.out.println(res); + } + + class Solution { + public List addToArrayForm(int[] num, int k) { + int indexA = num.length - 1; + int m = k; + boolean flag = false; + LinkedList res = new LinkedList<>(); + while (indexA >= 0 && m > 0) { + int sum = num[indexA] + m % 10; + sum = flag ? sum + 1 : sum; + flag = sum >= 10; + + res.addFirst(sum % 10); + + indexA--; + m /= 10; + } + + if (indexA < 0 && m <= 0 && flag) { + res.addFirst(1); + return res; + } + + while (indexA >= 0) { + int sum = num[indexA]; + sum = flag ? sum + 1 : sum; + flag = sum >= 10; + res.addFirst(sum % 10); + indexA--; + } + + while (m>0) { + int sum = m % 10; + sum = flag ? sum + 1 : sum; + flag = sum >= 10; + res.addFirst(sum % 10); + m /= 10; + } + if (flag) { + res.addFirst(1); + } + return res; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode_0207_IntersectionNode.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode_0207_IntersectionNode.java new file mode 100644 index 0000000..f309afa --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/LeetCode_0207_IntersectionNode.java @@ -0,0 +1,142 @@ +package cn.whaifree.leetCode.LinkedList; + +import cn.whaifree.leetCode.model.ListNode; +import org.junit.Test; + +public class LeetCode_0207_IntersectionNode { + + @Test + public void test() { + Solution1 solution = new Solution1(); + ListNode headA = ListNode.listNodeFromArray(new int[]{1, 2, 3}); + ListNode headB = ListNode.listNodeFromArray(new int[]{5}); + ListNode listNode = new ListNode(10); + + ListNode nodeA = headA; + while (nodeA.next != null) { + nodeA = nodeA.next; + } + nodeA.next = listNode; + + ListNode nodeB = headB; + while (nodeB.next != null) { + nodeB = nodeB.next; + } + nodeB.next = listNode; + + ListNode intersectionNode = solution.getIntersectionNode(headA, headB); + if (intersectionNode != null) { + System.out.println(intersectionNode.val); + } else { + System.out.println("null"); + } + + } + + /** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ + class Solution { + + /** + * 先找到长的,让长的指针移动到同步 + * @param headA + * @param headB + * @return + */ + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + int lengthA = getLength(headA); + int lengthB = getLength(headB); + + if (lengthB < lengthA) { + int sub = lengthA - lengthB; + ListNode indexA = headA; + ListNode indexB = headB; + for (int i = 0; i < sub; i++) { + indexA = indexA.next; + } + + while (indexA != null) { + if (indexA == indexB) { + return indexA; + } + indexA = indexA.next; + indexB = indexB.next; + } + + } else { + int sub = lengthB - lengthA; + ListNode indexA = headA; + ListNode indexB = headB; + for (int i = 0; i < sub; i++) { + indexB = indexB.next; + } + while (indexA != null) { + if (indexA == indexB) { + return indexA; + } + indexA = indexA.next; + indexB = indexB.next; + } + } + return null; + } + + int getLength(ListNode head) { + int length = 0; + ListNode index = head; + while (index != null) { + index = index.next; + length++; + } + return length; + } + } + + class Solution1 { + + /** + * 两个链表交替双指针 + * + * - + * + * @param headA + * @param headB + * @return + */ + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + + if (headA == null || headB == null) { + return null; + } + + ListNode indexA = headA; + ListNode indexB = headB; + // 链表没有公共节点的时候, indexA和b都为null,会跳出循环 + while (indexB != indexA) { + + if (indexA == null) { + indexA = headB; + }else { + indexA = indexA.next; + } + + if (indexB == null) { + indexB = headA; + }else { + indexB = indexB.next; + } + } + return indexA; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/leetCode/Stock.java b/ForJdk17/src/main/java/cn/whaifree/leetCode/Stock.java new file mode 100644 index 0000000..1bce9ec --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/leetCode/Stock.java @@ -0,0 +1,349 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * + * 买卖股票的最佳时机 四题+变形 + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/12 11:46 + * @注释 + */ +public class Stock { + + @Test + public void test() + { + System.out.println(new LeetCode188_.Solution().maxProfit(2, new int[]{3,2,6,5,0,3})); + } +} + +class LeetCode188_{ + + static class Solution { + public int maxProfit(int k, int[] prices) { + // dp[i][j] 表示第i天交易第k次的最大收益 + // dp[i][1] 表示第i天第 1/2 +1 次持有的最大手头 + // dp[i][0] 表示第i天第 0/2 +1次未持有的最大手头 + + // dp[i][0] = max dp[i-1][0] dp[i-1][1]+prices[i] + // dp[i][1] = max dp[i-1][1] dp[i-1][0]-prices[i] + // dp[i][2] = max dp[i-1][2] dp[i-1][1]+prices[i] + // dp[i][3] = max dp[i-1][3] dp[i-1][2]-prices[i] + + int[][] dp = new int[prices.length][k * 2 + 1]; + // 未持有 初始化 + for (int i = 1; i <= k * 2; i += 2) { + dp[0][i] = -prices[0]; + } + for (int i = 1; i < prices.length; i++) { + for (int j = 0; j < k ; j++) { + int indexJ = 2 * j + 1; + dp[i][indexJ] = Math.max(dp[i - 1][indexJ], dp[i - 1][indexJ - 1] - prices[i]); + dp[i][indexJ + 1] = Math.max(dp[i - 1][indexJ + 1], dp[i - 1][indexJ] + prices[i]); + } + } + return dp[prices.length - 1][k * 2]; + + // 假设k=2 +// int[][] dp = new int[prices.length][5]; +// // 4种状态 1 3 表示持有 +// dp[0][1] = -prices[0]; +// dp[0][3] = -prices[0]; +// for (int i = 1; i < prices.length; i++) { +// dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); +// dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]); +// dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]); +// dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]); +// } +// return dp[prices.length - 1][4]; + } + } +} + +class LeetCode123_ { + + static class Solution { + /** + * 最多可以完成 两笔 交易。 + * 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 + * + * dp[i][j] 表示第i天 状态j的最大手头有的钱 + * 一天一共就有五个状态, + * 0. 没有操作 (其实我们也可以不设置这个状态) + * + * 1. 第一次持有股票(第i天持有第一次股票) + * - 第i-1天就持有这个第一次股票 dp[i][1] = dp[i-1][1] + * - 第i天买入这个股票 dp[i][1] = dp[i-1][0] - prices[i] + * 2. 第一次不持有股票 + * - 第i天卖出 dp[i][2] = dp[i-1][1]+price[i] + * - 第i-1天就不持有第一支 dp[i][2] = dp[i-1][2] + * 3. 第二次持有股票 + * - 第i天买入第二支 dp[i][3] = dp[i-1][2] - price[i] + * - i-1天就持有 dp[i][3] = dp[i-1][3] + * 4. 第二次不持有股票 + * - 第i天卖出第二支 dp[i][4] = dp[i-1][3] + price[i] + * - 第i-1天就没有 dp[i][4] = dp[i-1][4] + * + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + int[][] dp = new int[prices.length][5]; + dp[0][1] = -prices[0]; + dp[0][3] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + // 没有操作,手上的现金自然就是0 + // dp[i][1] = Math.max(dp[i - 1][1], 0 - prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); + dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]); + dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]); + dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]); + } + return dp[prices.length - 1][4]; + } + + public int maxProfit1(int[] prices) { + int[] dp = new int[5]; + dp[1] = -prices[0]; + dp[3] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[1] = Math.max(dp[1], dp[0] - prices[i]); + dp[2] = Math.max(dp[2], dp[1] + prices[i]); + dp[3] = Math.max(dp[3], dp[2] - prices[i]); + dp[4] = Math.max(dp[4], dp[3] + prices[i]); + } + return dp[4]; + } + } + +} + +class LeetCode122_{ + + static class Solution { + public int maxProfit(int[] prices) { + // 只要递增就买入 + + int left = 0; + int right = 1; + int profit = 0; + while (right < prices.length) { + while (left < right && prices[left] > prices[right]) { + left++; + } + if (prices[left] < prices[right]) { + profit += (prices[right] - prices[left]); + left = right; + } + right++; + } + return profit; + } + + } + + static class Solution1 { + public int maxProfit(int[] prices) { + /** + * dp + * dp[i][0] 表示 i天没有股票的时候 手头的现金 + * - i-1就没有 dp[i-1][0] + * - i天刚刚卖 dp[i-1][1]+price[i] + * dp[i][1] 表示 i天有股票的时候 手头的现金 + * - i-1就有 dp[i-1][1] + * - 刚刚买入 dp[i-1][0] - price[i] + */ + int[][] dp = new int[prices.length][2]; + dp[0][1] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); + } + return dp[prices.length - 1][0]; + } + } +} + +class LeetCode121_ { + static class Solution { + public int maxProfit(int[] prices) { + // 最低点买入,最高点卖出 + int min = Integer.MAX_VALUE; + int res = 0; + for (int price : prices) { + min = Math.min(min, price); + res = Math.max(res, price - min); + } + return res; + } + } + + + static class Solution2 { + public int maxProfit(int[] prices) { + int[][] dp = new int[prices.length][2]; + // 本题只能交易一次 + // dp[i][0] 表示第i天手里没有股票的 手里的现金 + // - 第i天卖出 dp[i][0]=dp[i-1][1]+prices[i] + // - 第i-1天就没有股票 dp[i][0]=dp[i-1][0] + // dp[i][1] 表示第i天手里有股票的 手里的现金 + // - 第i天买入 dp[i][1] = - prices[i] + // - 第i-1天就有 dp[i][1] = dp[i-1][1] + dp[0][1] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], - prices[i]); + } + + return dp[prices.length - 1][0]; + } + } + + static class Solution3 { + public int maxProfit(int[] prices) { + int[] dp = new int[2]; + // 本题只能交易一次 + // dp[i][0] 表示第i天手里没有股票的 手里的现金 + // - 第i天卖出 dp[i][0]=dp[i-1][1]+prices[i] + // - 第i-1天就没有股票 dp[i][0]=dp[i-1][0] + // dp[i][1] 表示第i天手里有股票的 手里的现金 + // - 第i天买入 dp[i][1] = - prices[i] + // - 第i-1天就有 dp[i][1] = dp[i-1][1] + dp[1] = -prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[0] = Math.max(dp[0], dp[1] + prices[i]); + dp[1] = Math.max(dp[1], - prices[i]); + } + + return dp[0]; + } + } +} + +class LeetCode309_ { + + class Solution { + public int maxProfit(int[] prices) { + // 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 + /** + * boolean[] flag + * flag[i] 表示第i天是否卖出获得最大利润 + * + * s2 s3 + * dp[i][0] 表示 第i天手里不持有股票,i-1也不持有,表明在i-1之前卖出股票 手里有的钱 + * - i不持有 i-1 不持有 i-2不持有 dp[i-2][0] + * - i不持有 i-1 不持有 i-2持有,i-1卖出 dp[i-2][2] + prices[i-1] + * + * s4 + * dp[i][1] 表示i不持有,i-1持有 手里有的钱 + * - 今天为冷冻期 i卖出 dp[i-1][2] + prices[i] + * + * s1 + * dp[i][2] 表示 第i天持有股票 手里有的钱 + * - i-1有 dp[i-1][2] + * - 前一天是冷冻期 i和i-1都不持有 dp[i-1][0] - price[i] + * - 当天是冷冻期 i不持有 i-1持有 dp[i-1][1] - price[i] + * + */ + int[][] dp = new int[prices.length][2]; + boolean[] flag = new boolean[prices.length]; + + for (int i = 1; i < prices.length; i++) { + if (dp[i - 1][0] > dp[i - 1][1] + prices[i]) { + dp[i][0] = dp[i - 1][0]; + }else { + dp[i][0] = dp[i - 1][1] + prices[i]; + flag[i] = true; + } + +// if + + } + return 1; + + } + } + + class Solution1 { + /** + * 状态: + * 1. 持有dp[i][0] + * - i-1就持有 dp[i-1][0] + * - 当天买入 + * - 前一天是冷冻期 dp[i-1][3] - price[i] + * - 前一天不是冷冻期 dp[i-1][1] - price[i] + * 2. 不持有 + * - i-1就不持有,i-2或之前卖出过股票 dp[i][1] + * - i-1不持有 i-2不持有 dp[i-1][1] + * - i-1不持有 i-2持有,表明i-1卖出了 dp[i-1][2] + price[i] + * - 今天卖出 dp[i][2] + * - dp[i-1][0]+price[i] + * + * 3. 冷冻dp[i][3] + * - i-1卖出 dp[i-1][2] + * @param prices + * @return + */ + public int maxProfit(int[] prices) { + int[][] dp = new int[prices.length][4]; + dp[0][0] -= prices[0]; + for (int i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], Math.max(dp[i - 1][3] - prices[i], dp[i - 1][1] - prices[i])); + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][3]); + dp[i][2] = dp[i - 1][0] + prices[i]; + dp[i][3] = dp[i - 1][2]; + } + return Math.max( + dp[prices.length - 1][3], + Math.max( + dp[prices.length - 1][1], + dp[prices.length - 1][2] + ) + ); + } + + /** + * dp[i][0] 表示第i天手里没有股票的 手里的现金 + * 1. 当天卖出 dp[i-1][1] + prices[i] + * 2. i-1天就没有 + * dp[i-1][0] + * dp[i][1] 表示第i天手里有股票的 手里的现金 + * 1. 刚刚买入(考虑2天前手里没有股票,i-1天为冷冻期) dp[i-2][0] - prices[i] + * 2. i-1就持有 dp[i-1][1] + * + * 初始化 + * dp[0][0] = 0 + * dp[0][1] = -prices[0] + * dp[1][0] = Math.max(dp[0][0], dp[0][1] + prices[0]); + * dp[1][1] = Math.max(dp[0][1], dp[0][0]-prices[0]); + * + * @param prices + * @return + */ + public int maxProfit1(int[] prices) { + if(prices.length==1){ + return 0; + } + int[][] dp = new int[prices.length][2]; + dp[0][0] = 0; + dp[0][1] = -prices[0]; + dp[1][0] = Math.max(dp[0][0], dp[0][1] + prices[1]); + dp[1][1] = Math.max(dp[0][1], dp[0][0] - prices[1]); + for (int i = 2; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]); + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 2][0] - prices[i]); + } + return dp[prices.length - 1][0]; + } + + + + } + public static void main(String[] args) { + int[] prices = new int[]{1, 2, 3, 0, 2}; + System.out.println(new LeetCode309_().new Solution1().maxProfit1(prices)); + } +} + diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode115.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode115.java new file mode 100644 index 0000000..4e94e3b --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode115.java @@ -0,0 +1,56 @@ +package cn.whaifree.redo.redo_all_241016; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 12:00 + * @注释 + */ +public class LeetCode115 { + + class Solution { + /** + * + * dp[i][j] 表示s的 (以i-1为结尾的字符串)(的子序列) 在t的0-j中出现的个数 + * + * - 用本格 + * - 不用本格 + * + * ‘’ b a g + * ‘’ 1 0 0 0 + * b 1 1 0 0 + * a 1 1 1 0 + * b 1 2 1 0 + * g 1 2 1 1 + * b 1 3 1 1 + * a 1 3 4 1 用这个的a,使用dp[i-1][j-1] 表示前面所有匹配的次数; 不用这个a,使用已经匹配好的次数 dp[i-1][j] + * g 1 3 4 5 + * + * @param s + * @param t + * @return + */ + public int numDistinct(String s, String t) { + + int[][] dp = new int[s.length() + 1][t.length() + 1]; + + for (int i = 0; i <= s.length(); i++) { + dp[i][0] = 1; + } + + for (int i = 1; i <= s.length(); i++) { + for (int j = 1; j <= t.length(); j++) { + if (s.charAt(i - 1) == t.charAt(j - 1)) { + // 之前已经匹配的个数 dp[i - 1][j] + // 前面都匹配,还差这个没匹配 dp[i - 1][j - 1] + dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; + }else { + dp[i][j] = dp[i - 1][j]; + } + } + } + return dp[s.length()][t.length()]; + } + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode128.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode128.java new file mode 100644 index 0000000..7d643d1 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode128.java @@ -0,0 +1,37 @@ +package cn.whaifree.redo.redo_all_241016; + +import java.util.HashSet; +import java.util.Set; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 15:00 + * @注释 + */ +public class LeetCode128 { + + class Solution { + public int longestConsecutive(int[] nums) { + Set set = new HashSet<>(); + for (int num : nums) { + set.add(num); + } + + int res = 0; + for (int num : set) { + if (!set.contains(num - 1)) { + int currentNum = num; + int currentLength = 1; + while (set.contains(currentNum + 1)) { + currentNum++; + currentLength++; + } + res = Math.max(res, currentLength); + } + } + + return res; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode139.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode139.java new file mode 100644 index 0000000..6210bab --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode139.java @@ -0,0 +1,70 @@ +package cn.whaifree.redo.redo_all_241016; + +import org.junit.Test; + +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 15:08 + * @注释 + */ +public class LeetCode139 { + + @Test + public void test() { + String s = "applepenapple"; + List wordDict = List.of("apple", "pen"); + Solution solution = new Solution(); + boolean result = solution.wordBreak(s, wordDict); + System.out.println(result); + } + + + class Solution { + /** + * + * 无穷背包 + * + * 从WordDict中任选(无限数量),能否凑齐s中0-j这个子串 + * + * + * '' a p p l e p e n a p p l e + * '' + * apple 1 0 0 0 0 1 0 0 0 0 0 0 0 1 + * pen 1 0 0 0 0 1 0 0 1 0 0 0 0 1 + * + * 最好用一维数组,因为后面的判断需要前面的所有判断(后一个apple需要判断之前这k个字符能否凑出来a p p l e p e n ,即需要保证一列为true) + * + * + * @param s + * @param wordDict + * @return + */ + public boolean wordBreak(String s, List wordDict) { + + boolean[] dp = new boolean[s.length() + 1]; + + + dp[0] = true; + + for (int i = 1; i <= s.length() + 1; i++) { + for (int j = 1; j <= wordDict.size(); j++) { + String word = wordDict.get(j - 1); + if (i > word.length()) { + String sub = s.substring(i - word.length() - 1, i - 1); + if (sub.equals(word) && dp[i - word.length() - 1]) { + dp[i - 1] = true; + } else { + dp[i - 1] = dp[i - 1]; + } + } + } + } + + + return dp[s.length()]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode210.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode210.java new file mode 100644 index 0000000..6667a95 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode210.java @@ -0,0 +1,70 @@ +package cn.whaifree.redo.redo_all_241016; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 17:56 + * @注释 + */ +public class LeetCode210 { + @Test + public void test() { + int numCourses = 4; + int[][] prerequisites = {{1, 0}, {2, 0}, {3, 1}, {3, 2}}; + Solution solution = new Solution(); + int[] result = solution.findOrder(numCourses, prerequisites); + System.out.println(Arrays.toString(result)); + } + + class Solution { + /** + * pre[i][j] j->i + * + * @param numCourses + * @param prerequisites + * @return + */ + public int[] findOrder(int numCourses, int[][] prerequisites) { + // 统计每个节点所有 起始的边 + int[] inGre = new int[numCourses]; + Map> outLine = new HashMap<>(); + for (int[] prerequisite : prerequisites) { + int in = prerequisite[1]; // end + if (!outLine.containsKey(in)) { + outLine.put(in, new ArrayList<>()); + } + outLine.get(in).add(prerequisite[0]); // start + inGre[prerequisite[0]]++; // 统计每个节点的入度 + } + + Deque queue = new LinkedList<>(); + // 找到入度为0的节点 + for (int i = 0; i < inGre.length; i++) { + if (inGre[i] == 0) { + queue.offer(i); + } + } + + List res = new ArrayList<>(); + while (!queue.isEmpty()) { + Integer pop = queue.pop(); + res.add(pop); + // 表示选课 + List out = outLine.get(pop); + if (out != null) { + for (Integer i : out) { + inGre[i]--; + if (inGre[i] == 0) { + queue.offer(i); + } + } + } + } + return res.size() == numCourses ? res.stream().mapToInt(Integer::intValue).toArray() : new int[0]; + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode6.java b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode6.java new file mode 100644 index 0000000..2e6aad5 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/redo/redo_all_241016/LeetCode6.java @@ -0,0 +1,63 @@ +package cn.whaifree.redo.redo_all_241016; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 10:29 + * @注释 + */ +public class LeetCode6 { + + @Test + public void test() { + String s = "AB"; + int numRows = 1; + String res = new Solution().convert(s, numRows); + System.out.println(res); + } + + class Solution { + public String convert(String s, int numRows) { + if (numRows == 1) { + return s; + } + List result = new ArrayList<>(); + for (int i = 0; i < numRows; i++) { + result.add(new StringBuilder()); + } + + + int index = 0; + boolean down = true; + for (int i = 0; i < s.toCharArray().length; i++) { + result.get(index).append(s.charAt(i)); + if (down) { + if (index == numRows - 1) { + down = false; + index--; + }else { + index++; + } + }else { + if (index == 0) { + down = true; + index++; + }else { + index--; + } + } + } + + StringBuilder res = new StringBuilder(); + for (StringBuilder sb : result) { + res.append(sb.toString()); + } + return res.toString(); + } + } +} diff --git a/ForJdk17/src/main/java/cn/whaifree/tech/DateDemo/DateDemo.java b/ForJdk17/src/main/java/cn/whaifree/tech/DateDemo/DateDemo.java new file mode 100644 index 0000000..56e9511 --- /dev/null +++ b/ForJdk17/src/main/java/cn/whaifree/tech/DateDemo/DateDemo.java @@ -0,0 +1,88 @@ +package cn.whaifree.tech.DateDemo; + +import org.junit.Test; + +import java.sql.*; +import java.time.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/10/27 18:45 + * @注释 + */ +public class DateDemo { + + + @Test + public void test() { + LocalDateTime now = LocalDateTime.now(); + System.out.println(now); + + ZonedDateTime zonedDateTime = ZonedDateTime.now(); // 获取当前时区的时间 + System.out.println(zonedDateTime); + + // 切换时区到其他地方 美国 + ZonedDateTime zonedDateTime1 = zonedDateTime.withZoneSameInstant(java.time.ZoneId.of("America/New_York")); + System.out.println(zonedDateTime1); + } + + /** + * + + CREATE TABLE time_demo ( + id INT PRIMARY KEY AUTO_INCREMENT, + datetime_column DATETIME, + timestamp_column TIMESTAMP, + date_column DATE, + time_column TIME, + year_column YEAR + ); + + * @throws SQLException + */ + @Test + public void testSQLDate() throws SQLException { + Connection connection = null; + try { + Class.forName("com.mysql.cj.jdbc.Driver"); + connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test_tranc", "root", "123456"); + } catch (SQLException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + PreparedStatement pstmt = connection.prepareStatement("INSERT INTO time_demo (datetime_column, timestamp_column, date_column, time_column, year_column) VALUES (?, ?, ?, ?, ?)"); + + + // 使用当前的日期和时间 + LocalDateTime currentDateTime = LocalDateTime.now(); + LocalDate currentDate = LocalDate.now(); + LocalTime currentTime = LocalTime.now(); + Year currentYear = Year.now(); + + // 设置参数 + pstmt.setTimestamp(1, Timestamp.valueOf(currentDateTime)); // DATETIME + pstmt.setTimestamp(2, Timestamp.valueOf(currentDateTime)); // TIMESTAMP + pstmt.setDate(3, Date.valueOf(currentDate)); // DATE + pstmt.setTime(4, Time.valueOf(currentTime)); // TIME + pstmt.setInt(5, currentYear.getValue());// YEAR + pstmt.execute(); + + // 如果要要存储“公元1年1月1日11点11分”,只能使用MySQL的DATETIME类型 + // SET sql_mode = 'ALLOW_INVALID_DATES'; 在MySQL中允许存储更早的日期。 + // + // pstmt.setTimestamp(1, Timestamp.valueOf("1911-01-01 11:11:11")); // DATETIME + + ResultSet resultSet = connection.createStatement().executeQuery("SELECT * FROM time_demo"); + while (resultSet.next()) { + System.out.println(resultSet.getTimestamp("datetime_column")); + System.out.println(resultSet.getTimestamp("timestamp_column")); + System.out.println(resultSet.getDate("date_column")); + System.out.println(resultSet.getTime("time_column")); + System.out.println(resultSet.getInt("year_column")); + } + + } + +} diff --git a/ForJdk17/src/main/java/cn/whaifree/test/byteStream.java b/ForJdk17/src/main/java/cn/whaifree/test/byteStream.java index 1ca4868..6702002 100644 --- a/ForJdk17/src/main/java/cn/whaifree/test/byteStream.java +++ b/ForJdk17/src/main/java/cn/whaifree/test/byteStream.java @@ -1,6 +1,8 @@ package cn.whaifree.test; -import cn.whaifree.leetCode.Hash.LeetCode1; + + +import cn.whaifree.redo.redoAll.LeetCode11; import java.io.*; @@ -15,24 +17,24 @@ public class byteStream { public static void main(String[] args) throws IOException, ClassNotFoundException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream1 = new ObjectOutputStream(out); - objectOutputStream1.writeObject(new LeetCode1()); + objectOutputStream1.writeObject(new LeetCode11()); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray()); //转为对象 ObjectInputStream objectInputStream1 = new ObjectInputStream(byteArrayInputStream); - LeetCode1 o1 = (LeetCode1)objectInputStream1.readObject(); + LeetCode11 o1 = (LeetCode11)objectInputStream1.readObject(); o1.test(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("cc.txt")); - LeetCode1 obj = new LeetCode1(); + LeetCode11 obj = new LeetCode11(); obj.test(); objectOutputStream.writeObject(obj); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("cc.txt")); - LeetCode1 o = (LeetCode1) objectInputStream.readObject(); + LeetCode11 o = (LeetCode11) objectInputStream.readObject(); o.test(); objectOutputStream.close(); } diff --git a/springDemo/mvnw b/springDemo/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/springDemo/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/springDemo/mvnw.cmd b/springDemo/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/springDemo/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"