(leetcode)no.46 全排列(回溯做法)




题目

46. 全排列

img

思路

这里我主要讲的是回溯法的做法。

回溯主要是基于递归的思想,一定要记得,在递归结束后,要撤销选择。在递归之前做出选择,在递归之后撤销刚才的选择,就能正确得到每个节点的选择列表和路径。

大体框架如下:

def backtrack(选择列表,路径):
    if 满足结束条件:
        操作res
        return
        
    for 选择 in 选择列表:
        if 选择不合法
            # 剪枝
            continue

        # 做选择 进入下一层决策树
        选择列表.remove(选择)
        路径.add(选择)
        backtrack(选择列表,路径)

        # 撤销选择
        路径.remove(选择)
    

借用labuladong公众号的一张图来帮助理解一下,这道题的过程大概如下。

img

代码

import java.util.*;

public class Solution {

    List<List<Integer>> res = new LinkedList<>();

    public List<List<Integer>> permute(int[] nums) {
        if (nums.length == 0) {
            return res;
        }

        // 记录「路径」
        LinkedList<Integer> track = new LinkedList<>();

        backtrack(nums, track);

        return res;
    }


    // 路径:记录在 track 中
    // 选择列表:nums 中不存在于 track 的那些元素
    // 结束条件:nums 中的元素全都在 track 中出现
    void backtrack(int[] nums, LinkedList<Integer> track) {
        // 触发结束条件
        if (track.size() == nums.length) {
            // 注意这里要new一个 放入的将会变成引用
            res.add(new LinkedList(track));
            return;
        }

        for(int i=0; i< nums.length; i++){
            // 剪去不合法的分支
            if(track.contains(nums[i])){
                continue;
            }

            // 做选择
            track.add(nums[i]);

            // 进入下一层决策树
            backtrack(nums, track);

            // 取消选择
            track.removeLast();
        }
    }
}

img

结语

当然就这道题而言,还有很多更优秀的解法,比如dfs、bfs搭配visited等方法剪枝,这些我以后会争取多做些笔记。

比较适用回溯算法的题还有这些,冲冲冲。

39.组合总和

40. 组合总和 II

46. 全排列

47. 全排列 II

78. 子集

90. 子集 II

51. N皇后

参考资料

我的leetcode刷题历程是跟着labuladong大佬混的,没错,就是那个leetcode上一出题解,必属精品的那位。

img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值