代码随想录算法训练营day 29 |491.递增子序列、46.全排列、47.全排列 II

491.递增子序列

代码随想录

思路:

不能回头,所以需要startindex控制循环开始位置;同一层不能选相同的元素,但数组是无序的且不能排序,所以需要每层都需要建立一个数组记录用过的数字。

代码:

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> paths = new ArrayList<>();
    public List<List<Integer>> findSubsequences(int[] nums) {
        backtracking(nums, 0);
        return res;
    }

    private void backtracking(int[] nums, int startindex){
        if(paths.size() > 1){
            res.add(new ArrayList<>(paths));
            //取树上的节点,不需要return
        }
        int[] used = new int[201];//每一层都需要数组来记录用过的数字
        for(int i = startindex; i < nums.length; i++){
            if(!paths.isEmpty() && nums[i] < paths.get(paths.size() - 1) || used[nums[i] + 100] == 1){
                continue;//当前数小于paths最后一个数或这个数在本层用过(used[0] 记录-100,所以要+100)
            }
            used[nums[i] + 100] = 1;//记录用过的数
            paths.add(nums[i]);
            backtracking(nums, i + 1);//因为选序列,不能回头,所以需要startindex控制起始位置
            paths.remove(paths.size() - 1);
        }
    }
}

需要注意的点:

见代码

46.全排列

代码随想录

思路:

在进行每一步选元素前需要判断paths中是否有这个元素,无需考虑顺序(不用startindex)。

代码:

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    LinkedList<Integer> paths = new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
        backtracking(nums);
        return res;
    }

    private void backtracking(int[] nums){//顺序可以不同,但选过的元素不能选
        if(paths.size() == nums.length){
            res.add(new ArrayList<>(paths));
            return;
        }
        for(int i = 0; i < nums.length; i++){
            if(paths.contains(nums[i])){
                continue;
            }
            paths.add(nums[i]);
            backtracking(nums);
            paths.removeLast();
        }
    }
}

需要注意的点:

1、检查paths(LinkedList)中是否含有某元素:paths.contains(元素)。

47.全排列 II

代码随想录

思路:

因为有重复元素,不但要对用过位置进行跳过,重复的元素每层只能选一个。

代码:

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    LinkedList<Integer> paths = new LinkedList<>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        int[] check = new int[nums.length];
        backtracking(nums, check);
        return res;
    }

    private void backtracking(int[] nums, int[] check){
        if(paths.size() == nums.length){
            res.add(new ArrayList<>(paths));
            return;
        }

        for(int i = 0; i < nums.length; i++){
            //当遇到选过的元素(用check[]来记录,用过的位置记为1。
            //或碰到连续相同的元素,(相同元素)前面位置只有上一步被选过才能在这一步选这个(相同)元素)
            //从而保证同一层相同的元素只能选一个(保证每一次只选择选过元素后面一个)
            if(check[i] == 1 || (i > 0 && nums[i] == nums[i - 1] && check[i - 1] != 1)) continue;
            paths.add(nums[i]);
            check[i] = 1;//标记选过的位置
            backtracking(nums, check);
            paths.removeLast();
            check[i] = 0;
        }
    }
}

需要注意的点:

1、同层相同元素去重,注意对代码的理解:把相同的元素看成整体,每层选有相同元素的数时,指定选上一层选过相同数的后一个位置,除此之外的跳过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值