当前位置: 首页 > news >正文

Day26 第七章 回溯算法part05

一. 学习文章及资料

  • 491.递增子序列
  • 46.全排列
  • 47.全排列 II

二. 学习内容

1. 递增子序列

(1) 题目要点:

  • 递增子序列,
  • 数组中可能含有重复元素

(2) 解题思路:

如下一选取元素不是递增或使用过,则跳过这一分支,用set记录已使用元素以达去重效果

class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new LinkedList<>();
    void backtracking(int[] nums,int startIndex){
        if(path.size()>=2){
            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.removeLast();
        }
        return;
    }
    public List<List<Integer>> findSubsequences(int[] nums) {
        backtracking(nums,0);
        return result;
    }
}

2. 全排列

(1) 解题要点:

  • 没有重复数字
  • 返回其所有可能的全排列

(2) 解题思路:

首先排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的子集以及组合所不同的地方。可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了,每层i都从0开始,使用used数组记录使用情况

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

3. 全排列 II

(1) 题目要点:

  • 包含重复数字
  • 返回所有不重复的全排列

(2) 题目思路:

以示例中的 [1,1,1]为例 (为了方便举例,已经排序)抽象为一棵树,去重过程如图:

47.全排列II2

图中我们对同一树层,前一位(也就是nums[i-1])如果使用过,那么就进行去重。

要强调的是去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了

组合问题和排列问题是在树形结构的叶子节点上收集结果,而子集问题就是取树上所有节点的结果

class Solution {
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new LinkedList<>();
    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++){
            // used[i - 1] == true ,说明同一树枝nums[i - 1]使用过
            // used[i - 1] == false,说明同一树层nums[i - 1]使用过
            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();
            }
        }
    }
    public List<List<Integer>> permuteUnique(int[] nums) {
        boolean[] used = new boolean[nums.length];
        Arrays.sort(nums); 
        backtracking(nums,used);
        return result;
    }
}

相关文章:

  • 基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
  • mysql大数量表添加索引方案
  • Linux提权之环境劫持提权(九)
  • 大语言模型中的 Token如何理解?
  • Linux 命令大全完整版(03)
  • 【嵌入式Linux应用开发基础】多线程编程
  • 基于AIGC的图表自动化生成工具「图表狐」深度评测:如何用自然语言30秒搞定专业级数据可视化?
  • ABC381E题解
  • 数据结构之二叉树的定义及实现
  • Unity使用IL2CPP打包时,我们应该注意什么?如何避免(可以举例说明)
  • 创建虚拟环境以及配置对应的项目依赖
  • DeepSeek技术全景解析:架构创新与行业差异化竞争力
  • Spring Boot数据访问(JDBC)全解析:从基础配置到高级调优
  • 20-R 绘图 - 饼图
  • 游戏设计模式阅读 - 游戏循环
  • Spring Security+JWT (5)
  • 红队内网攻防渗透:内网渗透之内网对抗:实战项目VPC2打靶父子域三层路由某绒免杀下载突破约束委派域控提权
  • 深度解析:大模型在多显卡服务器下的通信机制与分布式训练——以DeepSeek、Ollama和vLLM为例
  • 安全面试4
  • 谷歌浏览器更新后导致的刷新数据无法显示
  • 做a暧小视频在线观看网站/万网注册域名查询
  • 有横向滚动条的网站/西安seo招聘
  • 怎么做自己的一个网站/如何弄一个自己的网站
  • 男女做爰视频免费网站/系统优化大师
  • 网上订酒店 网站开发/搜索引擎营销推广方案
  • 兖州网站建设/湖州网站seo