4

算法 | 全排列问题

 2 years ago
source link: https://jianengli.github.io/2021/02/17/algorithm_summerization/permutation/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Jianeng

算法 | 全排列问题

Created2021-02-17|Updated2021-02-17|算法专题
Word count:672|Reading time:2min|Post View:39

全排列问题可以套用模版:DFS找出所有符合要求的情况

1. lc 46 - 全排列

  • 题目来源
  • 给定一个 没有重复 数字的序列,返回其所有可能的全排列。
  • 难度:中等

直接看代码, 此题可以作为此类题模版了。

  • 时间复杂度:O(n*n!)
  • 空间复杂度:O(n) 其中 n 为序列的长度。除答案数组以外,递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,这里可知递归调用深度为 o(n)

具体请看:https://leetcode-cn.com/problems/permutations/solution/quan-pai-lie-by-leetcode-solution-2/

python
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
if len(nums) == 0: return []

self.res = []
self.length = len(nums)
self.recursion([],nums)
return self.res

'''
choosen列表储存一种新的排列的元素
candidates列表存储待选的元素
'''
def recursion(self,choosen,candidates):
if len(choosen) == self.length: # 当 choosen 长度达到要求,加入返回列表res中
self.res.append(choosen)
return
for i in range(len(candidates)): # 遍历 candidates列表 每个待选,放入到choosen,递归直到产生一种新的排序
tmp1 = choosen.copy() # 注意:需要对原数组拷贝,否则直接操作会改动到原数组
tmp1.append(candidates[i])

tmp2 = candidates.copy()
del (tmp2[i])

self.recursion(tmp1,tmp2)

类似题:剑指 38 - 字符串的排列

与上题区别:对象为字符串。字符串会存在重复字符。需要剪枝操作,排除重复方案。需在固定某位字符时,保证 “每种字符只在此位固定一次” ,即遇到重复字符时不交换,直接跳过。从 DFS 角度看,此操作称为 “剪枝” 。

Question source

套用模版,但需要剪枝操作,否则超时。可使用哈希表判重。

  • 时间复杂度:递归树的中间节点 O(N!), 然后每个中间节点内部有一个for循环,那么合计为 O(N * N!)。
  • 空间复杂度: O(n^2) ,全排列的递归深度为 N ,系统累计使用栈空间大小为 O(N) ;递归中辅助 Set 累计存储的字符数量最多为 N+(N−1)+...+2+1=(N+1)^N/2 ,即占用 O(N^2) 的额外空间。
python
class Solution:
def permutation(self, s: str) -> List[str]:
self.res = []
self.s = s
self.recursion(s,"")
return self.res

def recursion(self,candidates,choosen):
hashmap = dict() # 额外空间用于剪枝

if len(choosen) == len(self.s) :
self.res.append(choosen)
return
for i in range(len(candidates)):
if candidates[i] in hashmap.keys():
continue
else:
hashmap[candidates[i]] = 0
self.recursion(candidates[:i]+candidates[i+1:], choosen+candidates[i])

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK