回溯

力扣一篇关于回溯的解析,后面给了很多例题:回溯解析及例题

知乎关于回溯的文章:知乎回溯

回溯能解决的问题:
组合、排列、切割、子集、棋盘问题、解数独

回溯法在结局问题的时候都可以抽象成一颗n叉树

回溯的模板:
函数无返回值,函数名backtrack()

res = []    # 定义全局变量保存最终结果
state = []  # 定义状态变量保存当前状态
p,q,r       # 定义条件变量(一般条件变量就是题目直接给的参数)
def backtrack(状态,条件1,条件2,……):
    if # 不满足合法条件(可以说是剪枝)
        return
        
    elif # 状态满足最终要求
        res.append(state)   # 加入结果
        return 
        
    # 主要递归过程,一般是带有 循环体 或者 条件体
    for # 满足执行条件,注意起点
	    if  # 满足执行条件
	        backtrack(状态,条件1,条件2,……)
back(状态,条件1,条件2,……)
return res

关于排列的问题,回溯有着天然的优势,换句话说,对于排列的问题,第一个想到的就是回溯,
使用回溯来排列,难点就是去重的问题,去重有两种,一种是不允许有任何重复的元素(其本身没有重复的元素),还有一种就是排序前的本身有相同的元素,但是排列的时候不区分它们,比如 1,2l , 2 和1, 2, 2l 虽然两个2不相同,但是是属于一个相同的排序,要把这一部分剪枝掉

以下面这题为例:
力扣M47 全排列2
如果视两个不同的1 为不同的元素,那么代码为:

def permuteUnique(self, nums: List[int]) -> List[List[int]]:
    n = len(nums)
    ans = []
    # not_in 就是还没有进入排列的数
    #  al_in就是已经排列过的数
    def backtrack(not_in, al_in):
        if not not_in:
            ans.append(al_in)
        for i in range(len(not_in)):
            backtrack(not_in[:i]+not_in[i+1:], al_in+[not_in[i]])
    backtrack(nums, [])
    return ans

如果这两个2是一个,那就需要去重,去重的方法为先对nums进行排序,将相同的数全部放到一起,在for的时候,当当前的数==前一个数的时候直接continue,因为上一个2已经包括了我这个2的所有情况

def permuteUnique(self, nums: List[int]) -> List[List[int]]:
    ans = []
    # sort是为了把所有相同的数放到一起
    nums.sort()
    def back(not_in, al_in):
        # 如果没有进来的已经没有了(全部都进来了)
        if not not_in:
            ans.append(al_in)
            return
        else:
            for i in range(len(not_in)):
            # 区别就在这里,但是一定要先排序
                if i>0 and not_in[i]==not_in[i-1]:
                    continue
                else:
                    back(not_in[:i]+not_in[i+1:], al_in+[not_in[i]])
    back(nums, [])
    return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值