Combination Sum求和为给定值的所有序列的解题思路
来源:互联网 发布:淘宝电商是什么 编辑:程序博客网 时间:2024/05/18 17:40
因为数字可以重复,毫无疑问,这道题要用回溯来解。写出代码不难如下:
class Solution {public: vector<vector<int> > rec_combinationSum(vector<int> &candidates, int target) { vector<vector<int>> res; if(target==0){ res.push_back(vector<int>()); return res; } int tar = target; for(auto c:candidates){ target -=c; if(target<0){target +=c;continue;} auto vv = rec_combinationSum(candidates,target); for(auto vec:vv){ if(accumulate(vec.begin(),vec.end(),c) == tar) { vec.push_back(c); sort(vec.begin(),vec.end()); res.push_back(vec); } } target +=c; } return res; } vector<vector<int> > combinationSum(vector<int> &candidates, int target){ vector<vector<int>> res; if(candidates.size()==0) return res; sort(candidates.begin(),candidates.end()); res = rec_combinationSum(candidates,target); sort(res.begin(),res.end()); auto it=unique(res.begin(),res.end()); res.resize(distance(res.begin(),it)); return res; }};
但是,有一个问题就是运行速度很慢,在Leetcode168个测试用例上出现了TLE,这是回溯需要解决的问题。如果先不考虑剪枝,是不是因为代码中大量的排序导致变慢呢?每次计算得到一个结果都要排序,而且还有不少重复的。如果用set或者unordered_set来存储是否可以搞定呢?要为unordered_set<vector<int>>写一个hash函数类,因为vector<int>不是基本基本类型,代码如下:
class MyHash{public: size_t operator()(const vector<int> &v) const { size_t x = 0; for (auto &i : v) x ^= std::hash<int>()(i); return x; }};class Solution {public: unordered_set<vector<int>,MyHash > rec_combinationSum(vector<int> &candidates, int target) { unordered_set<vector<int>,MyHash> res; if(target==0){ res.insert(vector<int>()); return res; } int tar = target; for(auto c:candidates){ target -=c; if(target<0){target +=c;continue;} auto vv = rec_combinationSum(candidates,target); for(auto vec:vv){ if(accumulate(vec.begin(),vec.end(),c) == tar) { vec.push_back(c); sort(vec.begin(),vec.end()); res.insert(vec); } } target +=c; } return res; } vector<vector<int> > combinationSum(vector<int> &candidates, int target){ unordered_set<vector<int>,MyHash> tmp; vector<vector<int> > res; if(candidates.size()==0) return res; sort(candidates.begin(),candidates.end()); tmp = rec_combinationSum(candidates,target); for(auto vec:tmp) res.push_back(vec); return res; }};
结果发现仍然是TLE,这里虽然省去了排序,去重,理论上插入还是线性,但仍然不行。看来数据结构上的优化无法帮助解决本TLE问题。
下面只能考虑剪枝了。怎么剪?这个问题有什么特点?
正常情况下,当选定一个数字之后,下面仍然要把每个数字都再考虑一遍;有没有一种方法,某个数字的情况考虑完之后就不再考虑该数字出现的情况?存在不存在?答案是存在,那就是要对数列进行排序,排序之后,我们发现如果某个数字考虑过,则包含该数字的所有情况,包括重复的情况都在回溯的过程中考虑了。所以之后,就不必再考虑该种情况了,此处可剪枝。
class Solution {public: vector<vector<int>> rec_combinationSum(vector<int> &candidates, int target,int idx) { vector<vector<int>> res; if(target==0){ res.push_back(vector<int>()); return res; } int tar = target; for(int i=idx;i<candidates.size();++i){ target -=candidates[i]; if(target<0){target +=candidates[i];continue;} auto vv = rec_combinationSum(candidates,target,i); for(auto vec:vv){ if(accumulate(vec.begin(),vec.end(),candidates[i]) == tar) { vec.push_back(candidates[i]); sort(vec.begin(),vec.end()); res.push_back(vec); } } target +=candidates[i]; } return res; } vector<vector<int> > combinationSum(vector<int> &candidates, int target){ vector<vector<int> > res; if(candidates.size()==0) return res; sort(candidates.begin(),candidates.end()); res = rec_combinationSum(candidates,target,0); return res; }};
增加了一个参数,该参数保存当前访问的数值,考虑完之后不再考虑之前的所有元素而是从下一个开始,达到了剪枝的目的。速度大概是108ms,仍然不佳。
0 0
- Combination Sum求和为给定值的所有序列的解题思路
- Combination Sum求和为给定值的所有序列的解题思路(续)
- 求数组中和为给定值的所有子序列
- leetCode 16.3Sum Closest (离给定值最近的三数之和) 解题思路和方法
- Combination Sum II:允许重复的数组中选取若干元素使和为某一给定值
- 和为给定值的所有组合
- Combination Sum:非重复数组中选取若干元素求和等于给定值
- Leetcode #39. Combination Sum 组合求和 解题报告
- Leetcode #40. Combination Sum II 组合求和2 解题报告
- leetcode解题之 Combination Sum java 版(组合求和)
- poj 1564 Sum It Up 【DFS】【求和为N的所有数的组合】
- leetCode 39.Combination Sum(组合总和) 解题思路和方法
- 剑指offer--求和为sum的连续序列,并用vector<vector<int>>来存储
- 求解所有集合中和为给定值的组合
- 求二叉树中和为给定值的所有路径
- 给一个正整数sum,打印出所有和为sum的连续正整数序列之和。
- 在给定数组中查找两个数的和为给定值sum
- 每天一道LeetCode-----找出给定序列的所有子序列
- 黑马程序员——Objective-C程序设计(第4版)学习笔记之20-Cocoa和Cocoa Touch简介——黑马 IOS 技术博客
- Android程序开发重新开始一
- 安装office2007安装程序找不到office.zh-cn\*三种详细解决方案
- Spark SQL之External DataSource外部数据源(一)示例
- 炸弹
- Combination Sum求和为给定值的所有序列的解题思路
- 分布式系统阅读笔记(三)-----计算机网络和网络互连技术
- 离散时间序列的内插算法(sinc 函数内插)
- 【第二次作业】
- MTK 软件设置路径
- 第十七周项目2-引用做形参(2)
- Emacs常用命令快速参考
- javabean内省
- python命令行解析