Given an integer array, your task is to find all the different possible increasing subsequences of the given array, and the length of an increasing subsequence should be at least 2 .

Example:

  1. Input: [4, 6, 7, 7]
  2. Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

Note:

  1. The length of the given array will not exceed 15.
  2. The range of integer in the given array is [-100,100].
  3. The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence.

这道题让我们找出所有的递增子序列,应该不难想到,这题肯定是要先找出所有的子序列,从中找出递增的。找出所有的子序列的题之前也接触过 Subsets 和 Subsets II,那两题不同之处在于数组中有没有重复项。而这道题明显是有重复项的,所以需要用到 Subsets II 中的解法。首先来看一种迭代的解法,对于重复项的处理,最偷懒的方法是使用 TreeSet,利用其自动去处重复项的机制,然后最后返回时再转回 vector 即可。由于是找递增序列,所以需要对递归函数做一些修改,首先题目中说明了递增序列数字至少两个,所以只有子序列个数大于等于2时,才加入结果。然后就是要递增,如果之前的数字大于当前的数字,那么跳过这种情况,继续循环,参见代码如下:

解法一:

  1. class Solution {
  2. public:
  3. vector<vector<int>> findSubsequences(vector<int>& nums) {
  4. set<vector<int>> res;
  5. vector<int> out;
  6. helper(nums, , out, res);
  7. return vector<vector<int>>(res.begin(), res.end());
  8. }
  9. void helper(vector<int>& nums, int start, vector<int>& out, set<vector<int>>& res) {
  10. if (out.size() >= ) res.insert(out);
  11. for (int i = start; i < nums.size(); ++i) {
  12. if (!out.empty() && out.back() > nums[i]) continue;
  13. out.push_back(nums[i]);
  14. helper(nums, i + , out, res);
  15. out.pop_back();
  16. }
  17. }
  18. };

我们也可以在递归中进行去重复处理,方法是用一个 HashSet 保存中间过程的数字,如果当前的数字在之前出现过了,就直接跳过这种情况即可,参见代码如下:

解法二:

  1. class Solution {
  2. public:
  3. vector<vector<int>> findSubsequences(vector<int>& nums) {
  4. vector<vector<int>> res;
  5. vector<int> out;
  6. helper(nums, , out, res);
  7. return res;
  8. }
  9. void helper(vector<int>& nums, int start, vector<int>& out, vector<vector<int>>& res) {
  10. if (out.size() >= ) res.push_back(out);
  11. unordered_set<int> st;
  12. for (int i = start; i < nums.size(); ++i) {
  13. if ((!out.empty() && out.back() > nums[i]) || st.count(nums[i])) continue;
  14. out.push_back(nums[i]);
  15. st.insert(nums[i]);
  16. helper(nums, i + , out, res);
  17. out.pop_back();
  18. }
  19. }
  20. };

下面我们来看迭代的解法,还是老套路,先看偷懒的方法,用 TreeSet 来去处重复。对于递归的处理方法跟之前相同,参见代码如下:

解法三:

  1. class Solution {
  2. public:
  3. vector<vector<int>> findSubsequences(vector<int>& nums) {
  4. set<vector<int>> res;
  5. vector<vector<int>> cur();
  6. for (int i = ; i < nums.size(); ++i) {
  7. int n = cur.size();
  8. for (int j = ; j < n; ++j) {
  9. if (!cur[j].empty() && cur[j].back() > nums[i]) continue;
  10. cur.push_back(cur[j]);
  11. cur.back().push_back(nums[i]);
  12. if (cur.back().size() >= ) res.insert(cur.back());
  13. }
  14. }
  15. return vector<vector<int>>(res.begin(), res.end());
  16. }
  17. };

我们来看不用 TreeSet 的方法,使用一个 HashMap 来建立每个数字对应的遍历起始位置,默认都是0,然后在遍历的时候先取出原有值当作遍历起始点,然后更新为当前位置,如果某个数字之前出现过,那么取出的原有值就不是0,而是之前那个数的出现位置,这样就不会产生重复了,如果不太好理解的话就带个简单的实例去试试吧,参见代码如下:

解法四:

  1. class Solution {
  2. public:
  3. vector<vector<int>> findSubsequences(vector<int>& nums) {
  4. vector<vector<int>> res, cur();
  5. unordered_map<int, int> m;
  6. for (int i = ; i < nums.size(); ++i) {
  7. int n = cur.size(), start = m[nums[i]];
  8. m[nums[i]] = n;
  9. for (int j = start; j < n; ++j) {
  10. if (!cur[j].empty() && cur[j].back() > nums[i]) continue;
  11. cur.push_back(cur[j]);
  12. cur.back().push_back(nums[i]);
  13. if (cur.back().size() >= ) res.push_back(cur.back());
  14. }
  15. }
  16. return res;
  17. }
  18. };

Github 同步地址:

https://github.com/grandyang/leetcode/issues/491

类似题目:

Subsets

Subsets II

Maximum Length of Pair Chain

参考资料:

