Leetcoder Day25| 回溯part05:子集+排列

491.递增子序列

给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。

示例:

  • 输入:[4, 7, 6, 7]
  • 输出: [[4, 6], [4, 7], [4, 6, 7], [6, 7], [7,7], [4,7,7]]

说明:

  • 给定数组的长度不会超过15。
  • 数组中的整数范围是 [-100,100]。
  • 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。

在子集中我们是通过排序,再加一个标记数组来达到去重的目的。而本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。**所以不能使用之前的去重逻辑。**本题抽象为树结构过程如下:

从上图可以看到,如果在同一个父节点下,同一树层使用过的元素便不再取,如果所取元素小于子序列最后一个元素,也不符合条件。因此,可以设置一个哈希集合,来记录当前所取的值是否被使用过,哈希集合在递归后不用回溯,因为记录的是同一树层的使用情况,新的循环会清空重新记录。

java 复制代码
class Solution {
    List<List<Integer>> res =new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    public void backTracking(int[] nums, int startIdx){
        if(path.size()>1){
            res.add(new ArrayList<>(path));
        }
        HashSet record= new HashSet<>();
        for(int i=startIdx;i<nums.length;i++){
            /*
            如果path不为空且当前元素小于path最后一个元素,则不取
            如果元素的值使用过,不取
             */
            if((!path.isEmpty() &&  path.get(path.size()-1)>nums[i]) || record.contains(nums[i])){
                continue;
            }
            record.add(nums[i]);
            path.add(nums[i]);
            backTracking(nums, i+1);
            path.removeLast();
        }

    }
    public List<List<Integer>> findSubsequences(int[] nums) {
        backTracking(nums, 0);
        return res;
    }
}

46.全排列

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

  • 输入: [1,2,3]
  • 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]

排列问题不需要使用startIdx因为可以存在重复取值的情况,比如第一次1被取过,形成[1,2,3],后面还可以再取组成[2,1,3],但是需要设置一个数组used来记录当前元素在同一path中是否使用过。如果used[i-1]为true,则取下一个元素,因为本题为不重复的元素,所以不用去重。

java 复制代码
class Solution {
    List<List<Integer>> res =new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    public void backTracking(int[] nums, boolean[] used){
        if(path.size()==nums.length){
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
            /* 
            如果used[i-1]为true,说明同一树枝上使用过值一样的元素
            如果used[i-1]为false,说明同一树层上使用过值一样的元素
            */
            if(used[i]==true) continue;
            used[i]=true;
            path.add(nums[i]);
            backTracking(nums, used);
            path.removeLast();
            used[i]=false;
        }

    }
    public List<List<Integer>> permute(int[] nums) {
        boolean[] used=new boolean[nums.length];
        backTracking(nums, used);
        return res;
    }
}

📢注意:在调用回溯算法的时候,要记得创建一个used数组。

47.全排列 II

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:

  • 输入:nums = [1,1,2]
  • 输出: [[1,1,2], [1,2,1], [2,1,1]]

示例 2:

  • 输入:nums = [1,2,3]
  • 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

本题和上一题的区别在于有重复的数字,所以需要去重,先对数组进行排序,设置used数组记录是否使用过如果used[i-1]为true,说明同一树枝上使用过值一样的元素;如果used[i-1]为false,说明同一树层上使用过值一样的元素。

java 复制代码
import java.util.Arrays;
class Solution {
    List<List<Integer>> res =new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    boolean[] used;
    public void backTracking(int[] nums, boolean[] used){
        if(path.size()==nums.length){
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=0;i<nums.length;i++){
            /*
            当 used[i-1]== used[i]时
            used[i-1]为true,说明同一树枝使用过
            若为false,说明同一树层使用过
             */
            if(used[i]==true || (i>0 && nums[i-1]==nums[i] && used[i-1]==false)){
                continue;
            }
            used[i]=true;
            path.add(nums[i]);
            backTracking(nums, used);
            path.removeLast();
            used[i]=false;
        }

    }
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        used=new boolean[nums.length];
        backTracking(nums, used);
        return res;
    }
}
相关推荐
CSCN新手听安1 小时前
list的常用操作
数据结构·list
梅茜Mercy3 小时前
数据结构:链表(经典算法例题)详解
数据结构·链表
88号技师3 小时前
2024年12月一区SCI-加权平均优化算法Weighted average algorithm-附Matlab免费代码
人工智能·算法·matlab·优化算法
IT猿手3 小时前
多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码
开发语言·人工智能·算法·机器学习·matlab
青春男大3 小时前
java栈--数据结构
java·开发语言·数据结构·学习·eclipse
88号技师3 小时前
几款性能优秀的差分进化算法DE(SaDE、JADE,SHADE,LSHADE、LSHADE_SPACMA、LSHADE_EpSin)-附Matlab免费代码
开发语言·人工智能·算法·matlab·优化算法
Zer0_on3 小时前
数据结构栈和队列
c语言·开发语言·数据结构
一只小bit3 小时前
数据结构之栈,队列,树
c语言·开发语言·数据结构·c++
我要学编程(ಥ_ಥ)4 小时前
一文详解“二叉树中的深搜“在算法中的应用
java·数据结构·算法·leetcode·深度优先
埃菲尔铁塔_CV算法4 小时前
FTT变换Matlab代码解释及应用场景
算法