From 1eb60f9be44c26e017b74b12fea29d26408b8999 Mon Sep 17 00:00:00 2001 From: whai Date: Fri, 8 Mar 2024 22:49:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=A7=84=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leetCode/Dynamic/LeetCode509.java | 48 +++++++ .../whaifree/leetCode/Dynamic/LeetCode62.java | 44 ++++++ .../whaifree/leetCode/Dynamic/LeetCode70.java | 42 ++++++ .../leetCode/Dynamic/LeetCode746.java | 46 ++++++ .../whaifree/leetCode/String/LeetCode28.java | 79 +++++++++- .../whaifree/leetCode/String/LeetCode459.java | 71 +++++++++ src/main/java/cn/whaifree/leetCode/Tes1.java | 135 ++++++++++++++++++ .../java/cn/whaifree/radom/LeetCode28.java | 64 +++++++++ 8 files changed, 525 insertions(+), 4 deletions(-) create mode 100644 src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode509.java create mode 100644 src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode62.java create mode 100644 src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode70.java create mode 100644 src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode746.java create mode 100644 src/main/java/cn/whaifree/leetCode/String/LeetCode459.java create mode 100644 src/main/java/cn/whaifree/leetCode/Tes1.java create mode 100644 src/main/java/cn/whaifree/radom/LeetCode28.java diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode509.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode509.java new file mode 100644 index 0000000..47ef87b --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/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/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode62.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode62.java new file mode 100644 index 0000000..e1f5412 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode62.java @@ -0,0 +1,44 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @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/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode70.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode70.java new file mode 100644 index 0000000..1347766 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/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/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode746.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode746.java new file mode 100644 index 0000000..3dd9024 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/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/src/main/java/cn/whaifree/leetCode/String/LeetCode28.java b/src/main/java/cn/whaifree/leetCode/String/LeetCode28.java index 6d9a821..4d2b992 100644 --- a/src/main/java/cn/whaifree/leetCode/String/LeetCode28.java +++ b/src/main/java/cn/whaifree/leetCode/String/LeetCode28.java @@ -2,6 +2,8 @@ package cn.whaifree.leetCode.String; import org.junit.Test; +import java.util.Arrays; + /** * 28. 找出字符串中第一个匹配项的下标 * @@ -27,9 +29,9 @@ public class LeetCode28 { @Test public void test() { - String haystack = "abc"; - String needle = "bc"; - int i = new Solution().strStr(haystack, needle); + String haystack = "aabaadaabaaf"; + String needle = "aabaaf"; + int i = new Solution1().strStr(haystack, needle); System.out.println(i); } @@ -47,8 +49,77 @@ public class LeetCode28 { 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/src/main/java/cn/whaifree/leetCode/String/LeetCode459.java b/src/main/java/cn/whaifree/leetCode/String/LeetCode459.java new file mode 100644 index 0000000..3105275 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/String/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/src/main/java/cn/whaifree/leetCode/Tes1.java b/src/main/java/cn/whaifree/leetCode/Tes1.java new file mode 100644 index 0000000..4725439 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Tes1.java @@ -0,0 +1,135 @@ +package cn.whaifree.leetCode; + +import cn.whaifree.leetCode.model.TreeNode; + +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.util.ArrayList; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/6 19:14 + * @注释 + */ +public class Tes1 { + +// public static void main(String[] args) { +//// new Tes1().localvarGc1(); +//// new Tes1().localvarGc2(); +//// new Tes1().localvarGc3(); +// new Tes1().localvarGc4(); +// } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + System.out.println("SystemGCTest 重写了finalize()"); + } + + /** + * -XX:+PrintGCDetail + */ + public void localvarGc1() { + byte[] buffer = new byte[10 * 1024 * 1024]; + //10MB + System.gc(); // 成功回收PSYoungGen,移动到ParOldGen老年代 + /** + * 新生代 PSYoungGen: 15482K->11192K(152576K 10mb + * full gc后,移动到老年代 [Full GC (System.gc()) [PSYoungGen: 11192K->0K(152576K)] 0mb [ParOldGen: 8K->10885K(348160K)] + * [GC (System.gc()) [PSYoungGen: 15482K->11192K(152576K)] 15482K->11200K(500736K), 0.0059640 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] + * [Full GC (System.gc()) [PSYoungGen: 11192K->0K(152576K)] [ParOldGen: 8K->10885K(348160K)] 11200K->10885K(500736K), [Metaspace: 3210K->3210K(1056768K)], 0.0060621 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] + * Heap + */ + } + + public void localvarGc2() { + byte[] buffer = new byte[10 * 1024 * 1024]; + buffer = null;// 对象已经没被引用,byte[]被回收 + + System.gc(); + /** + * 回收 空余的堆new byte[10 * 1024 * 1024]; + * [GC (System.gc()) [PSYoungGen: 15482K->840K(152576K)] 15482K->848K(500736K), 0.0009380 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] + * [Full GC (System.gc()) [PSYoungGen: 840K->0K(152576K)] [ParOldGen: 8K->645K(348160K)] 848K->645K(500736K), [Metaspace: 3215K->3215K(1056768K)], 0.0043640 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] + */ + } + + public void localvarGc3() { + { + byte[] buffer = new byte[10 * 1024 * 1024]; + } + System.gc(); + /** + * - 新生代 10mb + * [GC (System.gc()) [PSYoungGen: 15482K->11112K(152576K)] 15482K->11120K(500736K), 0.0064283 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] + * - 进入老年代 + * [Full GC (System.gc()) [PSYoungGen: 11112K->0K(152576K)] [ParOldGen: 8K->10882K(348160K)] 11120K->10882K(500736K), [Metaspace: 3169K->3169K(1056768K)], 0.0041698 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]*/ + } + + public void localvarGc4() { + { + byte[] buffer = new byte[10 * 1024 * 1024]; + } + int value = 10; + System.gc(); + /** + * // 局部变量表长度是2,第一个为this,第二个为value,替换了buffer,所以被回收了 + * [GC (System.gc()) [PSYoungGen: 15482K->904K(152576K)] 15482K->912K(500736K), 0.0006836 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] + * [Full GC (System.gc()) [PSYoungGen: 904K->0K(152576K)] [ParOldGen: 8K->669K(348160K)] 912K->669K(500736K), [Metaspace: 3216K->3216K(1056768K)], 0.0043170 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] + */ + } + + public void localvarGc5() { + localvarGc1(); + System.gc(); + } + + + public static void main1(String[] args) { + TreeNode treeNode = new TreeNode(11); + SoftReference treeNodeSoftReference = new SoftReference<>(treeNode); + treeNode = null; // 取消强引用 + System.out.println(treeNodeSoftReference.get().val); + + System.gc();//回收 + + System.out.println(treeNodeSoftReference.get().val); // 堆空间内存足够,不会回收软引用 + + try { + byte[] bytes = new byte[1024 * 1024 * 7]; //导致资源紧张、不够 + } catch (Exception e) { + e.printStackTrace(); + }finally { + System.out.println(treeNodeSoftReference.get()); // 在OOM之前,GC软引用对象treeNodeSoftReference + } + + } + + public static void main(String[] args) { + // 创建一个TreeNode对象并创建其对应的PhantomReference和ReferenceQueue + TreeNode treeNode = new TreeNode(11); + ReferenceQueue referenceQueue = new ReferenceQueue<>(); + PhantomReference treeNodePhantomReference = new PhantomReference<>(treeNode, referenceQueue); + + // 取消对TreeNode对象的强引用 + treeNode = null; + + // 尝试输出虚引用的对象,由于虚引用不能直接获取对象,所以此行会报错或无输出 + // System.out.println(treeNodePhantomReference.get().val); // 不允许直接访问 + + // 请求垃圾回收 + System.gc(); + + // 虽然对象可能已经被回收,但由于虚引用特性,此处仍然不会被回收 + // 需要检查ReferenceQueue来判断对象是否已被垃圾回收器处理 + if (referenceQueue.poll() != null) { + System.out.println("TreeNode对象已被垃圾回收器回收,但虚引用仍然存在"); + } else { + System.out.println("TreeNode对象还未被垃圾回收器回收"); + } + } + +} diff --git a/src/main/java/cn/whaifree/radom/LeetCode28.java b/src/main/java/cn/whaifree/radom/LeetCode28.java new file mode 100644 index 0000000..3542521 --- /dev/null +++ b/src/main/java/cn/whaifree/radom/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; + } + } + + +}