回溯法的基本思想:“试探着走”。如果试得不成功退回一步,再换一个方法试。反复进行这种试探性选择与返回纠错过程,直到求出问题的解为止。回溯法又被称为“通用解题法” 。 回溯法在包含问题所有解的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一结点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
代码如下:
def is_palind(s):
if len(s) <= 1:
return True
if s[0] != s[-1]:
return False
return is_palind(s[1:-1]) #递归求解子问题
def search(S,list,index,result):
if(index==len(S)):
result.append(list)
return
for i in range(index,len(S)):
sub = S[index:i+1] #从index到i之间作为子串 sub
if(not is_palind(sub)):
continue
search(S,list+[sub],i+1,result) #递归调用search函数查找剩余子串(i+1到结尾)之间的
if __name__ == "__main__":
s = "abbb"
result = [] #初始化result
search(s,[],0,result) #调用search函数并输出结果result
print(result)
下面再给大家扩展一个知识点:两种典型的解空间树
1、子集树(Subset Trees):当所给问题是从n个元素的集合中找出满足某种性质的子集时,相应的解空间树称为子集树。在子集树中,|S0 |=|S1 |=…=|Sn-1 |=c,即每个结点有相同数目的子树,通常情况下c=2,所以,子集树中共有2n个叶子结点,因此,遍历子集树需要O(2n)时间。(0/1背包问题)
2、排列树(Permutation Trees):当所给问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。 在排列树中,通常情况下,|S0 |=n,|S1 |=n-1,…,|Sn1 |=1,所以,排列树中共有n!个叶子结点,因此,遍历排列树需要O(n!)时间。(旅行售货员问题)