https://leetcode.com/problems/increasing-subsequences/

https://leetcode.com/problems/increasing-subsequences/discuss/97124/c-dfs-solution-using-unordered_set

https://leetcode.com/problems/increasing-subsequences/discuss/97134/evolve-from-intuitive-solution-to-optimal

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Increasing Subsequences 递增子序列的更多相关文章

  1. [LeetCode] 491. Increasing Subsequences 递增子序列

    Given an integer array, your task is to find all the different possible increasing subsequences of t ...

  2. 491 Increasing Subsequences 递增子序列

    给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2.示例:输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, ...

  3. 子序列 sub sequence问题,例:最长公共子序列,[LeetCode] Distinct Subsequences(求子序列个数)

    引言 子序列和子字符串或者连续子集的不同之处在于,子序列不需要是原序列上连续的值. 对于子序列的题目,大多数需要用到DP的思想,因此,状态转移是关键. 这里摘录两个常见子序列问题及其解法. 例题1, ...

  4. leetcode最长递增子序列问题

    题目描写叙述: 给定一个数组,删除最少的元素,保证剩下的元素是递增有序的. 分析: 题目的意思是删除最少的元素.保证剩下的元素是递增有序的,事实上换一种方式想,就是寻找最长的递增有序序列.解法有非常多 ...

  5. [Leetcode] distinct subsequences 不同子序列

    Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence ...

  6. Leetcode之深度优先搜索&回溯专题-491. 递增子序列(Increasing Subsequences)

    Leetcode之深度优先搜索&回溯专题-491. 递增子序列(Increasing Subsequences) 深度优先搜索的解题详细介绍,点击 给定一个整型数组, 你的任务是找到所有该数组 ...

  7. [Swift]LeetCode491. 递增子序列 | Increasing Subsequences

    Given an integer array, your task is to find all the different possible increasing subsequences of t ...

  8. [LeetCode] Increasing Triplet Subsequence 递增的三元子序列

    Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the ar ...

  9. Longest Increasing Subsequences(最长递增子序列)的两种DP实现

    一.本文内容 最长递增子序列的两种动态规划算法实现,O(n^2)及O(nlogn).     二.问题描述 最长递增子序列:给定一个序列,从该序列找出最长的 升序/递增 子序列. 特点:1.子序列不要 ...

随机推荐

  1. javaScript设计模式 -- 灵活的javaScript语言

    因为好长时间的懒惰和懈怠,好久没有更新文章了,从现在开始我会按时更新一些自己总结的一些知识,和研究的东西,希望能让大家从我这里学到一点点的知识. 本文参考了张荣铭的javascript设计模式一书,算 ...

  2. php数组排序和查找的算法

    1.php算法 // 算法 // 1.冒泡排序 => 思路:​每次循环排列出一个最大的数 // echo '<pre>'; $arr = [ 1,43,54,62,21,66,32, ...

  3. Java基础学习笔记七 Java基础语法之继承和抽象类

    继承 继承的概念 在现实生活中,继承一般指的是子女继承父辈的财产.在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系. 例如公司中的研发部员工和维护部员工都属于员工, ...

  4. pyc反编译-uncompyle2的安装及使用

    pyc反编译-uncompyle2的安装及使用 0x00 安装 1.下载并解压到安装目录 python setup.py install //安装 2.下载链接: 链接:https://pan.bai ...

  5. 使用Dockerfile创建一个tomcat镜像,并运行一个简单war包

    docker已经看了有一段时间了,对镜像和容器也有了一个大致了解,参考书上的例子制作一个tomcat镜像,并简单运行一个HelloWorld.war 1.首先下载linux环境的tomcat和jdk, ...

  6. MyGod_alpha版本测试报告

    买尬-Alpha版本测试报告 @(二手市场APP)[MyGod团队|团队项目|版本测试] 项目名称:武汉大学校园二手市场APP--买尬 软件版本:1.0.0 开发团队:MyGod 开发代表:程环宇 张 ...

  7. edittext实现自动查询,刷新listview

    mEdittextqueryvalue.addTextChangedListener(new TextWatcher() {             @Override             pub ...

  8. Hibernate之ORM与Hibernate

    ORM: ORM是 Object /Relation Mapping,对象/关系数据库映射. 目前比较流行的编程语言,如java ,c#等,它们都是面向对象的编程语言,而目前比较主流的数据库产品,如O ...

  9. python 面向对象之封装与类与对象

    封装 一,引子 从封装本身的意思去理解,封装就好像是拿来一个麻袋,把小猫,小狗,小王八,小老虎一起装进麻袋,然后把麻袋封上口子.照这种逻辑看,封装='隐藏',这种理解是相当片面的 二,先看如何隐藏 在 ...

  10. 微信qq,新浪等第三方授权登录的理解

    偶们常说的第三方是指的微信,qq,新浪这些第三方,因为现在基本每个人都有qq或者微信,那么我们就可以通过这些第三方进行登录.而这些网站比如慕课网是通过第三方获取用户的基本信息 它会有个勾选按钮,提示是 ...