https://leetcode-cn.com/problems/permutations/
# -*- coding:utf-8 -*-
class Solution(object):
def permute(self, nums):
def backtrack(i, flag_list, temp_list=[]):
if i == n:
output.append(temp_list)
return
# 找到第一个可用数字
for j in range(len(flag_list)):
if flag_list[j] != 0:
flag_list[j] = 0
temp_list.append(nums[j])
backtrack(i + 1, flag_list[:], temp_list[:])
flag_list[j] = 1
temp_list = temp_list[:-1]
n = len(nums)
output = []
flag_list = [1 for _ in range(n)]
backtrack(0, flag_list)
return output
if __name__ == '__main__':
nums = [1, 2, 3]
print(Solution().permute1(nums))
思路:回溯法,首先选择一个数字,然后向下递归下一位和当前可选数字,如果满足条件就添加到输出列表中,然后回溯,回溯的操作包括将使用标记从0变为1,将当前临时结果列表中剔除最后一个数字。
思考:有一个不用标记列表的方法,就是向后交换,因为是交换,也省去了临时列表等空间,但是实际提交和上一个方法相比较,空间上并没有区别,反而是时间上有了区别,我也不是很懂为啥。
使用交换来模拟每次寻找可用数字,举个例子,1,2,3,4这个列表,如果我们处理第一位时,1,2,3,4都是可用数字,因此我们可以用1分别与后面的数字进行交换,这样idx0就分别取到了所有数字。当固定了1时,我们继续分析2,3,4,依然是交换,这样可以固定新的idx0(也就是旧列表的idx1),以此类推。
def permute1(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtrack(first=0):
if first == n:
output.append(nums[:])
for i in range(first, n):
# 这里使用交换来模拟递归其余数字(比如1,2,3。 交换1 2 13 就模拟了第一个位置的全部可能)
nums[first], nums[i] = nums[i], nums[first]
backtrack(first + 1)
nums[first], nums[i] = nums[i], nums[first]
n = len(nums)
output = []
backtrack()
return output
0 条评论