回溯算法05 | *491.递增子序列 *46.全排列 47.全排列 II

*491.递增子序列

https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html
视频讲解:https://www.bilibili.com/video/BV1EG4y1h78v

  • 考点
    • 回溯+子集+去重
  • 我的思路
    • 暴力法,不进行去重,仅在最后加入结果时判断当前子序列是否之前出现过
    • 能通过力扣,但是效率排在后10%
  • 视频讲解关键点总结
    • 重点在于去重逻辑和判断递增子序列的逻辑
    • 本题的树结构
    • 去重逻辑:由于本题的数组不是有序数组,因此对于重复的元素,需要使用的判断条件是其是否在同一树层出现过,而不是同一树层的前一元素;为此,需要使用哈希结构(数组或集合)记录同一树层中已出现元素的情况
    • 判断递增子序列的逻辑:在将当前元素加入子序列之前,先判断该元素是否小于子序列的最后一个元素,如果小于,就跳过当前元素;这样,所得到的所有子序列就全都是递增的了,不需要进行额外判断,能提升一些效率
  • 我的思路的问题
    • 运行效率慢
  • 代码书写问题
    • list.sort()没有返回值,因此想要把排序后的列表和其它列表进行比对,要先进行sort,再用列表本身进行对比
  • 可执行代码
# 暴力法
class Solution:
    def backtracking(self, nums, sequence, result, start_index):
        if start_index == len(nums):
            return
        for i in range(start_index, len(nums)):
            sequence.append(nums[i])
            cur = sequence[:]
            cur.sort()
            if len(sequence) >= 2 and cur == sequence and sequence not in result:
                result.append(sequence[:])
            self.backtracking(nums, sequence, result, i + 1)
            sequence.pop()

    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        result = []
        self.backtracking(nums, [], result, 0)
        return result
# 过程去重版(去掉了判断sequence in result,效率提升70-80倍)
class Solution:
    def backtracking(self, nums, sequence, result, start_index):
        used = set()
        if start_index == len(nums):
            return
        for i in range(start_index, len(nums)):
            if sequence and nums[i] < sequence[-1]:
                continue
            elif nums[i] in used:
                continue
            used.add(nums[i])
            sequence.append(nums[i])
            if len(sequence) >= 2:
                result.append(sequence[:])
            self.backtracking(nums, sequence, result, i + 1)
            sequence.pop()

    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        result = []
        self.backtracking(nums, [], result, 0)
        return result

*46.全排列

https://programmercarl.com/0046.%E5%85%A8%E6%8E%92%E5%88%97.html
视频讲解:https://www.bilibili.com/video/BV19v4y1S79W

  • 考点
    • 回溯+排列
  • 我的思路
    • 无思路
  • 视频讲解关键点总结
    • 排列问题也是依次取值然后逐步生成完整的排列
    • 回溯三要素
      • 形参:候选数组,候选数组使用情况used,单个排列,结果变量;返回值为空
      • 退出条件:当单个排列的长度等于候选数组时,将排列加入结果并返回
      • 回溯逻辑
        • 循环范围为候选数组:
          • 如果当前元素已经被使用过了(used对应标志位为1),则跳过当前元素
          • 将当前元素的used数组对应位置标记为1
          • 当前元素加入排列
          • 递归
          • 当前元素弹出
          • used标记位改回0
  • 我的思路的问题
    • 无思路
  • 代码书写问题
  • 可执行代码
class Solution:
    def backtracking(self, nums, used, permutation, result):
        if len(permutation) == len(nums):
            result.append(permutation[:])
            return
        for i in range(len(nums)):
            if used[i] == 1:
                continue
            used[i] = 1
            permutation.append(nums[i])
            self.backtracking(nums, used, permutation, result)
            permutation.pop()
            used[i] = 0

    def permute(self, nums: List[int]) -> List[List[int]]:
        result = []
        used = [0] * len(nums)
        self.backtracking(nums, used, [], result)
        return result

47.全排列 II

https://programmercarl.com/0047.%E5%85%A8%E6%8E%92%E5%88%97II.html
视频讲解:https://www.bilibili.com/video/BV1R84y1i7Tm

  • 考点
    • 回溯+排列+去重
  • 我的思路
    • 本题就是在上一题的基础上,加上树层去重即可
  • 视频讲解关键点总结
    • 和我的思路一致
  • 我的思路的问题
  • 代码书写问题
  • 可执行代码
class Solution:
    def backtracking(self, nums, used, permutation, result):
        if len(permutation) == len(nums):
            result.append(permutation[:])
            return
        for i in range(len(nums)):
            if used[i] == 1 or (i > 0 and nums[i] == nums[i - 1] and used[i - 1] == 0):
                continue
            used[i] = 1
            permutation.append(nums[i])
            self.backtracking(nums, used, permutation, result)
            permutation.pop()
            used[i] = 0

    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        result = []
        used = [0] * len(nums)
        self.backtracking(nums, used, [], result)
        return result
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值