leetcode第38题--Combination Sum
题目:
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
- The solution set must not contain duplicate combinations.
For example, given candidate set 2,3,6,7 and target 7,
A solution set is: [7] [2, 2, 3]
题目的意思是给定一个candidate集合,里面包含一些数字,给定一个目标T,在集合中找出可以组合成T的所有组合,集合中的数字可以重复利用。但组合后的结果不能重复。结果中按非降序排列。举例集合C为 2,3,6,7 目标位7,那么就有两种组合满足,一个是[2,2, 3] 一个是[7]
思路:
利用回溯法,深度优先。剪枝判断是相加的数大于目标时返回,或者相加之和为目标的时候记录在ans中并返回。如果相加小于目标,那就往下一层找,找到满足要返回的条件为止。
class Solution {
public:
int sum38(vector<int> vec) // 返回vec中所有值的和,用来和target判断用
{
if (vec.size() == 0)
return -1;
int len = vec.size(), ans = 0;
for (int i = 0; i < len; ++i)
{
ans += vec[i];
}
return ans;
}
void back38(vector<vector<int> > &ans, vector<int> &candidates, vector<int> &tmp, int target, int cur)
{
for (int i = cur; i < candidates.size(); ++i) // i从传入的cur下标开始,cur初始为0,之后根据i改变,为了保证不会有重复解
{
int num = sum38(tmp); // 避免三个if语句都调用sum38,计算一次就好,否则超时
if (num == target)
{
ans.push_back(tmp); // 如果找到了一组,就记录后返回
return;
}
if (num < target) // 如果比目标还小,说明还要在加一个数
{
tmp.push_back(candidates[i]);
back38(ans, candidates, tmp, target, i); // tmp加了一个数后再递归,注意此处传入的cur为i,这样为了保证不会有重复的解
// 因为candidates是排好序的,所以之后递归中要加的数只能是下标i之后的
tmp.pop_back(); // 递归返回到这可定是之前相等或者是大于了,所以要去掉tmp的最后一个,再继续找
}
if (num > target)
{
return;
}
}
}
vector<vector<int> > combinationSum(vector<int> &candidates, int target)
{
std::sort(candidates.begin(), candidates.end()); // 因为给的数不是有序的,所以一定要先排好序,才能为之后避免重复解
vector<vector<int> > ans;
vector<int> tmp;
back38(ans, candidates, tmp, target, 0);
return ans;
}
};
这个在oj上要440ms。发现时间主要是用在计算vec的和上了。在网上看别人的做法,发现还有个巧妙的技巧。就是传入的target每次变小,知道为零是即为满足条件。剪枝判断是用target和当前想要加入的元素进行比较,如果target比较大那就把target减去要加入的元素之后的值当做下一次的target。同理如果要加入的值都比当前的target更大了就可以剪枝返回了。
这个代码只要80ms,提高了5倍
void back38(vector<vector<int> > &ans, vector<int> &candidates, vector<int> &tmp, int target, int cur)
{
for (int i = cur; i < candidates.size(); ++i)
{
if (0 == target) // 为零即之前的组合满足最初target
{
ans.push_back(tmp);
return;
}
if (candidates[i] <= target) // 如果将要加入的不比目标大,加入
{
tmp.push_back(candidates[i]);
back38(ans, candidates, tmp, target - candidates[i], i);
tmp.pop_back();
}
if (candidates[i] > target) // 剪枝
{
return;
}
}
}
leetcode第38题--Combination Sum的更多相关文章
- leetcode第39题--Combination Sum II
题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...
- Leetcode 39 40 216 Combination Sum I II III
Combination Sum Given a set of candidate numbers (C) and a target number (T), find all unique combin ...
- LeetCode(40) Combination Sum II
题目 Given a collection of candidate numbers (C) and a target number (T), find all unique combinations ...
- LeetCode笔记:39. Combination Sum
题目描述 给定一个无重复的正整数数组 candidates 和一个正整数 target, 求所有和为 target 的 candidates 中数的组合中.其中相同数的不同顺序组合算做同一种组合,ca ...
- LeetCode(39) Combination Sum
题目 Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C w ...
- leetcode第38题:报数
这是一道简单题,但是我做了很久,主要难度在读题和理解题上. 思路:给定一个数字,返回这个数字报数数列.我们可以通过从1开始,不断扩展到n的数列.数列的值为前一个数列的count+num,所以我们不断叠 ...
- leetcode个人题解——#39 Combination Sum
思路:先对数据进行排序(看评论给的测试数据好像都是有序数组了,但题目里没有给出这个条件),然后回溯加剪枝即可. class Solution { public: ; vector<vector& ...
- LeetCode:40. Combination Sum II(Medium)
1. 原题链接 https://leetcode.com/problems/combination-sum-ii/description/ 2. 题目要求 给定一个整型数组candidates[ ]和 ...
- Leetcode 之 Combination Sum系列
39. Combination Sum 1.Problem Find all possible combinations of k numbers that add up to a number n, ...
随机推荐
- [Network]Transport Layer
1 Principles behind Transport Layer Services 1.1 Multiplexing/Demultiplexing Multiplexing at sender ...
- Spring AOP在pointcut expression解析表达式 并匹配多个条件
Pointcut 方法是那些需要运行"AOP",由"Pointcut Expression"为了描述叙事. Pointcut以下方法可以通过定义任&&a ...
- 采用shell脚本统计代码的行数
刚毕业那会儿有一次去台湾公司面试,我问多行代码怎么写.我从来没有想过这个问题,粗略计算,.惊叹:大概几十万行不行. 最近整理资料,看着eclipse左边全面上市,我觉得这个东西.代码共同拥有的行倒底总 ...
- The Swift Programming Language中国完整版
近来的ios的swift语言似乎火了.我没有objectc基金会,但在此之前有c随着java在...的基础上.从几天开始学习ios的swift语言,晚发表在博客形式.下面是英文版本翻译swif图书.还 ...
- verilog中的有符号数运算
verilog中的有符号数运算 http://hi.baidu.com/lixu1113/item/d00dc095f86aed48f142159a verilog中的有符号数运算 有符号数的计算:若 ...
- Javascript标准类型的方法集
1 array.concat(item...) concat方法会产生一个新数组,将一个或多个item附加在数组之后 var a = ['a', 'b', 'c'] var b = ['x', 'y' ...
- Java Web整合开发(4) -- JSP
JSP脚本中的9个内置对象: application: javax.servlet.ServletContext config: javax.servlet.ServletCo ...
- SharePoint 如何使自己的网页自动跳转
SharePoint 如何使自己的网页自动跳转 SharePoint自动制作自己的网页跳的很easy,只有在页面上要添加一个Web部分--内容编辑器,对应的js代码就可以. ...
- Android 4.4(KitKat)表格管理子系统 - 骨架
原文地址:http://blog.csdn.net/jinzhuojun/article/details/37737439 窗体管理系统是Android中的主要子系统之中的一个.它涉及到App中组件的 ...
- (两)unity4.6Ugui中国教程文档-------总结-UGUI Canvas
大家好,我是广东太阳. 转载请注明出处:http://write.blog.csdn.net/postedit/38922399 更全的内容请看我的游戏蛮牛地址:http://www.unitym ...