Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dee5d5d

Browse files
Merge pull request youngyangyang04#1591 from YukunJ/updates
Update: 增加<131.分割回文串>优化代码
2 parents 69b5fb5 + 3fdf448 commit dee5d5d

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

‎problems/0131.分割回文串.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,65 @@ public:
206206
return result;
207207
}
208208
};
209+
```
210+
# 优化
211+
212+
上面的代码还存在一定的优化空间, 在于如何更高效的计算一个子字符串是否是回文字串。上述代码```isPalindrome```函数运用双指针的方法来判定对于一个字符串```s```, 给定起始下标和终止下标, 截取出的子字符串是否是回文字串。但是其中有一定的重复计算存在:
213+
214+
例如给定字符串```"abcde"```, 在已知```"bcd"```不是回文字串时, 不再需要去双指针操作```"abcde"```而可以直接判定它一定不是回文字串。
215+
216+
具体来说, 给定一个字符串`s`, 长度为```n```, 它成为回文字串的充分必要条件是```s[0] == s[n-1]```且```s[1:n-1]```是回文字串。
217+
218+
大家如果熟悉动态规划这种算法的话, 我们可以高效地事先一次性计算出, 针对一个字符串```s```, 它的任何子串是否是回文字串, 然后在我们的回溯函数中直接查询即可, 省去了双指针移动判定这一步骤.
219+
220+
具体参考代码如下:
221+
222+
```CPP
223+
class Solution {
224+
private:
225+
vector<vector<string>> result;
226+
vector<string> path; // 放已经回文的子串
227+
vector<vector<bool>> isPalindrome; // 放事先计算好的是否回文子串的结果
228+
void backtracking (const string& s, int startIndex) {
229+
// 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
230+
if (startIndex >= s.size()) {
231+
result.push_back(path);
232+
return;
233+
}
234+
for (int i = startIndex; i < s.size(); i++) {
235+
if (isPalindrome[startIndex][i]) { // 是回文子串
236+
// 获取[startIndex,i]在s中的子串
237+
string str = s.substr(startIndex, i - startIndex + 1);
238+
path.push_back(str);
239+
} else { // 不是回文,跳过
240+
continue;
241+
}
242+
backtracking(s, i + 1); // 寻找i+1为起始位置的子串
243+
path.pop_back(); // 回溯过程,弹出本次已经填在的子串
244+
}
245+
}
246+
void computePalindrome(const string& s) {
247+
// isPalindrome[i][j] 代表 s[i:j](双边包括)是否是回文字串
248+
isPalindrome.resize(s.size(), vector<bool>(s.size(), false)); // 根据字符串s, 刷新布尔矩阵的大小
249+
for (int i = s.size() - 1; i >= 0; i--) {
250+
// 需要倒序计算, 保证在i行时, i+1行已经计算好了
251+
for (int j = i; j < s.size(); j++) {
252+
if (j == i) {isPalindrome[i][j] = true;}
253+
else if (j - i == 1) {isPalindrome[i][j] = (s[i] == s[j]);}
254+
else {isPalindrome[i][j] = (s[i] == s[j] && isPalindrome[i+1][j-1]);}
255+
}
256+
}
257+
}
258+
public:
259+
vector<vector<string>> partition(string s) {
260+
result.clear();
261+
path.clear();
262+
computePalindrome(s);
263+
backtracking(s, 0);
264+
return result;
265+
}
266+
};
267+
209268
```
210269

211270
# 总结

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /