LeetCode算法训练-回溯 491.递增子序列 46.全排列 47.全排列 II
欢迎关注个人公众号:爱喝可可牛奶
LeetCode算法训练-回溯 491.递增子序列 46.全排列 47.全排列 II
LeetCode 491. 递增子序列
分析
找出并返回所有数组中不同的递增子序列
- 绝对不能先升序 绝对不能先升序 绝对不能先升序 这样会改变原有数组的结构 
- 子序列中元素在数组中不一定相邻 
- 只要叶子节点,也就是path,一满足条件,直接加入res 
- 注意去重used[] 数组只针对当前节点的后序节点 要在回溯函数中定义 画回溯树一看便知 
代码
class Solution {
    private LinkedList<Integer> path = new LinkedList<>();
    private List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> findSubsequences(int[] nums) {
        backtracking(nums,0);
        return res;
    }
    private void backtracking (int[] nums, int start) {
        // 保证了能进入path的元素是升序的
        if (path.size() > 1) {
            res.add(new LinkedList<>(path));
            // 注意这里不要加return,要取树上的节点
        }
        // 元素值为used数组索引 只对同一行进行去重
        int[] used = new int[201];
        for (int i = start; i < nums.length; i++) {
            // path 为空 当前元素小于path最后一个元素 或者这个元素在本层已经使用过了 跳过这个继续横向遍历
            if (!path.isEmpty() && nums[i] < path.getLast() || (used[nums[i] + 100] == 1)) {
                    // 如果是break 应该是终止当前节点的横向遍历 进入递归
                    continue;
                }
            used[nums[i] + 100] = 1;
            path.add(nums[i]);
            backtracking(nums, i + 1);
            path.removeLast();
        }
    }
}
LeetCode 46. 全排列
分析
全排列,收集回溯树的叶子节点即可 注意终止条件要return
But 因为搜索过程每次都从第一个元素开始,要记录哪些元素已经使用过了 used[]数组应该是全局的
代码
class Solution {
    List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
    LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        if (nums.length == 0){
            return result;
        }
        used = new boolean[nums.length];
        permuteHelper(nums);
        return result;
    }
    private void permuteHelper(int[] nums){
        if (path.size() == nums.length){
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++){
            if (used[i]){
                continue;
            }
            used[i] = true;
            path.add(nums[i]);
            permuteHelper(nums);
            path.removeLast();
            used[i] = false;
        }
    }
}
LeetCode 47. 全排列 II
分析
按任意顺序 返回所有不重复的全排列
涉及到如何去重 根据用例画一个回溯树看看
在横向遍历时,如果当前元素==前一个元素,continue;
难点:如何判断统一树层当前节点的前一个节点使用过 去看一下当前节点前一个节点的状态
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
	continue;
}
代码
class Solution {
    List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
    LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
    public List<List<Integer>> permuteUnique(int[] nums) {
        if (nums.length == 0){
            return result;
        }
        // 得先排个序才能保证前后元素比较的正确性
        Arrays.sort(nums);
        boolean[] used = new boolean[nums.length];
        permuteHelper(nums,used);
        return result;
    }
    private void permuteHelper(int[] nums, boolean[] used){
        if (path.size() == nums.length){
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++){
            // 一定要通过used保证nums[i-1]是树层上nums[i]的前一个元素
            if(i > 0 && nums[i] == nums[i-1] && !used[i-1]){
                continue;
            }
            if (!used[i]){
                used[i] = true;
                path.add(nums[i]);
                permuteHelper(nums,used);
                path.removeLast();
                used[i] = false;
            }
        }
    }
}
总结
- 组合问题和排列问题是在树形结构的叶子节点上收集结果,而子集问题就是取树上所有节点的结果
- 理清回溯树树层、树枝的节点关系 for循环处理的是树层,递归调用函数处理的是树枝
- 如果没有startIndex来确定取的是数组中哪一个元素,used[]数组+for循环能间接确定这个元素是不是取过
LeetCode算法训练-回溯 491.递增子序列 46.全排列 47.全排列 II的更多相关文章
- Leetcode之深度优先搜索&回溯专题-491. 递增子序列(Increasing Subsequences)
		Leetcode之深度优先搜索&回溯专题-491. 递增子序列(Increasing Subsequences) 深度优先搜索的解题详细介绍,点击 给定一个整型数组, 你的任务是找到所有该数组 ... 
- Java实现 LeetCode 491递增子序列
		491. 递增子序列 给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2. 示例: 输入: [4, 6, 7, 7] 输出: [[4, 6], [4, 7], [4, ... 
- Leetcode 491.递增子序列
		递增子序列 给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2. 示例: 输入: [4, 6, 7, 7] 输出: [[4, 6], [4, 7], [4, 6, 7] ... 
- LeetCode编程训练 - 回溯(Backtracking)
		回溯基础 先看一个使用回溯方法求集合子集的例子(78. Subsets),以下代码基本说明了回溯使用的基本框架: //78. Subsets class Solution { private: voi ... 
- 算法实践--最长递增子序列(Longest Increasing Subsquence)
		什么是最长递增子序列(Longest Increasing Subsquence) 对于一个序列{3, 2, 6, 4, 5, 1},它包含很多递增子序列{3, 6}, {2,6}, {2, 4, 5 ... 
- 【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))
		算法新手,刷力扣遇到这题,搞了半天终于搞懂了,来这记录一下,欢迎大家交流指点. 题目描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删 ... 
- 每日一题 LeetCode 491. 递增子序列 【递推】【递增子序列】【动态规划】
		题目链接 https://leetcode-cn.com/problems/increasing-subsequences/ 题目说明 题解 主要方法:递推:动态规划 解释说明: 数据表示:观察数据范 ... 
- 31. Next Permutation + 46. Permutations + 47. Permutations II + 60. Permutation Sequence
		▶ 问题:字典序生成有关的问题. ▶ 31. 由当前序列生成字典序里的下一个序列. ● 初版代码,19 ms class Solution { public: void nextPermutation ... 
- 2019年7-8月Leetcode每日训练日志
		2019-08-29 #274 H指数 2019-08-28 #287 寻找重复数 #875 爱吃香蕉的珂珂 #704 二分查找 2019-08-27 #744 寻找比目标字母大的最小字母 #225 ... 
- Luogu 3402 最长公共子序列(二分,最长递增子序列)
		Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ... 
随机推荐
- 【Day04】Spring Cloud 升华篇:容器化技术docker和kurbernetes
			一.介绍 1.要考虑的问题 微服务数量有很多 中间件的部署-nacos-server sentinel-server 如何部署多个服务和中间件? 2.存在问题---机器上直接解压使用 资源利用率的问题 ... 
- PostgreSQL和MySQL的优劣对比
			在开发项目的过程中,难免要面对选择数据库的情况.总结此文章是因为在之前公司里使用的都是MYSQL 数据库,而在现在公司里,新项目中使用的是 PostgreSQL 数据库,在使用过程中,经常需要查找两种 ... 
- Java/JDK各版本主要特性汇总
			目录 Java18(2022.3) Java17(2021.9)(LTS版本) Java16(2021.3) Java15(2020.9) Java14(2020.3) Java13(2019.9) ... 
- 东拼西凑学java
			前言 随着大环境的影响,互联网寒冬降临,程序员的日子越来越难,搞不好哪天就被噶了,多学点东西也没啥坏处,国内市场java如日中天,出门在外不会写两行java代码,都不好意思说自己是程序员,伪装成一个萌 ... 
- java中的自增运算
			本文主要阐明java中的自增运算 1.当i ++ 与 ++ i作为单独语句时,作用与i = i +1一样 2.当赋值时,结果就不一样了 temp = i ++: 操作顺序:1)temp = i: 2) ... 
- vivo 实时计算平台建设实践
			作者:vivo 互联网实时计算团队- Chen Tao 本文根据"2022 vivo开发者大会"现场演讲内容整理而成. vivo 实时计算平台是 vivo 实时团队基于 Apach ... 
- ASP.NET 6.0 Core 迁移 ASP.NET Core 7.0
			2022年微软发布了.NET 7, 同时提供了详细的升级迁移方案. Migrate from ASP.NET Core 6.0 to 7.0 今天给大家简单整理.分享一篇文章. 一.首先需要升级Vis ... 
- Python 常用库函数
			压缩 zlib: 兼容gzip的压缩 gzip: 对gzip文件的支持 bz2: 对bzip2压缩的支持 lzma: 使用LZMA算法的压缩 zipfile: 操作ZIP存档 tarfile: 读取t ... 
- DVWA靶场实战(九)——Weak Session IDS
			DVWA靶场实战(九) 九.Weak Session IDS: 1.漏洞原理: Weak Session IDS也叫做弱会话,当用户登录后,在服务器就会创造一个会话(session),叫做会话控制,接 ... 
- liunx系统安装Redis详细步骤
			liunx系统安装Redis详细步骤 官网下载Redis安装包 使用工具将redis安装包拖入liunx系统 创建Redis存放目录 mkdir /usr/local/redis 解压到redis存放 ... 
