枚举问题的两大利器:深度优先搜索 (DFS) 与下一个排列 (Next Permutation) 算法详解
一、引言:枚举问题的核心挑战
在算法竞赛与工程实践中,暴力枚举常是解决排列/组合问题的兜底方案。然而,当问题规模扩大(如 n > 10)时,直接生成所有排列会导致 O(n!) 时间复杂度,极易超时。此时,DFS 回溯与Next Permutation成为两大高效解法:
- DFS:通过递归 + 剪枝实现灵活枚举,适合需动态过滤的场景
- Next Permutation:原地生成字典序排列,空间高效且常数极小

典型场景:LeetCode 46(全排列)、47(带重复元素的全排列)、31(下一个排列)、60(第 k 个排列)
二、深度优先搜索 (DFS):回溯法的灵活枚举
1. 核心思想与剪枝机制
DFS 通过递归探索状态空间树,核心逻辑如下:
- 选择:从未使用元素中选一个加入当前路径
- 递归:进入下一层搜索
- 回溯:撤销选择,尝试其他分支
关键优势:剪枝
在递归过程中动态判断是否满足题目约束(如和为特定值、无连续重复等),提前终止无效分支,显著减少搜索空间。
剪枝示例:
题目要求排列中不能有连续偶数
2. 代码实现(含完整注释)
import java.util.*;
public class PermutationDFS {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new <>();
List<Integer> path = <>();
[] used = [nums.length];
dfs(nums, used, path, res);
res;
}
{
(path.size() == nums.length) {
res.add( <>(path));
;
}
( ; i < nums.length; i++) {
(used[i]) ;
(i > && nums[i] == nums[i - ] && !used[i - ]) ;
path.add(nums[i]);
used[i] = ;
dfs(nums, used, path, res);
path.remove(path.size() - );
used[i] = ;
}
}
}






