回溯 时间复杂度 O(n * n!)
时间复杂度分析:
- 第一次从n个数中选 第二次从n - 1个数选… 总共的选择 n!
- 递归结束时 复制数组时间复杂度 O(n)
- 综合1 2 总复杂度 O(n * n!)
每次将选中的数字挪到左侧 下一次在右侧数字中选择
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
'''
把 nums数组分为左右两边 维护一个分界索引
每次把 从剩下的元素中选出的元素挪到左边去
'''
n = len(nums)
res_list = []
def doit(first):
if first == n:
res_list.append(nums[:])
# 每一层都在右侧剩余元素中选择一个元素
for i in range(first, n):
# 选出的元素加入左侧
nums[i], nums[first] = nums[first], nums[i]
# 分界索引+1 去下一层
doit(first + 1)
# 之后 记得把元素再交换回来 开启下一轮循环
nums[i], nums[first] = nums[first], nums[i]
doit(0)
return res_list
使用相同大小的标记数组来表示之前是否选择过
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res_list = []
path = []
nums_len = len(nums)
# 一个相同大小的标记数组 来标记某个下标是否被选择过
selected = [False for _ in range(nums_len)]
def doit():
if len(path) == nums_len:
res_list.append(path[:])
return
for i in range(nums_len):
if not selected[i]:
# 标记选过
selected[i] = True
# 添加值
path.append(nums[i])
doit()
# 回滚
path.pop()
selected[i] = False
doit()
return res_list