算法 13 回溯算法

13.1 全排列(46)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jwVozwXV-1653565695001)(D:\markdown文件\算法\算法图片\Snipaste_2022-05-26_17-52-13.png)]

图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GO0qBCke-1653565695002)(D:\markdown文件\算法\算法图片\Snipaste_2022-05-26_18-00-00.png)]

思路

当第一个数选1 时
      |
第二层 的数 只能选2,3
	  |
第二层选2时,第三层只能选3;当第二层选3时,第三层只能选2

定义一个List<List<Integer>> res,集合元素为 Integer类型的集合 的集合res。来存储每一种排列方式[[1,2,3],[1,3,2]]
定义一个List<Integer> track,集合元素为Integer类型,用来存储一种排列方式 [1,2,3]
每当找到一种排列方式时,需要往 上一层 回退 ,操作的方法就是 删掉track中最后一个元素 使用递归调用时,当函数执行完成,就会回到上一层的递归,利用这一特点,将 删除集合最后一个元素这个操作,定义为函数的最后一步。这样上一层函数的track就保持不变

具体例子:
第二层track(1,2) 执行递归 进第三层 
第三层执行循环 1,2都存在于track中,将3加入track track(1,2,3) 此时删掉3 track(1,2) 
返回上一层函数调用,第二层的track(1,2)未变化

当track的数量 与 传入的数组nums 长度相同时,说明 找到了一种全排列,加入res中,此时返回上一层
具体例子:
当1,3,2这种排列被找到并加入res后,此时回到第二层 track(1,3,2) -> track(1,3) 
此时for循环还要执行一轮 i = 2 nums[2] = 3
判断track中是否有3 发现track中存在3 进入下一轮循环

解法

class Solution {
	//定义集合 用来存放所有全排列情况
    List<List<Integer>> res = new ArrayList<>();
	//执行操作后 返回上文定义的集合
    public List<List<Integer>> permute(int[] nums) {
        List<Integer> track = new ArrayList<>();
        method(nums,track);
        return res;
    }
    public void method(int[] nums,List<Integer> track){
        //当集合元素数  =  数组元素数 时 说明 完成了一种全排列情况 加入到res中 然后 返回上一层method函数
        if(track.size() == nums.length){
            //注意:集合是引用类型,需要new一个新的集合,否则最后放入的每一个track均为空集合(递归调用结束,track中无元素)
            res.add(new ArrayList<>(track));
            return;
        }
        //循环用来 选择元素 放入track集合中
        for(int i = 0;i<nums.length;i++){
            //集合中存在该元素时 进入下一轮循环
            if(track.contains(nums[i])){
                continue;
            }
            track.add(nums[i]);
            //递归 进入下一层 选择
            method(nums,track);
            //执行到这句话时 说明一种全排列已经发现,此时要回到上一层函数 就需要去掉集合中最后一个元素
            track.remove(track.size()-1);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值