每天一道LeetCode-----找出给定序列的所有子序列
来源:互联网 发布:自学设计软件 编辑:程序博客网 时间:2024/06/05 05:00
Subsets
原题链接Subsets
给定一个数组序列,找出所有子序列
深度优先扫一遍:)
class Solution {public: vector<vector<int>> subsets(vector<int>& nums) { vector<vector<int>> res; vector<int> cur; dfs(0, nums, cur, res); return res; }private: void dfs(int i, vector<int>& nums, vector<int>& cur, vector<vector<int>>& res) { res.emplace_back(cur); if(i >= nums.size()) return; for(int j = i; j < nums.size(); ++j) { cur.push_back(nums[j]); dfs(j + 1, nums, cur, res); cur.pop_back(); } }};
原题链接Subsets II
找到给定序列的所有子序列,给定的序列中可能会包含重复元素
解题时需要注意几个地方
- 容我好好吐槽一下,根本没有说明好伐:(
- 最后的结果中子序列的顺序无要求,即[1,2,3]和[3,2,1]是相同的
- 对于重复元素,第二条规定尤为重要,即[4,4,4,1]和[4,4,1,4]是相同的
- 更重要的是,对于第三条,[1,4,4,4]和[4,4,4,1]以及[4,4,1,4]同样是相同的
用[1,2,3]代替[3,2,1]以及用[1,4,4,4]代替[4,4,1,4]是什么概念,就是说所有子序列可以都是递增的,再往上想就是可以事先对给定序列排序,那解决重复问题就简单多了
在Subsets中,通过深度优先找到了所有的子序列,但是如果序列中有重复元素,需要添加几个限制条件
以序列[4,4,4,1,4]举例,如果不添加限制条件,那么最后的结果可能存在
[4,4,4,1],[4,4,1,4]以及[4,1],[1,4]以及[4,4,4],[4,4,4]
毫无疑问上面二个都是相同的,即结果中出现重复元素,不符合要求
深度优先和回溯在解决重复问题时通常是在下次递归之前判断当前要添加到结果集中的元素是否应该被添加到结果集中,针对Subsets的模板
class Solution {public: vector<vector<int>> subsetsWithDup(vector<int>& nums) { //std::sort(nums.begin(), nums.end()); vector<vector<int>> res; vector<int> cur; dfs(nums, 0, cur, res); return res; }private: void dfs(vector<int>& nums, int i, vector<int>& cur, vector<vector<int>>& res) { res.emplace_back(cur); for(int j = i; j != nums.size(); ++j) { //判断是否应该添加到结果集中 if(...) { cur.emplace_back(nums[j]); dfs(nums, j + 1, cur, res); cur.pop_back(); } } }};
方法就是判断nums[j]是否在[i : j-1]这个范围内出现过,考虑当前遍历到[1,4,4,4,4] (已排序)的下标1(即元素4的位置),在回溯之后遍历的下标改为2(即第二个元素4的位置),这就会重复
因为在遍历第一个4时进入深度优先递归,在递归的过程中已经将所有组合可能都记录到结果中,其中就包括下标组合[1,3,4],那和第二次递归的下标组合[2,3,4]其实是一样的,结果都是[4,4,4]
原因是对于任何重复的元素,只需要考虑第一个即可,假设i, i+1, i+2, …, k是重复元素,那么选择nums[i]和选择nums[i+2]是一样的,因为选择nums[i]时,可以假设递归时不选择nums[i+1],那么就和直接选择nums[i+2]一样了
代码如下
class Solution {public: vector<vector<int>> subsetsWithDup(vector<int>& nums) { std::sort(nums.begin(), nums.end()); vector<vector<int>> res; vector<int> cur; dfs(nums, 0, cur, res); return res; }private: void dfs(vector<int>& nums, int i, vector<int>& cur, vector<vector<int>>& res) { res.emplace_back(cur); for(int j = i; j != nums.size(); ++j) { if(j == i || nums[j] != nums[j - 1]) { cur.emplace_back(nums[j]); dfs(nums, j + 1, cur, res); cur.pop_back(); } } }};
- 每天一道LeetCode-----找出给定序列的所有子序列
- 每天一道LeetCode-----计算给定序列中所有长度为k的滑动窗的最大值集合
- 每天一道LeetCode-----计算两个序列最长的公共子序列长度
- 每天一道LeetCode-----给定序列中2/3/4个元素的和为target的所有集合,或3个元素的和最接近target的集合
- 每天一道LeetCode-----最长回文子串/序列,从头开始的最长回文子串长度
- 每天一道LeetCode-----找到给定序列中所有和为某个值的集合或集合个数,序列中可以有/无重复项,集合元素顺序不同算不同集合等
- 求数组中和为给定值的所有子序列
- 在给定整数序列中,找出最大和的子序列...
- 找出数据库的所有序列
- 自然数序列,找出任意连续之和等于n的所有子序列
- 给定一个长度为N的数组,找出一个最长的单调自增子序列
- 给定一个数字序列,输出一个最长的子序列
- 每天一道LeetCode-----删除序列中指定元素,将满足要求的元素移动到前面
- 每天一道LeetCode-----获取无重复项/有重复项序列的全排列
- 每天一道LeetCode-----某个数在递增序列第一次和最后一次出现的位置
- 每天一道LeetCode-----寻找地增序列中第一个大于等于目标元素的位置
- 找出最长的顺序子序列
- 给定两个已排序序列,找出共同的元素
- jedis是什么?jedis概念
- 第一次机房收费系统--收取金额
- 巧用VMware Workstation的clone来制作虚拟机模板
- Eclipse中修改Maven 仓库位置
- 动态规划作业
- 每天一道LeetCode-----找出给定序列的所有子序列
- OpenCV提取显示一张图片的R,G,B颜色分量
- Java设计模式——命令模式、模板方法、迭代器和组合模式
- 12.07学习计划
- Linux中c程序的编译链接过程2017/12/10
- cef3编译记录经典资料
- vector实现和使用
- java--数组3
- UE4 道路编辑 Spline的使用