46. /47.全排列Ⅰ/Ⅱ(中)
46.题目
- 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]
示例 3:
输入:nums = [1]
输出:[[1]]
题解:回溯
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
#nums是选择列表
def backtrack(nums: List[int], track: List[int], res: List[List[int]]):
if len(track) == len(nums):#触发结束条件:nums中的元素全都在track中出现
res.append(track[:]) # 将路径加入结果
return
for i in range(len(nums)):
if nums[i] in track:#排除不合法选择
continue
track.append(nums[i])#做选择
backtrack(nums, track, res)#递归
track.pop() # 撤销选择
res = [] # 结果
track = [] # 路径
backtrack(nums, track, res)
return res
47.题目
- 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
题解:回溯
- 先对数组进行排序,把相同的元素放一起好进行剪枝;used记录每个元素在当前路径中是否已经被使用过。确保每个元素在当前路径中只被选择一次,并且得到不重复的全排列结果。
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
def backtrack(nums: List[int], track: List[int], res: List[List[int]],used:List[bool]):
if len(track) == len(nums):#触发结束条件:nums中的元素全都在track中出现
res.append(track[:]) # 将路径加入结果
return
for i in range(len(nums)):
if used[i]:
continue
#第一个i=0不会重复,由于排好序了,当前与前一个重复就并且前面那个已经记录好了,就进行逃过(即剪枝)
if i>0 and nums[i] == nums[i-1] and not used[i-1]:#排除不合法选择
continue
track.append(nums[i])#做选择
used[i]=True#used[i] 设置为 True,表示该元素已经被使用
backtrack(nums, track, res,used)#递归
track.pop() # 撤销选择
used[i]=False
#对 nums 进行排序,以便相同的元素相邻,为后面的去重操作奠定基础。
nums.sort()
res = [] # 结果
track = [] # 路径
used=[False]*len(nums)#used记录每个元素在当前路径中是否已经被使用过。确保每个元素在当前路径中只被选择一次,并且得到不重复的全排列结果。
backtrack(nums, track, res,used)
return res