代码随想录训练营第二十五天| 491.递增子序列 46.全排列 47.全排列 II N皇后(回溯法)

LeetCode递增子序列与全排列算法解析

491.递增子序列

 和求子集不同 求递增子序列就需要注意去重逻辑和求组合的区别 同时判断上一个记录的元素是否大于当前元素 并且要记录当前元素是否使用过(用了hashset)

Java代码:

class Solution{
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> findSubsequences(int[] nums){
        backtracking(nums, 0);
        return result;
    }
    public void backtracking(int[] nums, int startindex){
        if(path.size() > 1){
            result.add(new ArrayList<>(path));
        }
        HashSet<Integer> hs = new HashSet<>();
        for(int i = startindex; i < nums.length; i++){
            if(!path.isEmpty() && path.get(path.size() - 1) > nums[i] || hs.contains(nums[i])){
                //如果当前路径不为空,并且最后一个元素大于当前元素,
                // 或者HashSet中已经包含了当前元素
                // 则跳过当前元素,不将其添加到路径中。
                continue;
            }
            hs.add(nums[i]);//将当前元素添加到HashSet中,标记为已访问。
            path.add(nums[i]);//将当前元素添加到路径path中
            backtracking(nums, i + 1);
            //递归调用backTracking方法,处理下一个元素,
            //但是从i + 1开始,因为当前元素已经被考虑过。
            path.remove(path.size() - 1);
            //:在回溯时,从路径path中移除最后一个元素,以便尝试下一个元素。
        }
    }
}

46.全排列

首先就是在数学角度上想 组合和排列本身就不同 虽然有公式转换 但是本质不一样 排列是有序的 组合是无序的(1 2 3 的子集有8个 但是排列有6个 无序和有序不同)

在排列问题里不需要用startindex 因为排列问题中的递归里元素可以重复 

Java代码:

class Solution{
    List<List<Integer>> result = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    public List<List<Integer>> permute(int[] nums){
        if(nums.length == 0) return result;
        backtracking(nums, path);
        return result;
    }
    public void backtracking(int[] nums, LinkedList<Integer> path){
        if(path.size() == nums.length){
            result.add(new ArrayList<>(path));
        }
        for(int i = 0; i < nums.length; i++){
            //如果path里已经有这个元素 就把当前元素跳过
            if(path.contains(nums[i])) continue;
            path.add(nums[i]);
            backtracking(nums, path);
            path.removeLast();
        }
    }
}

47.全排列 II  

 数组里有重复元素 所以要在递归过程里去重 但是保证结果 要注意树层和树枝的区别 这题只能用used记录当前元素是否使用过是较好的

Java代码:

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        boolean[] used = new boolean[nums.length];
        Arrays.fill(used, false);
        Arrays.sort(nums);
        backtracking(nums,used);
        return ans;
    }
    private void backtracking(int[] nums, boolean[] used){
        if(path.size() == nums.length){
            ans.add(new ArrayList<>(path));
            return;
        }for(int i = 0; i < nums.length; i++){
            //used[i - 1] == true 说明同一树枝nums[i - 1]使用过
            //used[i - 1] == false 说明同一树层nums[i - 1]使用过
            //如果同一树层nums[i - 1]使用过则直接跳过
            if(i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false){
                continue;
            }
            //如果同一树枝nums[i]没使用过开始处理
            if(used[i] == false){
                used[i] = true;
                //标记同一树枝nums[i]使用过 防止同一树枝重复使用
                path.add(nums[i]);
                backtracking(nums, used);
                path.removeLast();//回溯 说明同一树层nums[i]使用过 防止重复使用树层
                used[i] = false;
            }
        }
    }
}

还有三道比较难的 但是最近在期末考试我一点没复习 还是去复习一下先 那三道n皇后我自己有点印象 其他两道没写过 没关系 今天也是需要刷算法和八股的一天 努力找工作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值