leetcode刷题记录【回溯递归类题目】—Python代码+详细注释

题目:473. 火柴拼正方形
难度:中等
算法:回溯+剪枝

# 2022.08.28
class Solution:
    def makesquare(self, matchsticks: List[int]) -> bool:
    # 递归/回溯
        # 如果总数不是4的倍数,不行
        if sum(matchsticks) % 4:
            return False
        # 如果最大的边长>平均下来的边长,不行
        edge = sum(matchsticks) // 4
        if max(matchsticks) > edge:
            return False

        n = len(matchsticks)
        edge_tmp = [0] * 4
        # 倒着排序递归的更快
        matchsticks = sorted(matchsticks, reverse = True)

        # 递归走起
        def dfs(index):
            if index == n:
                return True
            # 穷举每个桶
            for i in range(4):
                # 选择装进第i个桶
                edge_tmp[i] += matchsticks[index]
                # print("桶号 = ", i, "的时,数字角度index = ", index, ", 桶edge = ", edge_tmp)
                
                # 递归之前先剪枝
                # 如果桶装装满了,就可以跳过这个桶i了,相当于:
                # if (bucket[i] + nums[index]) > target:
                #     continue
                # 没装满的话,再继续
                if edge_tmp[i] <= edge:  # 判断的是桶
                    # 递归穷举下一个数字的选择
                    if dfs(index + 1):  # 判断的是数字
                        return True
                # 撤销选择
                edge_tmp[i] -= matchsticks[index]
            return False
        return dfs(0)

# 输入[1,1,2,2,2]
# 桶号 =  0 的时,数字角度index =  0 , 桶edge =  [2, 0, 0, 0]--第0个数放到第一个桶,OK

# 桶号 =  0 的时,数字角度index =  1 , 桶edge =  [4, 0, 0, 0]--第1个数放到第一个桶,不行
# 桶号 =  1 的时,数字角度index =  1 , 桶edge =  [2, 2, 0, 0]--第1个数放到第二个桶,OK,可以直接递归下一个数字了
#                                                         --第1个数放到第三个桶,被剪枝
#                                                         --第1个数放到第四个桶,被剪枝

# 桶号 =  0 的时,数字角度index =  2 , 桶edge =  [4, 2, 0, 0]--第2个数放到第一个桶,不行
# 桶号 =  1 的时,数字角度index =  2 , 桶edge =  [2, 4, 0, 0]--第2个数放到第二个桶,不行
# 桶号 =  2 的时,数字角度index =  2 , 桶edge =  [2, 2, 2, 0]--第2个数放到第三个桶,OK
#                                                         --第2个数放到第四个桶,被剪枝

# 桶号 =  0 的时,数字角度index =  3 , 桶edge =  [3, 2, 2, 0]
# 桶号 =  1 的时,数字角度index =  3 , 桶edge =  [2, 3, 2, 0]
# 桶号 =  2 的时,数字角度index =  3 , 桶edge =  [2, 2, 3, 0]
# 桶号 =  3 的时,数字角度index =  3 , 桶edge =  [2, 2, 2, 1]

# 桶号 =  0 的时,数字角度index =  4 , 桶edge =  [3, 2, 2, 1]
# 桶号 =  1 的时,数字角度index =  4 , 桶edge =  [2, 3, 2, 1]
# 桶号 =  2 的时,数字角度index =  4 , 桶edge =  [2, 2, 3, 1]
# 桶号 =  3 的时,数字角度index =  4 , 桶edge =  [2, 2, 2, 2]

题目:46. 全排列
难度:中等
算法:回溯

# 2022.03.03
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def backtrack(nums, depth, path, used, ans):
            # 遍历到底就加进答案
            if depth == len(nums):
                ans.append(path[:]) # 添加用path[:]而不是path,复制值而不是地址
                return
            for i in range(len(nums)):
                # 如果used[i]标记的是未遍历
                # if not used[i]:
                if used[i] == False:
                    # 把本nums[i]点加入路径,并标记为true
                    used[i] = True
                    path.append(nums[i])
                    # depth记录加一
                    backtrack(nums, depth + 1, path, used, ans)
                    # 撤销
                    path.pop()
                    used[i] = False
        # 在原def下--定义的backtrack函数之外--初始化这些变量
        depth = 0
        path = []
        used = [False for _ in range(len(nums))]
        ans = []
        # 运行backtrack函数
        backtrack(nums, depth, path, used, ans)
        return ans

题目:剑指Offer38. 字符串的排列
难度:中等
算法:回溯

# 2022.03.04
class Solution:
    def permutation(self, s: str) -> List[str]:
        nums = list(s)
        # 为下面去重做准备
        nums = sorted(nums)
        def dfs(nums, depth, path, used, ans):
            if depth == len(nums):
                ans.append(''.join(path))  # path携写成nums的时候输出了6个“abc”
                return
            for i in range(len(nums)):
                # 去重--由于已排序,从第二个起,如果和上一个字符一样且上一个没记录进路径
                if i > 0 and nums[i] == nums[i - 1] and used[i - 1] == False:
                    continue
                if used[i] == False:
                    # 加入
                    path.append(nums[i])
                    used[i] = True
                    # depth+1
                    dfs(nums, depth + 1, path, used, ans)
                    # 撤销
                    path.pop()
                    used[i] = False
        # 初始化
        depth = 0
        path = []
        used = [False for _ in range(len(nums))]
        ans = []
        # 执行dfs函数
        dfs(nums, depth, path, used, ans)
        return ans

题目:50. Pow(x, n)
难度:中等
算法:递归

# 2022.07.23
class Solution:
    def myPow(self, x: float, n: int) -> float:
        def binary(n):
            # 递归
            if n == 0:
                return 1
            y = binary(n//2)
            return y*y if n%2==0 else x*y*y
        return binary(n) if n>0 else 1/binary(-n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值