Permutation
🖼️

Permutation

 
 
  1. Next Permutation
 
找到下一个permutation。
 
class Solution: def nextPermutation(self, nums): """ :type nums: List[int] :rtype: void Do not return anything, modify nums in-place instead. """ i = len(nums) - 2 while i >= 0 and nums[i + 1] <= nums[i]: i -= 1 if i >= 0: j = len(nums) - 1 while nums[j] <= nums[i]: j -= 1 self.swap(nums, i, j) self.reverse(nums, i + 1) def reverse(self, nums, start): i, j = start, len(nums) - 1 while i < j: self.swap(nums, i, j) i += 1 j -= 1 def swap(self, nums, i, j): temp = nums[i] nums[i] = nums[j] nums[j] = temp
思路:从右往左推,如果有逆序,就处理。

🧩 一、全排列基础题

46. Permutations

题意:
给定一个不含重复数字的整数数组 nums,返回所有可能的全排列。
示例:
输入:[1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
思路:
  • 使用 回溯算法
  • 每一层选择一个未使用的元素加入路径。
  • 当路径长度等于 len(nums) 时,将路径加入结果集。
代码:
class Solution: def permute(self, nums): res = [] n = len(nums) def backtrack(path): if len(path) == len(nums): res.append(path[:]) return for num in nums: if num not in path: path.append(num) backtrack(path) path.pop() backtrack([]) return res

🔁 二、含重复元素的全排列

47. Permutations II

题意:
数组 nums 可能包含重复元素,返回所有 不重复 的全排列。
示例:
输入:[1,1,2]
输出:[[1,1,2],[1,2,1],[2,1,1]]
思路:
  • 仍然是回溯,但要跳过重复分支
  • 排序后,如果当前元素和前一个相等,且前一个还未使用,则跳过。
代码:
class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]: results = [] def backtrack(comb, counter): if len(comb) == len(nums): # make a deep copy of the resulting permutation, # since the permutation would be backtracked later. results.append(list(comb)) return for num in counter: if counter[num] > 0: # add this number into the current combination comb.append(num) counter[num] -= 1 # continue the exploration backtrack(comb, counter) # revert the choice for the next exploration comb.pop() counter[num] += 1 backtrack([], Counter(nums)) return results

📈 三、下一个排列(字典序思路)

31. Next Permutation

题意:
给定一个排列 nums,找出其 下一个字典序排列
如果不存在更大的排列,返回最小的排列(即升序)。
思路:
  1. 从右往左找第一个下降位置 i,满足 nums[i] < nums[i+1]
  1. 再从右往左找第一个比 nums[i] 大的元素 j
  1. 交换 nums[i]nums[j]
  1. 反转 nums[i+1:]
代码:
class Solution: def nextPermutation(self, nums): i = len(nums) - 2 while i >= 0 and nums[i] >= nums[i + 1]: i -= 1 if i >= 0: j = len(nums) - 1 while nums[j] <= nums[i]: j -= 1 nums[i], nums[j] = nums[j], nums[i] nums[i + 1:] = reversed(nums[i + 1:])

🧮 四、第 k 个排列(数学法)

60. Permutation Sequence

题意:
给定 nk,返回 [1,2,...,n] 的第 k 个排列(按字典序)。
示例:
输入:n=3, k=3
输出:"213"
思路:
  • 利用 阶乘 计算每一位对应的数字。
  • 第 i 位固定后剩下 n−i 位的排列数为 (n-i)!
  • 每次通过整除判断选哪个数字。
代码:
class Solution: def getPermutation(self, n, k): import math nums = [str(i) for i in range(1, n + 1)] k -= 1 res = "" for i in range(n, 0, -1): fact = math.factorial(i - 1) idx = k // fact res += nums[idx] nums.pop(idx) k %= fact return res

🔡 五、字符串全排列(字母)

567. Permutation in String

题意:
判断字符串 s2 中是否包含 s1 的某个排列。
(即判断 s1 的任意排列是否为 s2 的子串)
示例:
输入:s1 = "ab", s2 = "eidbaooo"
输出:True(因为 "ba" 存在于 s2)
思路:
  • 滑动窗口 + 计数数组(或Counter)
  • 窗口长度固定为 len(s1)
  • 当窗口内计数与 s1 的计数相同 → True
代码:
from collections import Counter class Solution: def checkInclusion(self, s1, s2): n, m = len(s1), len(s2) if n > m: return False c1, c2 = Counter(s1), Counter(s2[:n]) if c1 == c2: return True for i in range(n, m): c2[s2[i]] += 1 c2[s2[i-n]] -= 1 if c2[s2[i-n]] == 0: del c2[s2[i-n]] if c1 == c2: return True return False

💡 六、其他排列相关题(拓展)

题号
名称
类型
核心技巧
784
Letter Case Permutation
字母大小写排列
DFS/回溯
996
Number of Squareful Arrays
只要相邻和是平方数
回溯 + 剪枝
267
Palindrome Permutation II
构造回文排列
计数+DFS
869
Reordered Power of 2
数字重排后是2的幂
Counter判断排列
1830
Minimum Number of Operations to Make String Sorted
下一个排列次数
模拟nextPermutation

📚 七、总结比较

类型
代表题
核心思想
难度
基础排列
46
回溯 + used数组
去重排列
47
排序 + 剪枝
⭐⭐
字典序下一个
31
逆序区间 + 反转
⭐⭐
第k个排列
60
数学法 + 阶乘
⭐⭐⭐
包含排列
567
滑动窗口
⭐⭐
字母排列
784
DFS递归

是否希望我再给出一个 统一的对比表 + 图形化流程图(展示回溯树) 来帮助你系统掌握 permutation 类题型的核心差异?
(例如对比 permute, permuteUnique, nextPermutation, getPermutation 的执行路径和时间复杂度)