46.全排列
这里和77.组合问题 (opens new window)、131.切割问题 (opens new window)和78.子集问题 (opens new window)最大的不同就是for循环里不用startIndex
了。
因为排列问题,每次都要从头开始搜索
,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。 就是每一层可以重复 树枝上的路径的数不可以重复
而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次。
不用used判断
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
path = []
res = []
# used = [False] * len(nums)
'''
因为本题排列是有序的,这意味着同一层的元素可以重复使用,但同一树枝上不能重复使用
所以处理排列问题每层都需要从头搜索,故不再使用start_index
'''
def backtracking(nums):
if len(path) == len(nums):
res.append(path[:])
return
for i in range(0,len(nums)):
# 若遇到path里已收录的元素,跳过
if nums[i] in path:
continue
path.append(nums[i])
backtracking(nums)
path.pop()
backtracking(nums)
return res
用used判断
class Solution:
def __init__(self):
self.path = []
self.paths = []
def permute(self, nums: List[int]) -> List[List[int]]:
'''
因为本题排列是有序的,这意味着同一层的元素可以重复使用,但同一树枝上不能重复使用(usage_list)
所以处理排列问题每层都需要从头搜索,故不再使用start_index
'''
usage_list = [False] * len(nums)
self.backtracking(nums, usage_list)
return self.paths
def backtracking(self, nums: List[int], usage_list: List[bool]) -> None:
# Base Case本题求叶子节点
if len(self.path) == len(nums):
self.paths.append(self.path[:])
return
# 单层递归逻辑
for i in range(0, len(nums)): # 从头开始搜索
# 若遇到self.path里已收录的元素,跳过
if usage_list[i] == True:
continue
usage_list[i] = True
self.path.append(nums[i])
self.backtracking(nums, usage_list) # 纵向传递使用信息,去重
self.path.pop()
usage_list[i] = False
47.全排列 II
树层中去重
// used[i - 1] == true,说明同一树枝
nums[i - 1]使用过
// used[i - 1] == false,说明同一树层
nums[i - 1]使用过
// 如果同一树层nums[i - 1]使用过则直接跳过
如果要对树层中前一位去重,就用used[i - 1] == false,
如果要对树枝前一位去重用used[i - 1] == true。
对于排列问题
,树层上去重和树枝上去重,都是可以的,但是树层上去重效率更高!
层间去重
class Solution(object):
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
# 因为含有重复数 先排序去重 参考三数之和 层间去重 同一层不使用重复的数
nums.sort()
path = []
res = []
used = [0] * len(nums)
def backtracking(nums, used):
if len(path) == len(nums):
res.append(path[:])
return
for i in range(len(nums)):
# 当前数和前一个数相同 且前一个数没有被使用 说明 层间有两个的数 2 1 1
if i>=1 and nums[i] == nums[i-1] and used[i -1] == 0:
continue
# 如果当前这个数没被使用过
if used[i] == 0:
used[i] = 1
path.append(nums[i])
backtracking(nums, used)
path.pop()
used[i] = 0
backtracking(nums, used)
return res