@@ -206,6 +206,65 @@ public:
206
206
return result;
207
207
}
208
208
};
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
+
209
268
```
210
269
211
270
# 总结
0 commit comments