add
This commit is contained in:
parent
c7561d170b
commit
f168f3737d
129
算法/leetcode/常规题/Q131 分割回文串.md
Normal file
129
算法/leetcode/常规题/Q131 分割回文串.md
Normal file
@ -0,0 +1,129 @@
|
||||
---
|
||||
id: "20220309"
|
||||
date: "2021/03/09 20:15"
|
||||
title: "Q131 分割回文串(palindrome partitioning)"
|
||||
tags: ["java", "leetcode", "dp", "dfs"]
|
||||
index_img: https://qiniupic.fleyx.com/blog/202203091650691.jpg?imageView2/2/w/200
|
||||
banner_img: https://qiniupic.fleyx.com/blog/202203091650691.jpg
|
||||
categories:
|
||||
- "算法"
|
||||
- "leetcode刷题"
|
||||
---
|
||||
|
||||
## 解析思路
|
||||
|
||||
leetcode 中等难度,题目描述[点击这里](https://leetcode-cn.com/problems/palindrome-partitioning/)。
|
||||
|
||||
本题对于从没接触过回溯题目的人来说可以说是非常困难了,并不容易。
|
||||
|
||||
首先题意是要求返回所有的分割组合,使分割后数组中的数都为回文数。
|
||||
|
||||
判断回文数的方法很简单,两个指针从两端往中间遍历即可,或者先用 dp 计算得到所有的回文数组合(本解答采用 dp),本题字符串最长为 16,暴力判断和 dp 区别不大。
|
||||
|
||||
关键是如何穷举出所有分割可能,简单的 for 循环显然是做不到的.具体分割方法可以先看下图:
|
||||
|
||||
## 字符串分割
|
||||
|
||||

|
||||
|
||||
将字符串切分结果展开成一棵树以后,可以发现结果集就是对这棵树进行深度优先搜索的遍历结果,理解清楚分割原理以后用代码实现就比较简单了:
|
||||
|
||||
dfs 分割字符串代码如下:
|
||||
|
||||
```java
|
||||
/**
|
||||
* 分割字符串
|
||||
*
|
||||
* @param s 字符串
|
||||
* @param index 子串的起始位置
|
||||
* @param temp 临时存储已经分割后的字符串
|
||||
* @param res 存储最终分割结果
|
||||
*
|
||||
* @author fanxb
|
||||
* date 2022/3/9 16:39
|
||||
*/
|
||||
private void dfs(String s, int index, Stack<String> temp, List<List<String>> res ) {
|
||||
if (index == s.length()) {
|
||||
//当字符串起始位置超过字符串长度时说明本条链已经搜索完了
|
||||
res.add(new ArrayList<>(temp));
|
||||
return;
|
||||
}
|
||||
for (int i = index; i < s.length(); i++) {
|
||||
String tempS = s.substring(index, i + 1);
|
||||
temp.push(tempS);
|
||||
dfs(s, i + 1, temp, res, dp);
|
||||
//这里pop因为此路径已经处理完毕了,pop出去后,进行下一条路径处理
|
||||
temp.pop();
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## dp 得到回文数分布情况
|
||||
|
||||
判断回文的递推关系比较容易写.定义 dp[i][j]表示从下标 i 到 j 的字符串是否回文,递推关系如下:
|
||||
|
||||
1. dp[i][j]=true,i==j
|
||||
2. dp[i][j]=s[i]==s[j],i=j-1
|
||||
3. dp[i][j]=dp[i+1][j-1] && s[i]==s[j],其他情况
|
||||
|
||||
## 代码
|
||||
|
||||
经过上一节,现在我们已经能够穷举字符串所有的分割组合了,结合题意需要留下回文数组合,那么只需要进行剪枝操作即可(判断当前字符串片段是否回文,不回文就没必要继续当前路径)
|
||||
|
||||
完整代码如下:
|
||||
|
||||
```java
|
||||
public class Q131 {
|
||||
|
||||
public List<List<String>> partition(String s) {
|
||||
//先用dp找到所有符合条件的回文
|
||||
boolean[][] dp = new boolean[s.length()][s.length()];
|
||||
for (int j = 0; j < dp.length; j++) {
|
||||
for (int i = 0; i <= j; i++) {
|
||||
if (i == j) {
|
||||
dp[i][j] = true;
|
||||
} else {
|
||||
boolean b = s.charAt(i) == s.charAt(j);
|
||||
if (i + 1 == j) {
|
||||
dp[i][j] = b;
|
||||
} else {
|
||||
dp[i][j] = dp[i + 1][j - 1] && b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<List<String>> res = new ArrayList<>();
|
||||
dfs(s, 0, new Stack<>(), res, dp);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 分割字符串
|
||||
*
|
||||
* @param s 字符串
|
||||
* @param index 子串的起始位置
|
||||
* @param temp 临时存储已经分割后的字符串
|
||||
* @param res 存储最终分割结果
|
||||
* @param dp dp结果
|
||||
* @author fanxb
|
||||
* date 2022/3/9 16:39
|
||||
*/
|
||||
private void dfs(String s, int index, Stack<String> temp, List<List<String>> res, boolean[][] dp) {
|
||||
if (index == s.length()) {
|
||||
res.add(new ArrayList<>(temp));
|
||||
return;
|
||||
}
|
||||
for (int i = index; i < s.length(); i++) {
|
||||
if (dp[index][i + 1]) {
|
||||
String tempS = s.substring(index, i + 1);
|
||||
temp.push(tempS);
|
||||
dfs(s, i + 1, temp, res, dp);
|
||||
temp.pop();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
70
算法/leetcode/常规题/Q132 分割回文串Ⅱ.md
Normal file
70
算法/leetcode/常规题/Q132 分割回文串Ⅱ.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
id: "202203091"
|
||||
date: "2021/03/09 22:15"
|
||||
title: "Q132 分割回文串2(palindrome-partitioning-ii)"
|
||||
tags: ["java", "leetcode", "dp"]
|
||||
index_img: https://qiniupic.fleyx.com/blog/202203091652083.png?imageView2/2/w/200
|
||||
banner_img: https://qiniupic.fleyx.com/blog/202203091652083.png
|
||||
categories:
|
||||
- "算法"
|
||||
- "leetcode刷题"
|
||||
---
|
||||
|
||||
### 解析思路
|
||||
|
||||
leetcode 中等难度,题目描述[点击这里](https://leetcode-cn.com/problems/palindrome-partitioning-ii/)。
|
||||
|
||||
经过[分割回文数](https://blog.fleyx.com/blog/detail/20220309)后,本题应该就比较简单了。
|
||||
|
||||
题目要求返回最少的分割次数,通常这类最优问题都可以用 dp 来解决。注意这里无法使用上题的 dfs 暴力穷举所有结果后找到最优,会超时(因为字符长度最大为 2000,上题为 16)。
|
||||
|
||||
如果要用 dp 那么就需要构建 dp 表达式:
|
||||
|
||||
定义 minC[k]表示从 0 到 k 的最小分割次数,递推关系如下:
|
||||
|
||||
1. minC[k] = 0 ,k==0 || dp[0][k],当 k=0 或者 0-k 是一个回文串
|
||||
2. minC[k] = min(min[r-1]+1).其他情况需要在 0 到 k 之间找到一个 r 使 r 到 k 为一个回文数,那么分割次数就是 minC[r-1]+1(0 到 r-1 需要的最小分割次数再加上一次分割),在所有的情况下取最小的那个即可
|
||||
|
||||
### 代码如下:
|
||||
|
||||
```java
|
||||
public class Q132 {
|
||||
|
||||
public int minCut(String s) {
|
||||
//先用dp找到所有符合条件的回文
|
||||
boolean[][] dp = new boolean[s.length()][s.length()];
|
||||
for (int j = 0; j < dp.length; j++) {
|
||||
for (int i = 0; i <= j; i++) {
|
||||
if (i == j) {
|
||||
dp[i][j] = true;
|
||||
} else {
|
||||
boolean b = s.charAt(i) == s.charAt(j);
|
||||
if (i + 1 == j) {
|
||||
dp[i][j] = b;
|
||||
} else {
|
||||
dp[i][j] = dp[i + 1][j - 1] && b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//再次dp找到最小分割次数.定义minArr[i]为从0到i的最小分割次数
|
||||
int[] minArr = new int[s.length()];
|
||||
for (int i = 1; i < s.length(); i++) {
|
||||
//定义l,当l->i构成回文串时,此时分割次数为=minArr[l-1]+1.找到最小的l
|
||||
int temp = i;
|
||||
for (int l = 0; l <= i; l++) {
|
||||
if (dp[l][i]) {
|
||||
temp = Math.min(temp, l == 0 ? 0 : minArr[l - 1] + 1);
|
||||
}
|
||||
}
|
||||
minArr[i] = temp;
|
||||
}
|
||||
return minArr[s.length() - 1];
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(new Q132().minCut("aab"));
|
||||
}
|
||||
}
|
||||
```
|
1
算法/leetcode/面试题/xml/q131-字符串切割.drawio
Normal file
1
算法/leetcode/面试题/xml/q131-字符串切割.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2022-03-09T08:30:36.566Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.5.1 Chrome/96.0.4664.110 Electron/16.0.7 Safari/537.36" etag="h-3o1RLJ1HM2kZB66dxQ" version="16.5.1" type="device"><diagram id="XJrWYPWIyDJo6h6NABuz" name="第 1 页">7Vvfk6o2FP5r8rgdQoDAIyjb3pn2oXc703v7xmpUWjQW8ar963sSAoiJF++sgjvuzP4gJxHIOR/n+3KCiIyW+5/zZL34jU9ZhmxrukdkjGzbxwT+CsOhNLiuXxrmeTotTbgxvKT/MWW0lHWbTtmmNbDgPCvSdds44asVmxQtW5LnfNceNuNZ+6rrZM40w8skyXTrn+m0WKhp2bSx/8LS+aK6MvaCsmeZVIPVTDaLZMp3RyYSIzLKOS/Ko+V+xDLhu8ov5eeez/TWN5azVXHJB2afo+h35/O35eJT/GXs//WV7j49OermviXZVs0YxR4KRsi3UExRFCHfR7Er/vq0OvBUV0Dk4FiMj59RNEJBqCZbHCoP5ny7mjJxExYi0W6RFuxlnUxE7w4gA7ZFscygheFwxleFAgEWw5Msna+gkbEZTDJSN8vygu3PugHXzgVQMr5kRX6AIRUi6U9u+RmFSMdSPtg18XWoXY1aHEXXUyMTBap5ffbG73CgXP8DYfA6vMbzYsHnfJVkv3K+Vr76mxXFQTkr2Ra87UlwR374Ij4PM1HNr+p0sjHet1oH1TqOAKldzqbaY3LicLh7vs0n7DuzrJ7fJJ+z4jvjiDmAOcuSIv3Wvo+rh4JqoRBzf1HNFV/Bv+jN0bkDLztDetnvxcvv+Blwh4wO1kghQXSUvL4tt18hedu0nbtdPXXjwNITN7lV4rZ1+rS9TFDVAmbizUvSKi0CVS33ef9uedXxtJF4A/q0MFnvm876LHQkWDcE1i3pN0TRM4p9FGIU+rLLEUYgZD9GoYtiaAJXR5Kix9JS0zgVRO07whKOEXisHBzZ8iASZxCXg/EB8set8T78EHkDDgotYYlKsQCnouJyarbgznLCbSeA+dgzJ3gCZBRt0GyKnP/DRjzjeZMYZmmWnZg2ALt0NQeD27T+kHniyT4HTg5gnGVSlC3S6ZSttKRzBcw6vtXCbA3GY9A6BtAGtwIt1p/v3knPum5aJRemVWyZY9VPXiWGvDp4SiVteNZQPIIn7TOlEqz55F61wZVB7FyqjwcFsaODeHgUE6cbxV6fKHYNXhpePzmEdLrJ9Xp0U3BWP12sliyjWjIoGxAuIyFf4ADsYZSomoU/qkbLSkcwknpK6qCWjCoPAim1qJRFelnEE+KovAY0I/esGuoUPlXlYwKhZSB0IhH4dJJkoepYgmLJZCpk4I3kVZ5KwGjN01UhA+VGyB2Lc0H226ic9QOayrwMehMAMWkL+MCghUxsY99MC+np7L1roap02i2GBi20YL3o9SA8f3mAhq0C6LVhUQbQWayDt66+orKt0xqubajhYmys4d4ukxhqAQ1DyFW5HyRHxCJpCKywhoeVfEk+QC9hAEKhYSZZaA9pdTCuhkdq7V+yl85DAZEUBVcbC0p7d4RzJaxgQtuKh2IdKX6fjGOTh817l67SSw4eLO9dskzvO+fV+4pVxqMG5d6rcDKscO6AGpqNu7txlGGNo/HCUYk1EEuI0G+S+aOm7mptUK9VXS2QvS4VbF0P1ZRdEe1HILsDaRJr/QbSUP/+eCIvCKTfzUH9BjJ4VClVVSm6pRQdUkpVt3n0pL2KncWhZcKpmiL2wCLBNpShPrjlkpRkdQay35Sky2JTFcAWb1M0FQAXRVTWqMs37p5bS/owlot8ubsvIl1WlF/zptZdFwtg2U/lrryHIoIC11Q+0IoFjwod+2TPyFiMxgbw3O5tEmpIl3eXK4deUNn+R668Sq4cWr4R51HlW5VBurf6B92iqW6zS771v9vfXf7vNSURXecekbGWmx41ATknccNDUwnRS73Dv6ShoXtwL3kGdJdK1alErI91YSplLvzqLn0UwGPqtELpYL2GaXr183Yv1+kKUw+lfSaUjxtHm/p3FkeTBj6NIzHE8bGfR+JadxZH0+bQaRwdUxwfN4iO7fYVRGg2X9CUfUffciXx/w==</diagram></mxfile>
|
Loading…
x
Reference in New Issue
Block a user