131. 分割回文串
题目链接:
给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是 回文串 。返回 s
所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a"
输出:[["a"]]
提示:
-
1 <= s.length <= 16
-
s
仅由小写英文字母组成
解题思路
我觉得本题最大的难点在于:不知道如何将切割问题抽象为组合问题。
如下图所示,可以将切割问题抽象为一棵树形结构,for循环用来横向遍历,递归用来纵向遍历。同时递归函数参数需要 start
,因为切割过的地方,不能重复切割,和组合问题也是保持一致的。从图中可以看出,当statr
不小于s
的长度时,就可以找到一组分割方案。当然在分割的过程中还需要判断分割产生的子串是否是回文。
C++
class Solution { public: vector<vector<string>> result; vector<string> path; void backTracking(string s, int start) { // 当 起始位置 不小于 s 的大小,说明已经找到了一组分割方案了 if (start >= s.size()) { result.push_back(path); return; } for (int i = start; i < s.size(); i++) { // 判断将被截取的字符串[start,i]是不是回文 // 如果是,则截取并保存,继续纵向遍历 // 如果不是,则横向遍历 bool flag = isPalindrome(s, start, i); if (flag) { // substr(start, length) 返回一个从指定位置开始的指定长度的子字符串 // star 所需的子字符串的起始位置 字符串中的第一个字符的索引为 0 // lenght 在返回的子字符串中应包括的字符个数 string str = s.substr(start, i - start + 1); path.push_back(str); backTracking(s, i + 1); // // 纵向继续找i+1为起始位置的子串 path.pop_back(); // 回溯过程,弹出此次已填子串 } } } //判断一个字符串是不是回文 bool isPalindrome(string s, int i, int j) { while (i < j) { if (s[i] != s[j]) return false; i++; j--; } return true; } vector<vector<string>> partition(string s) { path.clear(); result.clear(); backTracking(s, 0); return result; } };
JavaScript
let path = []; let result = []; const backTracking = (s, start) => { if (start >= s.length) { result.push([...path]); return; } for (let i = start; i < s.length; i++) { if (isPalindrome(s, start, i)) { let str = s.substr(start, i - start + 1); path.push(str); backTracking(s, i + 1); path.pop(); } } } const isPalindrome = (s, i, j) => { while (i < j) { if (s[i] != s[j]) return false; i++; j--; } return true; } var partition = function(s) { path = []; result = []; backTracking(s, 0); return result; };