【回溯】总结

记忆化搜索:

from functools import cache
@cache
def dfs()
from functools import lru_cache
# 其中maxsize为最大缓存数量,默认为128。None则无限制。
# typed=True时不同参数类型的调用将分别缓存,默认False
@lru_cache(maxsize=128, typed=False)
def dfs()

1、 组合和子集问题

组合问题需要满足一定要求才算作一个答案,比如数量要求(k个数),累加和要求(=target)。
子集问题是只要构成一个新的子集就算作一个答案。

进阶:去重逻辑。

  1. 一般都是要对同层去重。比如[1,1,2,2,2]
    放置第一个位置的数时,如果已经使用过第一个1了,那么他的所有组合和子集一定包含第二个1,所以去重逻辑就是同层不能出现相同的数
  • 对于一个顺序数组,通常直接与前一个数比较即可。
for i in range(index+1, n):
	if i==index+1 or nums[i]!=nums[i-1]:
		dfs(i,[],target)
  • 对于一个乱序数组,则需要用哈希表存储同层出现过的数。
hash = set()
for i in range(index+1, n):
    if i==index+1 or (nums[i] not in hash):
        hash.add(nums[i])
        dfs(i, [])
  1. 实际上上面的两段代码还蕴含了另一个去重,即不同层不能用同一个下标的数,所以这里索引时是从index+1开始

2、分割问题

我们定义[start:end] **(左闭右闭)**这段区间为分割出来的子串,对他进行条件判断。在python中对应的是s[start: end+1],end指向某个字符后面,表示切割到这个字符。start则为上一步的end+1。可以看下面这幅图,比较直观。理解了怎么分割字符串,剩下的就套回溯的模板就可以了。
在这里插入图片描述

    def partition(self, s: str) -> List[List[str]]:
        n = len(s)
        res = []

        def ishuiwen(s):
            return s==s[::-1]

        def dfs(start,end,stack):
            ss = s[start:end+1]
            if not ishuiwen(ss):
                return
            stack.append(ss)
            if end == n-1:
                res.append(stack.copy())
                return 
            
            for i in range(end+1,n):
                dfs(end+1, i, stack.copy())
            
        for i in range(n):
            dfs(0, i, [])
        return res

猜你喜欢

转载自blog.csdn.net/LoveJSH/article/details/132351212
今日推荐