重温回溯算法(2)
继 [Leetcode] 每日两题 46 112 -day98重温回溯算法(1)
继 [Leetcode] 每日两题 51 100 -day99 重温回溯算法(2)
回溯算法的思路就是把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。本质上还是暴力枚举。使用的思想和DFS类似。
详细描述 :
回溯法按深度优先策略搜索问题的解空间树。
首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。
如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。
回溯法的基本行为是搜索,搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类:1. 使用约束函数,剪去不满足约束条件的路径;2.使用限界函数,剪去不能得到最优解的路径。
698. 划分为k个相等的子集
这个题就是一个暴力遍历,直到找到满足放置条件的一种放法,然后要加快速度的话需要剪枝,这里我就稍微剪了一下,写的有点乱。之后等脑子清晰点的时候再优化一下。(也就是不优化了)
class Solution:
def canPartitionKSubsets(self, nums: List[int], k: int) -> bool:
sumn = sum(nums)
dic = defaultdict(int)
one = sumn//k
if sumn/k != one:
return False
nums.sort(reverse=True)
brk = [[] for _ in range(k)]
brk[0].append(nums[0])
flag = False
def dfs(tbrk,nowk,lis):
nonlocal flag
if flag :
return
if sum(tbrk[nowk]) == one:
if nowk ==k-1:
flag =True
return True
tmp = tbrk.copy()
nowk+=1
tmp[nowk].append(lis[0])
dfs(tmp,nowk,lis[1:])
elif sum(tbrk[nowk]) >one:
return False
else :
for i in range(len(lis)-1,-1,-1):
tmp= copy.deepcopy(tbrk)
tmp[nowk].append(lis[i])
dfs(tmp,nowk,lis[:i]+lis[i+1:])
tmlis = lis[:i]+lis[i+1:]
dfs(brk,0,nums[1:])
return flag
78. 子集
子集问题 ,每次递归都将当前list 加入res中,对于 nums中的每个数,可以规定当前从第几位开始选择,一开始可以有三个选择,对于其中的每个选择又有不定项个选择。
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res =[]
def dfs(s,lis):
res.append(lis)
#print(lis)
for i in range(s,len(nums)):
tmp = lis.copy()
tmp.append(nums[i])
dfs(i+1,tmp)
dfs(0,[])
return res