自学内容网 自学内容网

leetcode刷题day25|回溯算法Part04(491.递增子序列、46.全排列、47.全排列 II)

491.递增子序列

思路:至少有两个元素,说明递归的树枝至少有两层;要求递增,每次取数的时候要考虑下一个元素是不是大于当前元素。此外,这个题也要在同一层中进行去重,但是这个题不能对原数组进行排序,所以需要在每一层开辟一个新的空间HashSet来记录已经遍历过的元素。

HashSet 不允许重复元素。如果尝试添加一个已经存在的元素,该操作将被忽略。

回溯三部曲:
1、递归函数参数:全局变量:数组result存放结果集,path存放遍历到的每个节点。 递归函数参数:原数组;startIndex。
2、终止条件:startIndex遍历完数组,大于等于数组的长度;可以不需要加终止条件,因为startIndex >= nums.length,本层for循环本来也结束了。
3、单层搜索的逻辑:在for (int i = startIndex; i < s.size(); i++)循环中,我们定义了起始位置startIndex,那么 [startIndex, i] 就是要截取的子串。首先判断这个数组元素是不是小于前一个或者已经遍历过了,如果是,就continue。

代码如下:

class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new LinkedList<>();
    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])) continue;
            hs.add(nums[i]);
            path.add(nums[i]);
            backTracking(nums,i+1);
            path.remove(path.size()-1);
        }
    }
}

46.全排列

思路:全排列相对于组合问题不需要设置startIndex,但是需要判断这个元素是不是已经在该树枝中用过了,如果用过则跳过循环。

class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path= new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
        backTracking(nums);
        return result;
    }
    public void backTracking(int[] nums){
        if(path.size()==nums.length){
            result.add(new ArrayList(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(path.contains(nums[i])) continue;
            path.add(nums[i]);
            backTracking(nums);
            path.removeLast();
        }
    }
}

47.全排列 II

思路:由于该题目中序列 nums 可包含重复数字,所以需要在同一层去重。

class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new LinkedList<>();
    boolean[] used;
    public List<List<Integer>> permuteUnique(int[] nums) {
        used=new boolean[nums.length];
        Arrays.fill(used, false);
        Arrays.sort(nums);
        backTracking(nums,used);
        return result;
    }
    public void backTracking(int[] nums,boolean[] used){
        if(path.size()==nums.length){
            result.add(new ArrayList(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(i>0 && nums[i]==nums[i-1] && used[i-1]==false) continue;
            if (used[i] == false) {
                path.add(nums[i]);
                used[i]=true;
                backTracking(nums,used);
                used[i]=false;
                path.removeLast();
            }
        }
    }
}

注意:
下面是对树层去重,两个元素相同,但之前没遍历过(used层与层之间是独立的):

if(i>0 && nums[i]==nums[i-1] && used[i-1]==false) continue;

下面是对数枝去重,两个元素相同,但前一个遍历过了:

if(i>0 && nums[i]==nums[i-1] && used[i-1]==true) continue;

原文地址:https://blog.csdn.net/m0_51007517/article/details/142421534

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!