[Leetcode] 491. Increasing Subsequences 解题报告
来源:互联网 发布:吹笛子软件 编辑:程序博客网 时间:2024/05/04 13:38
题目:
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:
- The length of the given array will not exceed 15.
- The range of integer in the given array is [-100,100].
- The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence.
思路:
1、DFS+backtracking:这是稍微有点变形的DFS题目:对于nums中的每个整数,如果符合条件,我们有两种选择:1)将它加入到结果中,然后进行DFS并且回溯;2)忽略它,直接进行DFS。为此我们在dfs的内部设立一个哈希表,表示已经尝试过的整数。这样对于具有重复整数的情况,比如例子中给出的[4, 6, 7, 7],当我们遇到第一个7之后,则包含7的所有升序组合都已经被输出了,那么当遇到第二个7的时候,我们就可以忽略。否则就生成重复结果了。
我发现DFS + BackTracking的题目往往有两种模板,一种是dfs中没有for循环的,也就是只调用DFS的下一层(有点像在dfs内部再进行dfs);另一种是dfs内含有从当前位置到末尾的for循环的,也就是在dfs内,平行的调用dfs(有点像dfs内部再进行一个bfs)。前一种模板适合无局部状态的情况,而后一种模板则比较适合需要记录局部状态的情况,例如本题目中我们需要记录已经采用过的整数。
2、前缀生成法:注意到一个升序序列总是可以由升序的前缀加上当前整数组成,所以我们可以采用递推的方式由升序的前缀生成所有的结果。例如对于本题目,我们初始的升序前缀是{},那么随着扫描的进行,结果的变化依次是:
当扫描到4之后,由升序前缀{{}}生成{4},然后升序前缀更新为{{}, {4}};
当扫描到6之后,由升序前缀{{}, {4}}生成{{6}, {4, 6}},然后升序前缀更新为{{}, {4}, {6}, {4, 6}};
当扫描到7之后,由升序前缀{{}, {4}, {6}, {4, 6}}生成{{7}, {4, 7}, {6, 7}, {4, 6, 7}},然后升序前缀更新为{{}, {4}, {6}, {4, 6}, {7}, {4, 7}, {6, 7}, {4, 6, 7}};
当再次扫描到7之后,由升序前缀{{}, {4}, {6}, {4, 6}, {7}, {4, 7}, {6, 7}, {4, 6, 7}}可以生成{{7}, {4, 7}, {6, 7}, {4, 6, 7}, {7, 7}, {4, 7, 7}, {6, 7, 7}, {4, 6, 7, 7}},然后升序前缀更新为{{}, {4}, {6}, {4, 6}, {7}, {4, 7}, {6, 7}, {4, 6, 7},{7}, {4, 7}, {6, 7}, {4, 6, 7}, {7, 7}, {4, 7, 7}, {6, 7, 7}, {4, 6, 7, 7}}。注意到背景为灰色的部分是重复元素,它们在set中将会被去重。最后再筛选出长度大于等于2的升序序列即可。
代码:
1、DFS+backtracking:
class Solution {public: vector<vector<int>> findSubsequences(vector<int>& nums) { vector<vector<int>> ret; vector<int> line; dfs(nums, ret, line, 0); return ret; }private: void dfs(vector<int> &nums, vector<vector<int>> &ret, vector<int> &line, int pos) { if (line.size() > 1) { ret.push_back(line); } unordered_set<int> hash; for (int i = pos; i < nums.size(); ++i) { if((line.empty() || nums[i] >= line.back()) && hash.find(nums[i]) == hash.end()) { line.push_back(nums[i]); dfs(nums, ret, line,i + 1); line.pop_back(); hash.insert(nums[i]); // the key point to avoid repeatation } } }};
2、前缀生成法:
class Solution {public: vector<vector<int>> findSubsequences(vector<int>& nums) { set<vector<int>> seqs = {vector<int>(0)}; // increasing prefix for (int i = 0; i < nums.size(); i++) { vector<vector<int>> built(seqs.size()); // get a copy of seqs std::copy(seqs.begin(), seqs.end(), built.begin()); for (auto seq : built) { if (seq.empty() || nums[i] >= seq.back()) { seq.push_back(nums[i]); seqs.insert(seq); } } } vector<vector<int>> res; for (auto seq : seqs) if (seq.size() > 1) { res.push_back(seq); } return res; }};
- 【LeetCode】491.Increasing Subsequences(Medium)解题报告
- [Leetcode] 491. Increasing Subsequences 解题报告
- Leetcode 491. Increasing Subsequences 上升序列 解题报告
- 【LeetCode】 491. Increasing Subsequences
- LeetCode 491. Increasing Subsequences
- LeetCode 491. Increasing Subsequences
- [LeetCode]491. Increasing Subsequences
- [leetcode]491. Increasing Subsequences
- 【Leetcode】491. Increasing Subsequences
- [leetcode] 491. Increasing Subsequences
- Leetcode -- 491. Increasing Subsequences
- leetcode-491. Increasing Subsequences
- (LeetCode) 491. Increasing Subsequences
- LeetCode 491. Increasing Subsequences
- Leetcode-491. Increasing Subsequences
- leetcode 491. Increasing Subsequences
- LeetCode-491. Increasing Subsequences
- LeetCode 491. Increasing Subsequences
- 不同博客的使用体验
- Android7.0适配心得(一)_拍照兼容
- 常见的视频质量客观测试标准
- 判断一棵树是否是二叉排序树算法的巧妙之处
- Java操作zip压缩和解压缩文件工具类
- [Leetcode] 491. Increasing Subsequences 解题报告
- winfrom开发框架
- 技术人员应该明白的几点tips
- STM32L152 USART HAL库接收任意长度数据详细解析
- C# web实现邮件发送小案例一
- (二)java框架篇笔记库(16)
- 人脸识别CNN网络微调流程
- 短波电台
- 软件调试笔记32