跳到主要内容

46. 全排列[medium]

46. 全排列[medium]

https://leetcode-cn.com/problems/permutations

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

通过次数135,082 提交次数177,420

Second Try

2020-06-06

学习了一波经典的backtrack回溯写法,写起来规范了许多,至少把套路功法跟上了,靠自己摸索写出来总有点不是业界正规军的感觉。

class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""

if not nums:
return []

def dfs(seq, sets, nums, len_n, rv):
if len(seq) == len_n:
rv.append(seq + []) # 内存地址不同,创建了新列表
return
for idx, x in enumerate(nums):
if idx in sets: # 用来判断是否已被使用
continue
seq.append(x)
sets.add(idx)
dfs(seq, sets, nums, len_n, rv)
seq.pop()
sets.remove(idx)

rv = []
dfs([], set(), nums, len(nums), rv)
return rv
  • 执行用时 :16 ms, 在所有 Python 提交中击败了96.16%的用户
  • 内存消耗 :12.7 MB, 在所有 Python 提交中击败了7.69%的用户
  • python列表加空列表,可以实现列表复制的功能
In [60]: a = [1, 2, 3, 4]

In [61]: id(a)
Out[61]: 4592438088

In [62]: b = a + []

In [63]: b
Out[63]: [1, 2, 3, 4]

In [64]: id(b)
Out[64]: 4592393416

In [65]: c = a

In [66]: id(c)
Out[66]: 4592438088

First Try

直接用递归DFS方法,但是使用列表的话无法实现递归之间的隔离,于是改成了字符串。然后为了处理负数的问题,字符串里用上了间隔符。但是得分还是挺低的,还得系统学下套路才行,靠自己摸索效率比较低。

class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if not nums:
return []
col = []

def backtrack(idv, nums):
if len(nums) == 1:
idv = idv + str(nums[0])
col.append([int(i) for i in idv.split("|")])
return
for i in range(len(nums)):
left = (nums + nums)[i+1: len(nums)+i]
tmp = idv + str(nums[i]) + "|"
# print(nums[i], left, tmp)
backtrack(tmp, left)

backtrack("", nums)
return col
  • 执行用时 :32 ms, 在所有 Python 提交中击败了22.72%的用户
  • 内存消耗 :13.1 MB, 在所有 Python 提交中击败了7.69%的用户

backtrack回溯公式

看来重点在撤销选择上面,每次使用新变量,或者是旧变量但是每次使用完会复归原样降低空间使用率?。

result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return

for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择