先给出一个例题:
也可以先看后面给出的小鸡例子
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
Input: "aab" Output: [ ["aa","b"], ["a","a","b"] ]
解题思路:先要判断子串是否是回文,然后使用dfs遍历即可
Palindrome的作用是判断输入字符串是否是回文数
flagPalindrome就是标示,如果flagPalindrome[i][j]=1,那么就是说s字符串从i到j位置这一子串是回文数,如果是0那么就不是回文数。
dfs就是遍历得到所有情况,注意
res = temp[:]
res.append(s[start:i+1])
self.dfs(s,i+1,res)
#上面两句不可简写为如下:
temp.append(s[start:i+1])
self.dfs(s,i+1,temp)
因为这里涉及到python的深浅拷贝,如果简写为下面两句话时,那么就是深拷贝(实际上是地址绑定,当母体发生改变时,复制它的那个变量的值也会发生相应的改变),结果就是错的:
笔者这里试了一下会输出:
[ ["a","a","b"] , ["a","a","b","aa","b"]]
一般对于dfs来说比如:
比如我们在上面进行dfs,用一个列表存储列表,开始肯定是1-4-10,此时列表是[1,4,10],然后进行第一次回溯到4,当前列表按理说应该是[1,4]但是当是深拷贝时,列表实际上可以看成是一个全局变量了!会回溯到上步的4,但是上步对应的列表已经被改变啦!正常来说这一步就是这一步的,不应该受下一步的影响,但是由于深拷贝的原因,这里受了影响。
对应到本题如果只是使用temp那么在第一次结束后即["a","a","b"]后,在进行for的下一次循环时,回溯到temp最开始的时候,按理说,这时temp还没有进行任何的append (回溯的过程可以看出就是去掉append的那些步骤),temp就是[] 但由于此时temp实际上已经是["a","a","b"]了,
因为由于深拷贝的原因,它依然悄悄的变为全局变量,后面的每一步其实都在影响改变着当前的temp,所以回溯回来的时候,temp已经不是当初的temp啦!
怎么办呢?当然再令一个临时res,其和temp是两个不同的东西(如果写成res=temp这相当于还是深拷贝,还会得出和上面一样的错误结果),res只是复制了一下temp的值,而并没有像深拷贝那样两者进行了地址绑定。那么此时的res就是[],不管后面temp怎么变化,res的值依然是[]
同样
self.result.append(temp[:])
#不要写成
self.result.append(temp)
如果还是没有懂,笔者再举个不太恰当的例子:
比如一只小鸡从家里出发去外面的世界闯荡,临走时鸡妈妈对她的影响值量化为是A,小鸡先去了北京闯荡了5年,学到不少本领,又去上海闯荡了3年,又学到不少本领,客观上此时的小鸡给人的影响值已经量化为B啦,此时小鸡回家(回缩)从上海北京,从北京到家里,那妈妈的影响值是多少呢?应该还是A,这也是我们使用dfs想看到的结果。
但如果小鸡在闯荡期间,把所见所闻都通过打电话告诉了妈妈,那么其实在妈妈眼里,对孩子的影响值一直都在随着小鸡去不同城市打拼经历变化而变化,当小鸡回溯到家里的时候妈妈对其影响值应该也变为了B,但这不是我们想要的,怎么办呢?
上面我们通过一个res进行了浅拷贝,意思就是说当初小鸡离开的时候妈妈对她的影响值量化为是A,妈妈当场又把这一影响告诉了兔帅哥,尽管以后小鸡和妈妈通电话,妈妈的影响值会改变,但是当小鸡回溯回来时兔帅哥对小鸡的影响依然是A,所以我们此时用兔帅哥的影响值就可以了!对应到程序时就是说我们在递归时用res,而不用temp
最后是完整代码:
class Solution:
def partition(self, s):
"""
:type s: str
:rtype: List[List[str]]
"""
self.flag =[[0 for i in range(len(s))] for j in range(len(s))]
self.result = []
self.flagPalindrome(s)
self.dfs(s,0,[])
return self.result
def Palindrome(self,s):
if s==s[::-1]:
return True
else:
return False
def flagPalindrome(self,s):
for i in range(len(s)):
for j in range(i+1,len(s)+1):
if self.Palindrome(s[i:j]):
self.flag[i][j-1] = 1
self.flag[j-1][i] = 1
def dfs(self,s,start,temp):
if start == len(s):
self.result.append(temp[:])
return
for i in range(start,len(s)):
if self.flag[start][i]==1:
res = temp[:]
res.append(s[start:i+1])
self.dfs(s,i+1,res)