leetcode46:全排列
思路一:运用库函数进行sao操作(笔试可以,但面试的时候不要这么做)
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
import itertools
if not nums:
return []
if len(nums) == 1:
return [nums]
return sorted(list(set(itertools.permutations(nums))))
思路二:与39、40题类似,也可以运用回溯法。
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
def helper(arr,tmp):
if not arr:
res.append(tmp)
for i in range(len(arr)):
# if i > 0 and arr[i] == arr[i-1]: #题目已经明确没有重复数字,所以这一步可以省略
# continue
helper(arr[:i] + arr[i+1:], tmp+[arr[i]])
helper(nums,[])
return res
leetcode47:全排列II
思路:与46题不同的是,这次的数组包含重复数字,所以要进行判断
写法一:
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
def helper(arr,tmp):
#递归边界:当数组中没有任何元素时,返回所有累加的元素
if not arr:
res.append(tmp)
for i in range(len(arr)):
if i > 0 and arr[i] == arr[i-1]:
continue
helper(arr[:i] + arr[i+1:],tmp+[arr[i]])
helper(nums,[])
return res
写法二:
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
#递归边界:当数组中没有任何元素时,返回空;只有一个元素时,返回该元素
if not nums:
return []
if len(nums)==1:
return [nums]
nums.sort()
res = []
for i in range(len(nums)):
#去重
if i > 0 and nums[i]==nums[i-1]:
continue
for j in self.permuteUnique(nums[:i]+nums[i+1:]):
res.append([nums[i]]+j)
return res
虽是不同的写法,但得到的效果完全一样。
期初对这种写法不是很理解,所以自己手推了对[1,2,3]进行回溯的过程,加深理解,以第二种写法为例:
图中黑色粗线为递归调用,红线是删除,蓝线为向上返回。
在第一层时,当i=1
时,由于nums[i] == nums[i-1]
,所以直接跳过,进行i=2
的操作;第二层中的i=1
同理
如果没有去重条件,则结果为[[1, 1, 2], [1, 2, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 1, 1]]
,即为46题。