From 263bc7481fbabddefd5155a67cb2d8871b345abf Mon Sep 17 00:00:00 2001 From: zhangsan <646228430@qq.com> Date: Mon, 21 Apr 2025 16:21:26 +0800 Subject: [PATCH] =?UTF-8?q?4.21=20=E5=9B=9E=E6=96=87=E4=B8=B2=20=E5=9B=9E?= =?UTF-8?q?=E6=96=87=E5=BA=8F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dynamic_programming/CountSubstrings.java | 44 +++++++++++++++++++ .../java/dynamic_programming/FindLength.java | 30 ++++++++++++- .../LongestCommonSubsequence.java | 30 +++++++++++++ .../LongestPalindrome.java | 38 ++++++++++++++++ .../LongestPalindromeSubseq.java | 38 ++++++++++++++++ .../LongestCommonSubsequenceTest.java | 16 +++++++ .../LongestPalindromeSubseqTest.java | 16 +++++++ .../LongestPalindromeTest.java | 16 +++++++ 8 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 src/main/java/dynamic_programming/CountSubstrings.java create mode 100644 src/main/java/dynamic_programming/LongestCommonSubsequence.java create mode 100644 src/main/java/dynamic_programming/LongestPalindrome.java create mode 100644 src/main/java/dynamic_programming/LongestPalindromeSubseq.java create mode 100644 src/test/java/dynamic_programming/LongestCommonSubsequenceTest.java create mode 100644 src/test/java/dynamic_programming/LongestPalindromeSubseqTest.java create mode 100644 src/test/java/dynamic_programming/LongestPalindromeTest.java diff --git a/src/main/java/dynamic_programming/CountSubstrings.java b/src/main/java/dynamic_programming/CountSubstrings.java new file mode 100644 index 0000000..4ceb42f --- /dev/null +++ b/src/main/java/dynamic_programming/CountSubstrings.java @@ -0,0 +1,44 @@ +package dynamic_programming; +/** + * 题目: 647. 回文子串 (longestCommonSubsequence) + * 描述:给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 + * 回文字符串 是正着读和倒过来读一样的字符串。 + * 子字符串 是字符串中的由连续字符组成的一个序列。 + + * 示例 1: + 输入:s = "abc" + 输出:3 + 解释:三个回文子串: "a", "b", "c" + + * 链接:https://leetcode.cn/problems/palindromic-substrings/ + */ +//不会 +public class CountSubstrings { + /** + *布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串 + * 情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串 + * 情况二:下标i 与 j相差为1,例如aa,也是回文子串 + * 情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。 + * 递推顺序为左下到右上 + */ + public int countSubstrings(String s) { + char[] chars = s.toCharArray(); + int len = chars.length; + boolean[][] dp = new boolean[len][len]; + int result = 0; + for (int i = len - 1; i >= 0; i--) { + for (int j = i; j < len; j++) { + if (chars[i] == chars[j]) { + if (j - i <= 1) { // 情况一 和 情况二 + result++; + dp[i][j] = true; + } else if (dp[i + 1][j - 1]) { //情况三 + result++; + dp[i][j] = true; + } + } + } + } + return result; + } +} diff --git a/src/main/java/dynamic_programming/FindLength.java b/src/main/java/dynamic_programming/FindLength.java index 303c491..32dff82 100644 --- a/src/main/java/dynamic_programming/FindLength.java +++ b/src/main/java/dynamic_programming/FindLength.java @@ -10,8 +10,36 @@ package dynamic_programming; * 链接:https://leetcode.cn/problems/maximum-length-of-repeated-subarray/ */ +//不会 + +/** + * dp[i][j] 的定义是: + * + * 以 nums1[i-1] 和 nums2[j-1] 作为“结尾”元素的两个前缀序列(分别是 nums1[0…i-1] 和 nums2[0…j-1])的最长公共后缀(subarray)的长度。 + * 这样就可能出现dp[1][1]=1 dp[1][2]=0的情况了 + * + * 状态转移方程 + * if (nums1[i-1] == nums2[j-1]) + * dp[i][j] = dp[i-1][j-1] + 1; + * else + * dp[i][j] = 0; + */ public class FindLength { public int findLength(int[] nums1, int[] nums2) { - return 0; + int n = nums1.length, m = nums2.length; + // dp[i][j] 表示 nums1[0..i-1] 与 nums2[0..j-1] '结尾'处的最长公共后缀长度 + int[][] dp = new int[n + 1][m + 1]; + int ans = 0; + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { + if (nums1[i - 1] == nums2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + ans = Math.max(ans, dp[i][j]); + } + // else dp[i][j] 默认为 0 + } + } + return ans; } } diff --git a/src/main/java/dynamic_programming/LongestCommonSubsequence.java b/src/main/java/dynamic_programming/LongestCommonSubsequence.java new file mode 100644 index 0000000..7b52c3e --- /dev/null +++ b/src/main/java/dynamic_programming/LongestCommonSubsequence.java @@ -0,0 +1,30 @@ +package dynamic_programming; +/** + * 题目: 1143. 最长公共子序列 (longestCommonSubsequence) + * 描述:给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 + * 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。 + * 例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。 + * 两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。 + + * 示例 1: + 输入:text1 = "abcde", text2 = "ace" + 输出:3 + 解释:最长公共子序列是 "ace" ,它的长度为 3 。 + + * 链接:https://leetcode.cn/problems/longest-common-subsequence/ + */ +public class LongestCommonSubsequence { + public int longestCommonSubsequence(String text1, String text2) { + int n=text1.length(),m=text2.length(); + int[][]dp=new int[n+1][m+1]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { + if(text1.charAt(i-1)==text2.charAt(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[n][m]; + } +} diff --git a/src/main/java/dynamic_programming/LongestPalindrome.java b/src/main/java/dynamic_programming/LongestPalindrome.java new file mode 100644 index 0000000..3a05a77 --- /dev/null +++ b/src/main/java/dynamic_programming/LongestPalindrome.java @@ -0,0 +1,38 @@ +package dynamic_programming; +/** + * 题目: 5. 最长回文子串 (longestPalindrome) + * 描述:给你一个字符串 s,找到 s 中最长的 回文 子串。 + * + + * 示例 1: + 输入:s = "babad" + 输出:"bab" + 解释:"aba" 同样是符合题意的答案。 + + * 链接:https://leetcode.cn/problems/longest-palindromic-substring/ + */ +public class LongestPalindrome { + public String longestPalindrome(String s) { + int n = s.length(); + if (n < 2) return s; + char[] cs = s.toCharArray(); + boolean[][] dp = new boolean[n][n]; + + int maxLen = 1, start = 0; + // 从后往前遍历 i,j 从 i 往后 + for (int i = n - 1; i >= 0; i--) { + for (int j = i; j < n; j++) { + // 回文条件:首尾相等,且要么长度<=2(两字符或单字符),要么内部也是回文 + if (cs[i] == cs[j] && (j - i <= 1 || dp[i + 1][j - 1])) { + dp[i][j] = true; + int len = j - i + 1; + if (len > maxLen) { + maxLen = len; + start = i; + } + } + } + } + return s.substring(start, start + maxLen); + } +} diff --git a/src/main/java/dynamic_programming/LongestPalindromeSubseq.java b/src/main/java/dynamic_programming/LongestPalindromeSubseq.java new file mode 100644 index 0000000..2b21a72 --- /dev/null +++ b/src/main/java/dynamic_programming/LongestPalindromeSubseq.java @@ -0,0 +1,38 @@ +package dynamic_programming; +/** + * 题目: 516. 最长回文子序列 (longestPalindromeSubseq) + * 描述:给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 + * 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 + + * 示例 1: + 输入:s = "bbbab" + 输出:4 + 解释:一个可能的最长回文子序列为 "bbbb" 。 + + * 链接:https://leetcode.cn/problems/longest-palindromic-subsequence/ + */ +public class LongestPalindromeSubseq { + public int longestPalindromeSubseq(String s) { + int n = s.length(); + if (n < 2) return n; + char[] cs = s.toCharArray(); + int[][] dp = new int[n][n]; + + // 对角线全是长度 1 的子序列 + for (int i = 0; i < n; i++) { + dp[i][i] = 1; + } + + // i 从后往前,确保 dp[i+1][*] 已经算好 + for (int i = n - 1; i >= 0; i--) { + for (int j = i + 1; j < n; j++) { + if (cs[i] == cs[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[0][n - 1]; + } +} diff --git a/src/test/java/dynamic_programming/LongestCommonSubsequenceTest.java b/src/test/java/dynamic_programming/LongestCommonSubsequenceTest.java new file mode 100644 index 0000000..86bb53a --- /dev/null +++ b/src/test/java/dynamic_programming/LongestCommonSubsequenceTest.java @@ -0,0 +1,16 @@ +package dynamic_programming; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LongestCommonSubsequenceTest { + + @Test + public void longestCommonSubsequence() { + String text1 = "aab",text2 = "abb"; + LongestCommonSubsequence solution = new LongestCommonSubsequence(); + int res=solution.longestCommonSubsequence(text1,text2); + System.out.println(res); + } +} \ No newline at end of file diff --git a/src/test/java/dynamic_programming/LongestPalindromeSubseqTest.java b/src/test/java/dynamic_programming/LongestPalindromeSubseqTest.java new file mode 100644 index 0000000..6a22b48 --- /dev/null +++ b/src/test/java/dynamic_programming/LongestPalindromeSubseqTest.java @@ -0,0 +1,16 @@ +package dynamic_programming; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LongestPalindromeSubseqTest { + + @Test + public void longestPalindromeSubseq() { + LongestPalindromeSubseq solution = new LongestPalindromeSubseq(); + String s="abc"; + int res=solution.longestPalindromeSubseq(s); + System.out.println(res); + } +} \ No newline at end of file diff --git a/src/test/java/dynamic_programming/LongestPalindromeTest.java b/src/test/java/dynamic_programming/LongestPalindromeTest.java new file mode 100644 index 0000000..f47e755 --- /dev/null +++ b/src/test/java/dynamic_programming/LongestPalindromeTest.java @@ -0,0 +1,16 @@ +package dynamic_programming; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LongestPalindromeTest { + + @Test + public void longestPalindrome() { + LongestPalindrome solution = new LongestPalindrome(); + String s = "babad"; + String S=solution.longestPalindrome(s); + System.out.println(S); + } +} \ No newline at end of file