力扣46全排列(回溯(递归))

46. 全排列 - 力扣(LeetCode)

回溯法:

一种通过探索所有可能的候选解来找出所有的解的算法

如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化抛弃该解,即回溯并且再次尝试

java 复制代码
class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();

        // output:当前正在构造的排列数组,一开始直接把nums全部放进来
        List<Integer> output = new ArrayList<Integer>();
        for (int num : nums) {
            output.add(num);
        }

        int n = nums.length;

        // 回溯入口:从第0个位置开始填数
        backtrack(n, output, res, 0);
        return res;
    }

  
    public void backtrack(int n, List<Integer> output, List<List<Integer>> res, int first) {
        // 终止条件:first == n,说明 [0 ~ n-1] 所有位置都已经填好了,得到一个完整排列
        if (first == n) {
            // 重点:不能直接add(output),要new一个新ArrayList拷贝快照
            // 因为后面swap会不断修改output对象,直接存引用会全部被改乱
            res.add(new ArrayList<Integer>(output));
        }
      
        for (int i = first; i < n; i++) {
            //相当于选定这个数放在first
            Collections.swap(output, first, i);

            // 递归:first位置已经确定,去处理下一个位置 first+1
            backtrack(n, output, res, first + 1);

            // 【回溯/撤销】交换回来,恢复现场,尝试下一个i
            // 这一步是回溯核心:递归结束后,把刚才的交换复原,不影响后面循环
            Collections.swap(output, first, i);
        }
    }
}

本质就是: 把所有合法的排列情况,不漏、不重地全部枚举一遍
为什么不用for循环遍历呢
for 循环的层数必须写死;但排列的长度 n 是变量,你不知道要写几层 for,所以写不了

相关推荐
文丑颜不良啊2 小时前
LeetCode1461~1480题目解析
java·leetcode
ZhengEnCi11 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
秋天的怀念_David11 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Pniubi12 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_61812 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang12 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
2601_9707038313 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你021413 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
ZhengEnCi14 小时前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm