class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if len(nums) == 1:
return [nums]
res = []
for sub in self.permute(nums[1:]):
for i in range(len(sub)+1):
res.append(sub[:i]+[nums[0]]+sub[i:])
return res
递归和回溯的概念:
- 递归:一个函数在其定义中直接或间接调用自身的方法。在这个例子中,
permute
函数在定义中调用了自身。 - 回溯:一种通过探索所有可能的候选解来找出所有解的算法。如果候选解被确认不是一个解的话(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化来丢弃该解,即“回溯”。
代码解释:
if len(nums) == 1:
:如果nums
列表只包含一个元素,那么它本身就是一个排列,直接返回包含这个元素的列表。res = []
:初始化一个空列表res
,用于存储所有的排列。for sub in self.permute(nums[1:]):
:对nums
列表的剩余部分(除第一个元素外的部分)进行排列。self.permute(nums[1:])
会递归地生成剩余部分的所有排列。for i in range(len(sub)+1):
:对于每一个子排列sub
,遍历从0到len(sub)
的所有索引。这些索引决定了第一个元素nums[0]
应该插入到sub
的哪个位置。res.append(sub[:i]+[nums[0]]+sub[i:])
:在sub
的第i
个位置之前插入nums[0]
,然后将新的排列添加到res
中。这就是回溯的部分,因为我们在每一步都尝试将nums[0]
插入到不同的位置,然后继续递归处理剩余的元素。
举例:
假设nums = [1, 2, 3]
,我们想生成它的所有排列。
- 初始调用:
self.permute([1, 2, 3])
- 第一次递归调用:
self.permute([2, 3])
- 第二次递归调用:
self.permute([3])
- 返回:
[[3]]
- 返回:
- 将
2
插入到[3]
的每个位置,得到[[2, 3], [3, 2]]
- 第二次递归调用:
- 将
1
插入到每个[2, 3]
和[3, 2]
的位置,得到所有可能的排列:[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]]
这就是整个递归和回溯的过程。最终,我们得到了nums
的所有可能排列。