题目:

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的更多相关文章

  1. leetcode第39题--Combination Sum II

    题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...

  2. 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 ...

  3. LeetCode(40) Combination Sum II

    题目 Given a collection of candidate numbers (C) and a target number (T), find all unique combinations ...

  4. LeetCode笔记:39. Combination Sum

    题目描述 给定一个无重复的正整数数组 candidates 和一个正整数 target, 求所有和为 target 的 candidates 中数的组合中.其中相同数的不同顺序组合算做同一种组合,ca ...

  5. LeetCode(39) Combination Sum

    题目 Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C w ...

  6. leetcode第38题:报数

    这是一道简单题,但是我做了很久,主要难度在读题和理解题上. 思路:给定一个数字,返回这个数字报数数列.我们可以通过从1开始,不断扩展到n的数列.数列的值为前一个数列的count+num,所以我们不断叠 ...

  7. leetcode个人题解——#39 Combination Sum

    思路:先对数据进行排序(看评论给的测试数据好像都是有序数组了,但题目里没有给出这个条件),然后回溯加剪枝即可. class Solution { public: ; vector<vector& ...

  8. LeetCode:40. Combination Sum II(Medium)

    1. 原题链接 https://leetcode.com/problems/combination-sum-ii/description/ 2. 题目要求 给定一个整型数组candidates[ ]和 ...

  9. Leetcode 之 Combination Sum系列

    39. Combination Sum 1.Problem Find all possible combinations of k numbers that add up to a number n, ...

随机推荐

  1. 【MySQL笔记】mysql来源安装/配置步骤和支持中国gbk/gb2312编码配置

    不久的学习笔记.分享.我想有很大的帮助谁刚开始学习其他人的 备注:该票据于mysql-5.1.73版本号例如 1. mysql源代码编译/安装步骤 1) 官网下载mysql源代码并解压 2) cd至源 ...

  2. javascript小白学习指南0---1

    引言: 做为一名程序猿.都是真心的想把自己的东西分享出来,供大家一起学习探讨.一起提高技能.一起涨工资,呵   这一系列的文章都是关于Javascript 基础的 当然文章其中穿插了些我自己的理解.希 ...

  3. Spark里边:到底是什么RDD

    RDD它是Spark基,它是最根本的数据抽象.http://www.cs.berkeley.edu/~matei/papers/2012/nsdi_spark.pdf 它开着RDD文件.假设英语阅读太 ...

  4. Microservice架构模

    Microservice架构模 在2014年,Sam Newman,Martin Fowler在ThoughtWorks的一位同事,出版了一本新书<Building Microservices& ...

  5. 第1章 单例模式(Single Pattern)

    原文 第1章 单例模式(Single Pattern) 单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点. 一.常用模式: 1 ...

  6. 汉字转拼音 oracle方式 [转]

    oracle汉字转拼音(获得全拼/拼音首字母/拼音截取等)   效果如下: Oracle 字符集 GBK 没有问题 , UTF -8 需要修改一下   Sql代码   --oracle汉字转拼音 PA ...

  7. div元素上下左右居中

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  8. 使用Blend的一些问题

    原文:使用Blend的一些问题 WPF开发,界面处理首选Blend,如果你开发了两年WPF都没接触过blend(当然这种几率不高),或者你刚接触WPF,可以考虑使用Blend,这货也算得上一个神器,上 ...

  9. 杭电1162Eddy&#39;s picture

    Eddy's picture Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Tota ...

  10. 1.cocos2dx存储卡的游戏代码、而游戏移植到“华为荣耀”电话、问题的总结移植

     1记忆卡片游戏代码 CardItem.h #pragmaonce #ifndef__CardItem_H__ #define__CardItem_H__ #include"cocos2 ...