题目:

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

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 10,1,2,7,6,1,5 and target 8
A solution set is: 
[1, 7] 
[1, 2, 5] 
[2, 6] 
[1, 1, 6]

链接: http://leetcode.com/problems/combination-sum-ii/

题解:

依然是一道DFS + Backtracking题目。 与之前不同的是每个数字只允许使用一次。所以在回溯的循环里当 i > pos时,假如之后又重复的,continue。我们依然使用candidates[i],而且candidates[i + 1]假如等于candidates[i], 会在DFS的下一个阶段被使用到。当然假如不用这个巧妙的条件也可以, 可以在 target == 0的时候判断res中是否contains  list,这样的话运行速度会慢不少,但也可以AC.

Time Complexity - O(), Space Complexity - O()。 如何计算复杂度,智商捉急啊...

public class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
if(candidates == null || candidates.length == 0)
return res;
Arrays.sort(candidates);
ArrayList<Integer> list = new ArrayList<>();
dfs(res, list, candidates, target, 0);
return res;
} private void dfs(List<List<Integer>> res, ArrayList<Integer> list, int[] candidates, int target, int pos) {
if(target == 0) {
res.add(new ArrayList<Integer>(list));
return;
}
if(pos >= candidates.length || target < 0)
return; for(int i = pos; i < candidates.length; i++) {
if(i > pos && candidates[i] == candidates[i - 1]) //for i > pos, if duplicate,continue. we still use candidates[i]
continue;
list.add(candidates[i]);
dfs(res, list, candidates, target - candidates[i], i + 1);
list.remove(list.size() - 1);
}
}
}

二刷:

这里依然是用了跟上一题目很接近的方法。不同的地方在于,每个数字不可以被无限次。所以一个数只能一次,而且遇到重复数字我们要跳过。这样我们在for循环里要加入一条 -  if (i > pos && candidates[i] == candidates[i - 1]) continue; 并且在DFS的时候每次

每次新的position = i + 1, 并不是上一题的position = i。

看到有discuss里有方法用array来做backtracking,速度beat 99%,以后也可以把list改成array,试一试这种方法。

Java:

public class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
if (candidates == null || candidates.length == 0) {
return res;
}
Arrays.sort(candidates);
List<Integer> comb = new ArrayList<>();
combinationSum2(res, comb, candidates, target, 0);
return res;
} private void combinationSum2(List<List<Integer>> res, List<Integer> comb, int[] candidates, int target, int pos) {
if (target < 0) {
return;
} else if (target == 0) {
res.add(new ArrayList<>(comb));
}
for (int i = pos; i < candidates.length; i++) {
if (i > pos && candidates[i] == candidates[i - 1]) {
continue;
}
int num = candidates[i];
if (num > target) {
return;
}
comb.add(num);
combinationSum2(res, comb, candidates, target - num, i + 1);
comb.remove(comb.size() - 1);
}
}
}

三刷:

跟上题唯一不同就是递归时把控制position的变量从 i 变成了 i + 1,这样我们就不会对一个元素进行多次计算。

Java:

public class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
if (candidates == null) return res;
Arrays.sort(candidates);
findCombinations(res, new ArrayList<>(), candidates, target, 0);
return res;
} private void findCombinations(List<List<Integer>> res, List<Integer> list, int[] candidates, int target, int pos) {
if (target < 0) return;
if (target == 0) {
res.add(new ArrayList<>(list));
return;
}
for (int i = pos; i < candidates.length; i++) {
if (candidates[i] > target) break;
if (i > pos && candidates[i] == candidates[i - 1]) continue;
list.add(candidates[i]);
findCombinations(res, list, candidates, target - candidates[i], i + 1);
list.remove(list.size() - 1);
}
}
}

Reference:

https://leetcode.com/submissions/detail/51501884/

40. Combination Sum II的更多相关文章

  1. [Leetcode][Python]40: Combination Sum II

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 40: Combination Sum IIhttps://oj.leetco ...

  2. [array] leetcode - 40. Combination Sum II - Medium

    leetcode - 40. Combination Sum II - Medium descrition Given a collection of candidate numbers (C) an ...

  3. leetcode 39. Combination Sum 、40. Combination Sum II 、216. Combination Sum III

    39. Combination Sum 依旧与subsets问题相似,每次选择这个数是否参加到求和中 因为是可以重复的,所以每次递归还是在i上,如果不能重复,就可以变成i+1 class Soluti ...

  4. 【LeetCode】40. Combination Sum II (2 solutions)

    Combination Sum II Given a collection of candidate numbers (C) and a target number (T), find all uni ...

  5. [LeetCode] 40. Combination Sum II 组合之和之二

    Given a collection of candidate numbers (candidates) and a target number (target), find all unique c ...

  6. 【LeetCode题意分析&解答】40. Combination Sum II

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

  7. LeetCode OJ 40. Combination Sum II

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

  8. 【一天一道LeetCode】#40. Combination Sum II

    一天一道LeetCode系列 (一)题目 Given a collection of candidate numbers (C) and a target number (T), find all u ...

  9. [leetcode]40. Combination Sum II组合之和之二

    Given a collection of candidate numbers (candidates) and a target number (target), find all unique c ...

  10. 39. Combination Sum + 40. Combination Sum II + 216. Combination Sum III + 377. Combination Sum IV

    ▶ 给定一个数组 和一个目标值.从该数组中选出若干项(项数不定),使他们的和等于目标值. ▶ 36. 数组元素无重复 ● 代码,初版,19 ms .从底向上的动态规划,但是转移方程比较智障(将待求数分 ...

随机推荐

  1. Selenium 入门

    我本身也是一个初学者,就顺手记录一下自己的成长记录,共勉 1, 登录selenium官方网站,download 相关的插件. http://docs.seleniumhq.org/ 我用的是eclip ...

  2. android studio安装插件

    1.File-Settings菜单

  3. 通过替换frm文件方式修改表结构

    版本:5.6.16 在自己的虚拟环境中,测试创建一个表,表结构如下:mysql> drop table yoon_temp;Query OK, 0 rows affected (0.09 sec ...

  4. Linux命令练级初级

    Linux命令练级初级 http://ke.qq.com/video/index.html?course_id=6815 ls    -a 所有文件    -l    类型,连接数,所属用户,工作组, ...

  5. Web开发从零单排之二:在自制电子请帖中添加留言板功能,SAE+PHP+MySql

    在上一篇博客中介绍怎样在SAE平台搭建一个html5的电子请帖网站,收到很多反馈,也有很多人送上婚礼的祝福,十分感谢! web开发从零学起,记录自己学习过程,各种前端大神们可以绕道不要围观啦 大婚将至 ...

  6. NodeJS从零开始——NPM的使用

    NPM是一个Node包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准.有了NPM,可以很快的找到特定服务要使用的包,进行下载.安装以及管理已经安装的包. NPM常用的命令有: (1)$ ...

  7. linux作业六——进程的描述和进程的创建

    进程的描述和进程的创建 一.进程描述符task_struct 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. 代码关键点: 1.Struct list_hea ...

  8. (转)使用 /proc 文件系统来访问 Linux 内核的内容

    转载网址:http://www.ibm.com/developerworks/cn/linux/l-proc.html 这个虚拟文件系统在内核空间和用户空间之间打开了一个通信窗口/proc 文件系统是 ...

  9. 利用JavaScript获取页面文档内容

    JavaScript的document对象包含了页面的实际内容,所以利用document对象可以获取页面内容,例如页面标题.各个表单值. <!DOCTYPE html> <html ...

  10. segment fault

    http://blog.chinaunix.net/uid-23069658-id-3959636.html