全排列问题可以套用模版: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/
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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: self.res.append(choosen) return for i in range (len (candidates)): 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) 的额外空间。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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])