-
题目:问题一:一个字符串至少要切几刀能让切出来的子串都是回文串
- 输入:s = “aab”
输出:1
解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。 - 切2刀==分成3个部分
- 输入:s = “aab”
-
思路:从i位置开始可以合并的最长回文串。从每个可以合并的末尾再调函数去递归处理后续可以合并的最长回文串。(暴力尝试)再加记忆法搜索
-
流程:i从右往左遍历,if(i~len)就是回文字符串则dp[i]=0
- else 则i往右遍历,找最小的dp[]值,则dp[i]= =min+1
- 最后得到一维的dp表
-
预处理检测回文串
- 问题:如果在主流程调递归时检查L~R是否是回文串则耦合太大,时间复杂度会乘上检查回文的复杂度
- 解决:先对字符串进行预处理,后续每次只要从表中取tmp[L][R]就知道是不是回文了。
- 问题:怎么对字符串进行检测回文的预处理
- [[获取单字符串中所有连续的回文字符串]]
-
[[回溯]]
-
回溯
- 含义:根据dp表中的值,根据尝试时的规律反推,找到答案的路径。
- 特点:路径要还原,最后记录答案
-
回溯答案的判断:需要切一刀的地方说明。①两个部分不能一同构成回文字符串,②两个各自可以构成字符串
-
①说明dp表中切的刀数后者少一
-
②后一个部分可以用两端检测,如果两端不同者一定不是,如果两端同&&不是的话因为指针一次只跳一格,一定能检测到后面某个子集中两端不同的情况不会漏掉。两端同&&是,则正确。
-
②前一部分不用验证,因为是从左开始遍历,遍历到i位置则说明i之前一定已经切分完形成回文串了
-
回溯所有答案
-
if(右指针到末尾)
- if(符合切一刀的判断)
- pathList添加这块
- ansList添加pathList
- 移除pathList中末尾项(还原现场)
- if(符合切一刀的判断)
-
else //没到末尾的情况
- if(符合切一刀的判断)
- pathList添加这块
- 调用递归,其中i=j,j=j+1
- 移除pathList中末尾项(还原现场)
- else //不符合切一刀的判断
- 调用递归,其中i=i,j=j+1
- if(符合切一刀的判断)
-
代码
```JAVA // s[0....i-1] 存到path里去了 // s[i..j-1]考察的分出来的第一份 public static void process(String s, int i, int j, boolean[][] checkMap, int[] dp, List<String> path, List<List<String>> ans) { if (j == s.length()) { // 右指针到结尾了 if (checkMap[i][j - 1] && dp[i] == dp[j] + 1) {//如果满足回溯条件 path.add(s.substring(i, j)); ans.add(copyStringList(path)); path.remove(path.size() - 1); } } else {// s[i...j-1] if (checkMap[i][j - 1] && dp[i] == dp[j] + 1) { path.add(s.substring(i, j)); process(s, j, j + 1, checkMap, dp, path, ans); path.remove(path.size() - 1); } process(s, i, j + 1, checkMap, dp, path, ans); } } ```
08-29
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交