diff --git a/pom.xml b/pom.xml index c159d4f..70b765a 100644 --- a/pom.xml +++ b/pom.xml @@ -9,14 +9,19 @@ 1.0-SNAPSHOT UTF-8 - 21 - 21 + 17 + 17 + + cglib + cglib + 3.3.0 + cn.hutool hutool-http diff --git a/src/main/java/cn/whaifree/interview/tx/tx01.java b/src/main/java/cn/whaifree/interview/tx/tx01.java new file mode 100644 index 0000000..f7a1d01 --- /dev/null +++ b/src/main/java/cn/whaifree/interview/tx/tx01.java @@ -0,0 +1,468 @@ +package cn.whaifree.interview.tx; + +import cn.whaifree.leetCode.model.ListNode; + +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/31 19:55 + * @注释 + */ +public class tx01 { + +// public volatile Integer single = null; +// +// public Integer getSingle() { +// if (single == null) { +// synchronized (Integer.class) { +// if (single == null) { +// return new Integer(1); +// } +// } +// } +// return null; +// } + + static class c extends Thread{ + + @Override + public void run() { + + System.out.println("c"); + + } + } + + public static void main(String[] args) { + new c().start(); + Runnable runnable = () -> { + System.out.println("1"); + }; + + Callable objectCallable = new Callable<>() { + @Override + public Object call() throws Exception { + System.out.println("call"); + return null; + } + }; + + FutureTask objectFutureTask = new FutureTask<>(objectCallable); + new Thread(objectFutureTask).start(); + } + + static class p1 { + /** + * 小红拿到了一个无向图,其中一些边被染成了红色。 + * 小红定义一个点是“好点”,当且仅当这个点的所有邻边都是红边。 + * 现在请你求出这个无向图“好点”的数量。 + * 注:如果一个节点没有任何邻边,那么它也是好点。 + *

+ * 输入描述 + * 第一行输入两个正整数n,m,代表节点的数量和边的数量。 + * 接下来的m行,每行输入两个正整数u,v和一个字符chr,代表节点u和节点v有一条边连接。如果 chr 为'R',代表这条边被染红;'W'代表未被染色。 + *

+ * 1\leq n,m \leq 10^5 + * 1\leq u,v \leq n + *

+ * 输出描述 + * 一个整数,代表“好点”的数量。 + *

+ * 示例 1 + * 收起 + *

+ * 输入 + * 复制 + * 4 4 + * 1 2 R + * 2 3 W + * 3 4 W + * 1 4 R + * 输出 + * 复制 + * 1 + * 说明 + * 只有 1 号节点是好点。 + * + * @param args + */ + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int m = scanner.nextInt(); + + HashMap> map = new HashMap<>(); + for (int i = 0; i < m; i++) { + int a = scanner.nextInt(); + int b = scanner.nextInt(); + String next = scanner.next(); + if (next.equals("R")) { + if (!map.containsKey(a)) { + map.put(a, new ArrayList<>()); + } + map.get(a).add(new int[]{b, 1}); + + if (!map.containsKey(b)) { + map.put(b, new ArrayList<>()); + } + map.get(b).add(new int[]{a, 1}); + } else { + if (!map.containsKey(a)) { + map.put(a, new ArrayList<>()); + } + map.get(a).add(new int[]{b, 0}); + if (!map.containsKey(b)) { + map.put(b, new ArrayList<>()); + } + map.get(b).add(new int[]{a, 0}); + } + } + + int res = 0; + + Set integers = map.keySet(); + for (Integer key : integers) { + boolean flag = true; + List ints = map.get(key); + for (int[] anInt : ints) { + if (anInt[1] == 0) { + flag = false; + break; + } + } + if (flag) res++; + } + // 对没有边的 + res += (n - integers.size()); + + System.out.println(res); + + } + } + + static class p2 { + + /** + * 小红拿到了一个链表。她准备将这个链表断裂成两个链表,再拼接到一起,使得链表从头节点到尾部升序。你能帮小红判断能否达成目的吗? + * 给定的为一个链表数组,你需要对于数组中每个链表进行一次“是”或者“否”的答案回答,并返回布尔数组。 + * 每个链表的长度不小于 2,且每个链表中不包含两个相等的元素。所有链表的长度之和保证不超过10^5 + *

+ * 示例 1 + * 收起 + *

+ * 输入 + * 复制 + * [{1,2,3},{2,3,1},{3,2,1}] + * 输出 + * 复制 + * [true,true,false] + * 说明 + * 第三个链表无论怎么操作都不满足条件。 + * + * @param args + */ + public static void main(String[] args) { + + System.out.println(cansort(ListNode.listNodeFromArray(new int[]{1, 2, 3}))); + } + + public boolean[] canSorted(ListNode[] lists) { + // write code here + boolean[] res = new boolean[lists.length]; + for (int i = 0; i < lists.length; i++) { + boolean cansort = cansort(lists[i]); + res[i] = cansort; + } + return res; + } + + public static boolean cansort(ListNode node) { + // 4 6 1 3 2 找到两个区间都递增 + ListNode index = node; + int flag = 0; + while (index.next != null) { + if (index.val > index.next.val) { + if (index.next.next != null && index.next.next.val > index.val) { + return false; + } + if (flag == 1) return false; + flag = 1; + } + index = index.next; + } + + return true; + } + } + + static class p4 { + /** + * 小红拿到了一个有 n 个节点的无向图,这个图初始并不是连通图。 + * 现在小红想知道,添加恰好一条边使得这个图连通,有多少种不同的加边方案? + *

+ * 输入描述 + * 第一行输入两个正整数n,m,用空格隔开。 + * 接下来的m行,每行输入两个正整数u,v,代表节点u和节点v之间有一条边连接。 + * 1\leq n,m \leq 10^5 + * 1\leq u,v \leq n + * 保证给出的图是不连通的。 + *

+ * 输出描述 + * 一个整数,代表加边的方案数。 + *

+ * 示例 1 + * 收起 + *

+ * 输入 + * 复制 + * 4 2 + * 1 2 + * 3 4 + * 输出 + * 复制 + * 4 + * 说明 + * 添加边 (1,3) 或者 (1,4) 或者 (2,3) 或者 (2,4) 都是可以的。 + *

+ * 示例 2 + * 收起 + *

+ * 输入 + * 复制 + * 4 1 + * 1 3 + * 输出 + * 复制 + * 0 + * 说明 + * 无论添加哪条边,都不可能使得该图变成连通图。 + * + * @param args + */ + public static void main(String[] args) { + + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int m = scanner.nextInt(); + + HashSet set1 = new HashSet<>(); + HashSet set2 = new HashSet<>(); + int a = scanner.nextInt(); + int b = scanner.nextInt(); + set1.add(a); + set1.add(b); + + + for (int i = 1; i < m; i++) { + a = scanner.nextInt(); + b = scanner.nextInt(); + + if ((set1.contains(a) || set1.contains(b))) { + set1.add(a); + set1.add(b); + } else { + set2.add(a); + set2.add(b); + } + } + + System.out.println(set1.size() * set2.size()); + + } + } + + static class p5 { + /** + * 小红拿到了一个数组,她准备将数组分割成 k 段,使得每段内部做按位异或后,再全部求和。小红希望最终这个和尽可能大,你能帮帮她吗? + *

+ * 输入描述 + * 输入包含两行。 + * 第一行两个正整数 n, k , (1\leq k \leq n \leq 400),分别表示数组的长度和要分的段数。 + * 第二行 n 个整数 a_i (0 \leq a_i \leq 10^9),表示数组 a 的元素。 + *

+ * 输出描述 + * 输出一个正整数,表示最终的最大和。 + *

+ * 示例 1 + * 收起 + *

+ * 输入 + * 复制 + * 6 2 + * 1 1 1 2 3 4 + * 输出 + * 复制 + * 10 + * 说明 + * 小红将数组分为了: + * [1, 4] 和 [5, 6] 这两个区间,得分分别为:1 \oplus 1 \oplus 1 \oplus 2 = 3 和 3 \oplus 4 = 7。总得分为 3+7=10。 + * 可以证明不存在比 10 更优的分割方案。 + * 注:\oplus 符号表示异或操作。 + *

+ * 示例 2 + * 收起 + *

+ * 输入 + * 复制 + * 5 3 + * 1 0 1 1 0 + * 输出 + * 复制 + * 3 + * 示例 3 + * 收起 + *

+ * 输入 + * 复制 + * 3 3 + * 1 1 2 + * 输出 + * 复制 + * 4 + * + * @param args + */ + public static void main(String[] args) { + + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int k = scanner.nextInt(); + int[] nums = new int[n]; + for (int i = 0; i < n; i++) { + nums[i] = scanner.nextInt(); + } + + + } + + public static int maxXorSum(int[] nums, int k) { + int n = nums.length; + int[][] prefixXor = new int[n + 1][k + 1]; + int[][] dp = new int[n + 1][k + 1]; + + // 计算前缀异或和 + for (int i = 1; i <= n; i++) { + prefixXor[i][0] = prefixXor[i - 1][0] ^ nums[i - 1]; + } + + for (int j = 1; j <= k; j++) { + for (int i = 1; i <= n; i++) { + prefixXor[i][j] = prefixXor[i][0]; + dp[i][j] = dp[i - 1][j]; + for (int x = 0; x < i; x++) { + dp[i][j] = Math.max(dp[i][j], dp[x][j - 1] + prefixXor[i][j]); + } + } + } + + return dp[n][k]; + } + } + + static class p6 { + + static int res = 0; + static List path = null; + + /** + * 小红拿到了一个字符矩阵,她可以从任意一个地方出发,希望走 6 步后恰好形成"tencent"字符串。小红想知道,共有多少种不同的行走方案? + * 注:每一步可以选择上、下、左、右中任意一个方向进行行走。不可行走到矩阵外部。 + *

+ * 输入描述 + * 第一行输入两个正整数n,m,代表矩阵的行数和列数。 + * 接下来的n行,每行输入一个长度为m的、仅由小写字母组成的字符串,代表小红拿到的矩阵。 + *

+ * 1\leq n,m \leq 1000 + *

+ * 输出描述 + * 一个整数,代表最终合法的方案数。 + *

+ * 示例 1 + * 收起 + *

+ * 输入 + * 复制 + * 3 3 + * ten + * nec + * ten + * 输出 + * 复制 + * 4 + * 说明 + * 第一个方案,从左上角出发,右右下左左上。 + * 第二个方案,从左上角出发,右右下左左下。 + * 第三个方案,从左下角出发,右右上左左下。 + * 第四个方案,从左上角出发,右右上左左上。 + * + * @param args + */ + public static void main(String[] args) { + path = new ArrayList<>(); + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int m = scanner.nextInt(); + char[][] chars = new char[n][m]; + for (int i = 0; i < n; i++) { + char[] c = scanner.next().toCharArray(); + for (int j = 0; j < c.length; j++) { + chars[i][j] = c[j]; + } + } + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (chars[i][j] == 't') { + path.add('t'); + backing(chars, i, j); + path.remove(path.size() - 1); + } + } + } + System.out.println(res); + + } + + public static void backing(char[][] chars, int x, int y) { + if (path.size() == 7) { +// System.out.println(new ArrayList<>(path)); + res++; + return; + } + + Character expect = null; + if (path.size() == 1) { + expect = 'e'; + } else if (path.size() == 2) { + expect = 'n'; + } else if (path.size() == 3) { + expect = 'c'; + } else if (path.size() == 4) { + expect = 'e'; + } else if (path.size() == 5) { + expect = 'n'; + } else if (path.size() == 6) { + expect = 't'; + } + + path.add(chars[x][y]); + if (x < chars.length - 1 && expect.equals(chars[x + 1][y])) { + backing(chars, x + 1, y); + } + if (y < chars[0].length - 1 && expect.equals(chars[x][y + 1])) { + backing(chars, x, y + 1); + } + if (x > 0 && expect.equals(chars[x - 1][y])) { + backing(chars, x - 1, y); + } + if (y > 0 && expect.equals(chars[x][y - 1])) { + backing(chars, x, y - 1); + } + path.remove(path.size() - 1); + } + } +} diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode121.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode121.java new file mode 100644 index 0000000..638adf6 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/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/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode198.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode198.java new file mode 100644 index 0000000..6e3210c --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/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/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode322.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode322.java index 2406a4f..413ac9f 100644 --- a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode322.java +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode322.java @@ -13,9 +13,9 @@ import java.util.Arrays; public class LeetCode322 { @Test public void test() { - int[] coins = {1,2,5}; - int amount = 11; - int i = new Solution().coinChange(coins, amount); + int[] coins = {1}; + int amount = 0; + int i = new Solution1().coinChange(coins, amount); System.out.println(i); } @@ -44,4 +44,49 @@ public class LeetCode322 { } } + + 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/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode337.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode337.java new file mode 100644 index 0000000..dee49fe --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/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/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode377.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode377.java index f709e3a..cf5bce1 100644 --- a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode377.java +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode377.java @@ -98,4 +98,7 @@ public class LeetCode377 { } + + + } diff --git a/src/main/java/cn/whaifree/leetCode/Hash/LeetCode1.java b/src/main/java/cn/whaifree/leetCode/Hash/LeetCode1.java index 5fd65f1..5aa2372 100644 --- a/src/main/java/cn/whaifree/leetCode/Hash/LeetCode1.java +++ b/src/main/java/cn/whaifree/leetCode/Hash/LeetCode1.java @@ -2,8 +2,8 @@ package cn.whaifree.leetCode.Hash; import org.junit.Test; +import java.io.Serializable; import java.util.HashMap; -import java.util.HashSet; /** * 1. 两数之和 @@ -39,7 +39,7 @@ import java.util.HashSet; * * 进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗? */ -public class LeetCode1 { +public class LeetCode1 implements Serializable { @Test public void test() { diff --git a/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode11.java b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode11.java new file mode 100644 index 0000000..86b6709 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode11.java @@ -0,0 +1,51 @@ +package cn.whaifree.leetCode.LeetCode; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/3 17:35 + * @注释 + */ +public class LeetCode11 { + + @Test + public void test() { + Solution solution = new Solution(); + int[] height = {1,1}; + int i = solution.maxArea(height); + System.out.println(i); + } + + class Solution { + /** + * $S(i,j)=min(h[i],h[j])*(j-i)$ + * 双指针 + * 长板移动面积不变或 变小 + * 短板移动 变大 或不变 + * 不断移动短板 + * @param height + * @return + */ + public int maxArea(int[] height) { + + int storage = 0; + int left = 0; + int right = height.length - 1; + while (left < right) { + storage = Math.max(getArea(height, left, right), storage); + if (height[left] < height[right]) { + left++; + }else { + right--; + } + } + return storage; + } + + public int getArea(int[] height, int start, int end) { + return Math.min(height[start], height[end]) * (end - start); + } + } +} diff --git a/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode22.java b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode22.java new file mode 100644 index 0000000..01b19d1 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/LeetCode/LeetCode22.java @@ -0,0 +1,115 @@ +package cn.whaifree.leetCode.LeetCode; + +import org.junit.Test; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/4 13:44 + * @注释 + */ +public class LeetCode22 { + + @Test + public void test() { + + List res =new Solution1().generateParenthesis(3); + System.out.println(res); + } + + class Solution { + List res = new ArrayList<>(); + StringBuilder path = new StringBuilder(); + + /** + * + * @param n + * @return + */ + public List generateParenthesis(int n) { + backTracking(n, 0, 0); + return res; + } + + /** + * + * @param n + * @param leftCount 左括号用了几个 + * @param rightCount 右括号用了几个 + */ + public void backTracking(int n, int leftCount , int rightCount) { + + if (leftCount > n || rightCount > leftCount) { + return; + } + + if (path.length() == n * 2) { + res.add(path.toString()); + return; + } + + + path.append("("); + backTracking(n, leftCount + 1, rightCount); + path.deleteCharAt(path.length() - 1); // 回溯 + + path.append(")"); + backTracking(n, leftCount, rightCount + 1); + path.deleteCharAt(path.length() - 1); // 回溯 + + } + + + } + + class Solution1 { + List res = new ArrayList<>(); + StringBuilder path = new StringBuilder(); + + /** + * + * @param n + * @return + */ + public List generateParenthesis(int n) { + backTracking(n, n, n); + return res; + } + + /** + * + * @param n + * @param leftCount 左括号可用数 + * @param rightCount 右括号可用数 + */ + public void backTracking(int n, int leftCount , int rightCount) { + + if (leftCount == 0 && rightCount == 0) { + res.add(path.toString()); + return; + } + + if (leftCount > rightCount) { + return; + } + + + if (leftCount > 0) { + path.append("("); + backTracking(n, leftCount - 1, rightCount); + path.deleteCharAt(path.length() - 1); + } + if (rightCount > 0) { + path.append(")"); + backTracking(n, leftCount, rightCount - 1); + path.deleteCharAt(path.length() - 1); + } + + } + + + } + +} diff --git a/src/main/java/cn/whaifree/leetCode/LinkedList/LeetCode21.java b/src/main/java/cn/whaifree/leetCode/LinkedList/LeetCode21.java new file mode 100644 index 0000000..2ecf941 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/LinkedList/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/src/main/java/cn/whaifree/test/CRC16_ARC.java b/src/main/java/cn/whaifree/test/CRC16_ARC.java new file mode 100644 index 0000000..bfa6689 --- /dev/null +++ b/src/main/java/cn/whaifree/test/CRC16_ARC.java @@ -0,0 +1,150 @@ +package cn.whaifree.test; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/23 20:36 + * @注释 + */ +public class CRC16_ARC { + + + + private static final int CRC16_ARC = 0x8005; // CRC16-ARC多项式 + + /** + * 计算CRC16ARC校验值 + * @param data 要计算校验值的数据数组 + * @return 返回计算得到的CRC16ARC校验值 + */ + public static int calculateCRC16ARC(byte[] data) { + // 使用CRC32算法计算校验值,然后将其转换为16位 + int crcValue = 0xFFFF; // 初始值为0xFFFF,表示CRC16-ARC的初始寄存器状态 + + // 遍历数据数组,逐字节计算CRC校验值 + for (byte b : data) { + crcValue ^= b & 0xFF; // 将数据字节与CRC值异或 + + // 对CRC值进行8次位运算,模拟移位和异或过程 + for (int i = 0; i < 8; i++) { + if ((crcValue & 0x0001) != 0) { + crcValue = (crcValue >> 1) ^ CRC16_ARC; // 如果最低位为1,进行异或运算 + } else { + crcValue >>= 1; // 如果最低位为0,仅右移一位 + } + } + } + + return crcValue; + } + + + + /** + * 为指定的源文件附加CRC16ARC校验值,并将结果保存为新文件。 + * + * @param sourceFilePath 源文件路径,将对此文件进行读取。 + * @param destinationFilePath 保存带有CRC校验值的新文件的路径。 + * @throws IOException 如果在读取源文件或写入新文件过程中发生I/O错误。 + */ + public static void attachCRC16ARC(String sourceFilePath, String destinationFilePath) throws IOException { + // 打开源文件并读取所有内容 + FileInputStream fis = new FileInputStream(sourceFilePath); + byte[] data = fis.readAllBytes(); + fis.close(); + + // 计算源文件数据的CRC16ARC校验值 + int crcValue = calculateCRC16ARC(data); + + // 打开目标文件,写入源文件数据和CRC校验值 + FileOutputStream fos = new FileOutputStream(destinationFilePath); + fos.write(data); + // 写入CRC的高字节 + fos.write((crcValue & 0xFF00) >> 8); + // 写入CRC的低字节 + fos.write(crcValue & 0xFF); + fos.close(); + } + + public static byte[] generateCRC16ARCForSend(String filePath) throws IOException { + FileInputStream fis = new FileInputStream(filePath); + byte[] data = fis.readAllBytes(); + fis.close(); + + // 计算CRC16ARC校验值 + int crcValue = calculateCRC16ARC(data); + + byte[] crcBytes = new byte[2]; + crcBytes[0] = (byte) ((crcValue >> 8) & 0xFF); // 高位字节 + crcBytes[1] = (byte) (crcValue & 0xFF); // 低位字节 + + byte[] dataWithCRC = new byte[data.length + 2]; + System.arraycopy(data, 0, dataWithCRC, 0, data.length); + System.arraycopy(crcBytes, 0, dataWithCRC, data.length, 2); + + return dataWithCRC; + } + + public static boolean verifyCRC16ARCByBytes(byte[] bytes) { + + int crcValue = ((bytes[bytes.length - 2] & 0xFF) << 8) | (bytes[bytes.length - 1] & 0xFF); + byte[] crcData = new byte[]{(byte) (crcValue >> 8), (byte) crcValue}; + byte[] data = Arrays.copyOf(bytes, bytes.length - crcData.length); + int calculatedCRC = calculateCRC16ARC(data); + return crcValue == calculatedCRC; + } + + + /** + * 读取文件时,提取末尾的CRC值并进行验证: + * @param filePath + * @return + * @throws IOException + */ + public static boolean verifyCRC16ARC(String filePath) throws IOException { + FileInputStream fis = new FileInputStream(filePath); + byte[] data = fis.readAllBytes(); + fis.close(); + + // 文件附带的CRC + int fileCRC = ((data[data.length - 2] & 0xFF) << 8) | (data[data.length - 1] & 0xFF); + byte[] fileData = Arrays.copyOf(data, data.length - 2); + // 重新计算的CRC + int calculatedCRC = calculateCRC16ARC(fileData); + + return fileCRC == calculatedCRC; + } + + + + public static void main(String[] args) throws IOException, ClassNotFoundException { + + + + String filePath = "D:\\Downloads\\BFD-D42401883.pdf"; + String destinationFilePath = "D:\\Downloads\\BFD-D42401883-1.pdf"; // 输出的 + attachCRC16ARC(filePath, destinationFilePath); + if (verifyCRC16ARC(destinationFilePath)) { + System.out.println("验证成功"); + }else { + System.out.println("验证失败"); + } + + + byte[] bytes = generateCRC16ARCForSend(filePath); // 生成附带CRC的完整文件 + if (verifyCRC16ARCByBytes(bytes)) { // 验证 + System.out.println("验证成功"); + }else { + System.out.println("验证失败"); + } + + + System.out.println(calculateCRC16ARC(new byte[]{1})); + + } +} diff --git a/src/main/java/cn/whaifree/test/ShapleyValueDemo.java b/src/main/java/cn/whaifree/test/ShapleyValueDemo.java new file mode 100644 index 0000000..c25f8d7 --- /dev/null +++ b/src/main/java/cn/whaifree/test/ShapleyValueDemo.java @@ -0,0 +1,74 @@ +package cn.whaifree.test; + +import java.util.ArrayList; +import java.util.List; + +public class ShapleyValueDemo { + + static class Node { + int id; + double distance; + double strength; + + Node(int id, double distance, double strength) { + this.id = id; + this.distance = distance; + this.strength = strength; + } + } + + public static void main(String[] args) { + List nodes = new ArrayList<>(); + // 添加三个节点的信息,这里以节点的 ID、距离和强度为例 + nodes.add(new Node(1, 0.5, 0.8)); + nodes.add(new Node(2, 0.8, 0.6)); + nodes.add(new Node(3, 0.7, 0.7)); + + List shapleyValues = calculateShapleyValues(nodes); + + System.out.println("Shapley Values:"); + for (int i = 0; i < nodes.size(); i++) { + System.out.println("Node " + nodes.get(i).id + ": " + shapleyValues.get(i)); + } + } + + public static List calculateShapleyValues(List nodes) { + List shapleyValues = new ArrayList<>(); + double[] marginalContributions = new double[nodes.size()]; + + // 计算每个节点的 Shapley 值 + for (int i = 0; i < nodes.size(); i++) { + for (int j = 0; j < nodes.size(); j++) { + if (i != j) { + double valueWithI = getValue(getPlayerSubset(nodes.get(i), nodes.get(j))); + double valueWithoutI = getValue(getPlayerSubset(nodes.get(j))); + marginalContributions[i] += (valueWithI - valueWithoutI); + } + } + shapleyValues.add(marginalContributions[i] / nodes.size()); + } + + return shapleyValues; + } + + // 模拟每个节点的贡献价值 + public static double getValue(List nodes) { + // 这里可以根据实际情况编写计算价值的逻辑,这里简单地假设节点的贡献价值为距离与强度的乘积之和 + double value = 0.0; + for (Node node : nodes) { + value += node.distance * node.strength; + } + return value; + } + + // 生成不包含给定节点的组合 + public static List getPlayerSubset(Node excludedNode, Node... nodes) { + List subset = new ArrayList<>(); + for (Node node : nodes) { + if (node != excludedNode) { + subset.add(node); + } + } + return subset; + } +} diff --git a/src/main/java/cn/whaifree/test/byteStream.java b/src/main/java/cn/whaifree/test/byteStream.java new file mode 100644 index 0000000..1ca4868 --- /dev/null +++ b/src/main/java/cn/whaifree/test/byteStream.java @@ -0,0 +1,39 @@ +package cn.whaifree.test; + +import cn.whaifree.leetCode.Hash.LeetCode1; + +import java.io.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/1 22:08 + * @注释 + */ +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()); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray()); + //转为对象 + ObjectInputStream objectInputStream1 = new ObjectInputStream(byteArrayInputStream); + LeetCode1 o1 = (LeetCode1)objectInputStream1.readObject(); + o1.test(); + + + + + ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("cc.txt")); + LeetCode1 obj = new LeetCode1(); + obj.test(); + objectOutputStream.writeObject(obj); + + ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("cc.txt")); + LeetCode1 o = (LeetCode1) objectInputStream.readObject(); + o.test(); + objectOutputStream.close(); + } +} diff --git a/src/main/java/cn/whaifree/test/cglib.java b/src/main/java/cn/whaifree/test/cglib.java new file mode 100644 index 0000000..3bf1ec2 --- /dev/null +++ b/src/main/java/cn/whaifree/test/cglib.java @@ -0,0 +1,76 @@ +package cn.whaifree.test; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/1 22:15 + * @注释 + */ +public class cglib { + + public static void main(String[] args) { + // 创建目标类的代理 + TargetClassProxy proxy = new TargetClassProxy(); + + // 使用CGLIB创建代理对象 + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(TargetClass.class); + enhancer.setCallback(proxy); + + TargetClass targetProxy = (TargetClass) enhancer.create(); // Enhancer创建子类代理 + + // 调用代理对象的方法 + targetProxy.doSomething(); + System.out.println("==================="); + targetProxy.doA(); + } +} + +class TargetClass extends TargetA{ + public void doSomething() { + System.out.println("TargetClass: doSomething()"); + } +} + +class TargetA{ + /** + * 加了final后,Enhancer不会增强 + *

+ * Before method: doSomething
+ * TargetClass: doSomething()
+ * After method: doSomething
+ * ===================
+ * TargetA: doA()
+ *

+ * + * 不加final + *

+ * Before method: doSomething
+ * TargetClass: doSomething()
+ * After method: doSomething
+ * ===================
+ * Before method: doA
+ * TargetA: doA()
+ * After method: doA
+ *

+ */ + public void doA(){ + + System.out.println("TargetA: doA()"); + } +} + +class TargetClassProxy implements MethodInterceptor { + @Override + public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable { + System.out.println("Before method: " + method.getName()); + Object result = proxy.invokeSuper(obj, args); // 调用目标类的原始方法 + System.out.println("After method: " + method.getName()); + return result; + } +} + diff --git a/src/main/java/cn/whaifree/test/hashDB.java b/src/main/java/cn/whaifree/test/hashDB.java new file mode 100644 index 0000000..249ca6f --- /dev/null +++ b/src/main/java/cn/whaifree/test/hashDB.java @@ -0,0 +1,43 @@ +package cn.whaifree.test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/1 20:01 + * @注释 + */ +public class hashDB { + + static final int[] hashes = {1,4}; // 哈希函数数组 + + // 3个库 + private static final int NUM_SHARDS = 3; + + + + public static void main(String[] args) { + // 要分库的数据 + String[] id = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; + + // 对每个数据计算哈希值并分配到库 + for (String datum : id) { + int[] shard = getShard(datum); + System.out.println("Data: " + datum + " -> Shard: " + shard[0] + ", " + shard[1]); + } + } + + // 计算数据的哈希值并分配到库 + private static int[] getShard(String data) { + // 使用Java的hashCode()方法计算哈希值 + int hash = data.hashCode(); + // 取模运算得到库编号 + int[] loc = new int[hashes.length]; + for (int i = 0; i < loc.length; i++) { + loc[i] = Math.abs((hash ^ hashes[i]) % NUM_SHARDS) + 1; + } + + return loc; + } + + +} diff --git a/src/main/java/cn/whaifree/test/testTry.java b/src/main/java/cn/whaifree/test/testTry.java index 48c3306..8904df5 100644 --- a/src/main/java/cn/whaifree/test/testTry.java +++ b/src/main/java/cn/whaifree/test/testTry.java @@ -2,6 +2,10 @@ package cn.whaifree.test; import org.junit.Test; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.spec.SecretKeySpec; + /** * @version 1.0 * @Author whai文海 @@ -28,3 +32,35 @@ public class testTry { } } + +class SymmetricEncryptionUtil { + + + + private static final String ALGORITHM = "AES"; + private static byte[] SECRET_KEY = null; // 替换为你自己的密钥,密钥长度必须符合算法要求 + + public static byte[] encrypt(byte[] data) throws Exception { + Cipher cipher = Cipher.getInstance(ALGORITHM); + SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY, ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + return cipher.doFinal(data); + } + + public static byte[] decrypt(byte[] encryptedData) throws Exception { + Cipher cipher = Cipher.getInstance(ALGORITHM); + SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY, ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, secretKey); + return cipher.doFinal(encryptedData); + } + + public static void main(String[] args) throws Exception { + SECRET_KEY = KeyGenerator.getInstance(ALGORITHM).generateKey().getEncoded(); + System.out.println(new String(SECRET_KEY)); + byte[] encrypt = SymmetricEncryptionUtil.encrypt("123456".getBytes()); + System.out.println(new String(encrypt)); + byte[] decrypt = SymmetricEncryptionUtil.decrypt(encrypt); + System.out.println(new String(decrypt)); + + } +}