优先搜索算法:包括深度优先搜索和广度优先搜索;深度优先搜索(DFS):在搜索到一个新节点时,立即对该新节点进行遍历;因此遍历需要用先入后出的栈来实现,也可以通过与栈等价的递归来实现;广度优先搜索(BFS):一层层进行遍历,需要用先入先出的队列进行遍历。
回溯法:优先搜索特殊情况,常用于需要记录状态的深度优先搜索。步骤有修改当前节点状态—递归子节点—回改当前节点状态;
1.按引用传状态
2.所有状态修改在递归后完成
回溯法修改一般有两种情况:一是修改最后一位;二是修改访问标记
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
采用回溯算法,对于每一个当前位置i,将其与之后的任意位置进行交换,然后继续处理i+1的位置,知道处理到最后一位,利用回溯算法,只对源数组进行修改,在递归完后再修改回来
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
ans = []
def backtracking(nums,level): #回溯
if level == len(nums)-1:
ans.append(nums[:]) #后续的操作会对nums产生影响,使用nums[:]相当于取nums对应对象的一个视图,后续的操作不会产生影响
return
for i in range(level,len(nums)):
nums[i],nums[level] = nums[level],nums[i] #修改当前节点状态
backtracking(nums,level+1) #递归子节点
nums[i], nums[level] = nums[level], nums[i] #修改回当前节点状态
backtracking(nums , 0)
return ans
注:第一次发现nums值会被后续操作修改,nums[:]相当于对nums拷贝,与nums地址不同
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
示例:
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combinations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
上一题排列回溯,用的是交换位置,这题组合回溯,用的是把当前的数字加入结果中
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
ans = []
com = [None] * k #初始化
count = 0 #位置标记
def backtracking(com,count,pos): #回溯
if count == k:
ans.append(com[:])
return
for i in range(pos,n+1):
com[count] = i #修改当前节点状态
count += 1 #修改当前节点位置标记
backtracking(com,count,i+1) #递归子节点
count -= 1 #修改回当前节点
backtracking(com,count,1)
return ans
当然回溯在python有内置函数 itertools库内置了这个函数可以直接调用
所以以上两题均可直接调用函数
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
"""LeetCode 46 全排列 itertools库内置了这个函数"""
return itertools.permutations(nums)
###########################################################
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
"""LeetCode 77 组合 itertools库内置了这个函数"""
return list(itertools.combinations(range(1,n+1),k))
##########################################################
def backtracking(状态, 条件列表):
"""回溯通用参考模板"""
if 满足结束条件:
结果.append(状态)
return
for 条件 in 条件列表: # 核心代码段
修改当前节点状态
递归子节点执行backtracking()
修改回当前节点