题目: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)