Skip to content

Commit

Permalink
修改
Browse files Browse the repository at this point in the history
  • Loading branch information
arkingc committed Jul 6, 2018
1 parent 2eafe7f commit 6faf320
Showing 1 changed file with 61 additions and 3 deletions.
64 changes: 61 additions & 3 deletions 数据结构与算法/算法题总结.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,14 @@
- *字符串转换*
+ Leetcode91:[数字字符串解码](#数字字符串解码)(`动态规划` `medium`)
+ Leetcode127:[单词阶梯](#单词阶梯)(`BFS` `medium`)
- *子串与拆分*
- *子串与子序列*
+ Leetcode28:[字符串查找](#字符串查找)(`KMP` `easy`)
+ Leetcode3:[不含重复字符的最长子串](#不含重复字符的最长子串)(`哈希表` `medium`)
+ Leetcode395:[至少有K个重复字符的最长子串](#至少有k个重复字符的最长子串)(`哈希表` `medium`)
+ Leetcode5:[最长回文子串](#最长回文子串)(`动态规划` `medium`)
+ Leetcode125:[判断字符串是否是回文串](#判断字符串是否是回文串)(`双指针` `easy`)
+ Leetcode131:[分割回文串](#分割回文串)(`DFS` `medium`)
- *字符串拆分*
+ Leetcode131:[分割回文串](#分割回文串)(`动态规划` `DFS` `medium`)
+ Leetcode139:[单词拆分I](#单词拆分i)(`动态规划` `medium`)
+ Leetcode140:[单词拆分II](#单词拆分ii)(`动态规划` `hard`)
- *字符串匹配*
Expand Down Expand Up @@ -9876,13 +9877,17 @@ public:

### 解答

#### 1)DFS

对于字符串str,遍历从下标0开始的每一个子串:

* 如果子串[0,i]是回文,则将子串添加到路径,递归处理剩余子串[i+1,n]
* 如果子串[0,i]不是回文,处理下一个子串[0,i+1]
* 如果字符串str为空,表示已经递归处理(dfs)到结尾,那么将这条路径添加到结果中
* 如果字符串str为空,表示已经递归处理(DFS)到结尾,那么将这条路径添加到结果中
* 每处理完一条路径,递归返回时,需要将之前添加到路径结尾的回文串[0,i]弹出

> DFS会求重复子问题,比如”aabcd“,判断"a"是回文时,递归处理"abcd"时判断"a"是回文,进而 会求"bcd";往后在判断"aa"是回文时,也会递归处理“bcd”

```c++
class Solution {
public:
Expand Down Expand Up @@ -9920,6 +9925,59 @@ private:
};
```

#### 2)动态规划

> 这种解法结合[单词拆分II](#单词拆分ii)一起分析,是求类似问题的通用解法

对于`“aaabc”`:

* 如果`“aaabc”`是回文,那么单独构成一个解
* 如果`“aabc”`是回文,那么递归求出`“a”`的结果,在结果的每个解后面`push_back`回文`"aabc"`,得到了一组解
* 如果`“abc”`是回文,那么递归求出`“aa”`的结果,在结果的每个解后面`push_back`回文`"abc"`,得到了一组解
* ...
* 如果`“c”`是回文,那么递归求出`“aabc”`的结果,在结果的每个解后面`push_back`回文`"aabc"`,得到了一组解

在递归过程中,为了防止求重复子问题,使用`mem`保存状态,即每个子问题的解,如果后续需要求相同子问题的解,可以从`mem`中直接取出结果

```c++
class Solution {
public:
vector<vector<string>> partition(string s) {
unordered_map<int,vector<vector<string>>> mem;
partition(s,s.length() - 1,mem);
return mem[s.length() - 1];
}
private:
void partition(const string &s,int r,unordered_map<int,vector<vector<string>>> &mem){
if(mem.find(r) != mem.end()) return;

if(isPalindrome(s.substr(0,r + 1)))
mem[r].push_back(vector<string>({s.substr(0,r + 1)}));

for(int len = r;len >= 1;len--){//右边子串的长度
int leftLen = r + 1 - len;
const string &right = s.substr(leftLen,len);
if(isPalindrome(right)){
partition(s,leftLen - 1,mem);
for(vector<string> left : mem[leftLen - 1]){
left.push_back(right);
mem[r].push_back(left);
}
}
}
}

bool isPalindrome(const string &s){
int i = 0,j = s.length() - 1;
while(i < j && s[i] == s[j]){
i++;
j--;
}
return i >= j;
}
};
```

<br>
<br>

Expand Down

0 comments on commit 6faf320

Please sign in to comment.