题目描述
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
示例:
输入: “aab”
输出:
[
[“aa”,“b”],
[“a”,“a”,“b”]
]
解决思路
这个题一看就是使用回溯算法,但是看见回溯就脑袋疼,可能是还没有转过弯来。最后看了一下别人的思路,还是三要素啊三要素,终止条件,条件(啥时候继续进行)以及选择(这一步干啥)。
递归的时候其实就是把问题当成一个只有2步或者3步的事,以小见大。回溯是每一个子答案结束之后,能够回到子答案生成之前的状态。
这个题的思路是这样的,先放进去第一个字符,是不是满足条件?如果满足,前进,再放第二个,以此类推,如果一直满足,则把答案记录在册。不满足则退出。
条件就是是不是回文字符串了,终止条件就是可以方入的字符串为空或者说长度为0。选择指的是放入几个?
这个东西不能钻进去妄图追踪计算机一步一步的细节,否则得不偿失,刚刚又妄图追踪,结果又把自己绕晕了。
代码如下,这次用python写的,一会用java写一遍。
class Solution:
def partition(self, s):
"""
:type s: str
:rtype: List[List[str]]
"""
res = []
sub_res = []
self.helper(res,s,sub_res)
return res
def helper(self,res,s,sub_res):
if(len(s)==0):
res.append(sub_res[:])(2)
for i in range(1,len(s)+1):
if self.isPalindrome(s[:i]):
sub_res.append(s[:i])
self.helper(res,s[i:],sub_res)
sub_res.pop() #(1)
def isPalindrome(self,s):
if(len(s)==0):
return False
i =0
j=len(s)-1
while(i<=j):
if s[i] != s[j]:
return False
i+=1
j-=1
return True
(1)处就是这个题中的回溯了,其实可以用sub_res+[s[:i]]的写法,但是自我感觉不如使用上面的写法表达的回溯更加清晰,sub_res+[s[:i]]的回溯是隐式的。(小白,写的不对的地方,还请大佬指教。)
在(2)处不要直接使用sub_res本身,因为python里面除了基本类型其他的都是引用,也可以使用copy函数。
java代码(好坑啊,把<=写成了<,导致调了半天。要注意,结束条件是字符串为空或者说字符长度为0的时候,也就是s.sunstring(s.length(),s.length())的时候才会满足终止条件,如果i到达不了s.length(),那就永远不会满足终止条件,自然答案不会被添加了。
class Solution
{
public List<List<String>> partition(String s)
{
List<List<String>> ans = new ArrayList<>();
List<String> sub_ans = new ArrayList<>();
help(ans, sub_ans, s);
return ans;
}
private void help(List<List<String>> ans, List<String> sub_ans, String s)
{
System.out.println("S.LENGTH:"+s.length());
if (s.length() == 0) {
ans.add(new ArrayList<String>(sub_ans));
System.out.println(11111);
}
for (int i = 0; i <= s.length(); i++)
{
if (check(s.substring(0, i)))
{
sub_ans.add(s.substring(0, i));
help(ans, sub_ans, s.substring(i, s.length()));
sub_ans.remove(sub_ans.size() - 1);
}
}
}
private boolean check(String s)
{
if(s.length()==0)
return false;
int i = 0;
int j = s.length() - 1;
while (i <= j)
{
if (s.charAt(i) != s.charAt(j))
return false;
i++;
j--;
}
return true;
}
}