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:

Input: [4, 6, 7, 7]
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时,才加入结果。然后就是要递增,如果之前的数字大于当前的数字,那么跳过这种情况,继续循环,参见代码如下:

解法一:

class Solution {
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
set<vector<int>> res;
vector<int> out;
helper(nums, , out, res);
return vector<vector<int>>(res.begin(), res.end());
}
void helper(vector<int>& nums, int start, vector<int>& out, set<vector<int>>& res) {
if (out.size() >= ) res.insert(out);
for (int i = start; i < nums.size(); ++i) {
if (!out.empty() && out.back() > nums[i]) continue;
out.push_back(nums[i]);
helper(nums, i + , out, res);
out.pop_back();
}
}
};

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

解法二:

class Solution {
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
vector<vector<int>> res;
vector<int> out;
helper(nums, , out, res);
return res;
}
void helper(vector<int>& nums, int start, vector<int>& out, vector<vector<int>>& res) {
if (out.size() >= ) res.push_back(out);
unordered_set<int> st;
for (int i = start; i < nums.size(); ++i) {
if ((!out.empty() && out.back() > nums[i]) || st.count(nums[i])) continue;
out.push_back(nums[i]);
st.insert(nums[i]);
helper(nums, i + , out, res);
out.pop_back();
}
}
};

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

解法三:

class Solution {
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
set<vector<int>> res;
vector<vector<int>> cur();
for (int i = ; i < nums.size(); ++i) {
int n = cur.size();
for (int j = ; j < n; ++j) {
if (!cur[j].empty() && cur[j].back() > nums[i]) continue;
cur.push_back(cur[j]);
cur.back().push_back(nums[i]);
if (cur.back().size() >= ) res.insert(cur.back());
}
}
return vector<vector<int>>(res.begin(), res.end());
}
};

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

解法四:

class Solution {
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
vector<vector<int>> res, cur();
unordered_map<int, int> m;
for (int i = ; i < nums.size(); ++i) {
int n = cur.size(), start = m[nums[i]];
m[nums[i]] = n;
for (int j = start; j < n; ++j) {
if (!cur[j].empty() && cur[j].back() > nums[i]) continue;
cur.push_back(cur[j]);
cur.back().push_back(nums[i]);
if (cur.back().size() >= ) res.push_back(cur.back());
}
}
return res;
}
};

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. JavaWeb学习笔记八 监听器

    监听器Listener jservlet规范包括三个技术点:servlet :listener :filter:监听器就是监听某个对象的的状态变化的组件.监听器的相关概念事件源: 被监听的对象(三个域 ...

  2. android 与 服务器通信

    android 与 服务器通信 服务端代码: (1)control 层 /** * 用户登录 * @return */ @RequestMapping(value = "/login&quo ...

  3. 第二次作业-关于Steam游戏平台的简单分析

    1.1 Steam平台的简单介绍 你选择的产品是? 如题,这次的作业我选择了Steam作为分析的对象. 为什么选择该产品作为分析? 我选择数字游戏贩售平台STEAM作为分析对象的原因有以下几点: 1. ...

  4. 高级软件工程2017第6次作业--团队项目:Alpha阶段综合报告

    高级软件工程2017第6次作业--团队项目:Alpha阶段综合报告 Deadline:2017-10-30(周一)21:00pm (注:以下内容参考集大作业4,集大作业5,集大作业6,集大作业7 一. ...

  5. 20145237 《Java程序设计》第10周学习总结

    20145237 <Java程序设计>第10周学习总结 教材学习内容总结 Java的网络编程 •网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. •java.n ...

  6. js的 == 和 ===的区别

    1.对于string,number等基础类型,==和===是有区别的 不同类型间比较,==之比较转化成同一类型后的值看值是否相等,===如果类型不同,其结果就是不等,同类型比较,直接进行"值 ...

  7. linux 下 nc 命令的使用

    netcat被誉为网络安全界的'瑞士军刀',一个简单而有用的工具,透过使用TCP或UDP协议的网络连接去读写数据.它被设计成一个稳定的后门工具,能够直接由其它程序和脚本轻松驱动.同时,它也是一个功能强 ...

  8. java 注解的实现机制

    一.什么是注解: 注解是标记,也可以理解成是一种应用在类.方法.参数.属性.构造器上的特殊修饰符.注解作用有以下三种: 第一种:生成文档,常用的有@param@return等. 第二种:替代配置文件的 ...

  9. JAVA_SE基础——12.运算符的优先级

    优先级 操作符 含义 关联性 用法 ---------------------------------------------------------------- 1 [ ] 数组下标 左 arra ...

  10. javascript原型链__proto__属性的理解

    在javascript中,按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头.一个方法使用new操作符创建,例如下面代码块中的Person1(可以吧Person1看做 ...