Combination Sum II

描述

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,…,aka_1, a_2, …, a_ka​1​​,a​2​​,…,a​k​​) must be in non-descending order. (ie, a1>a2>…>aka_1 > a_2 > … > a_ka​1​​>a​2​​>…>a​k​​).
  • 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. [1, 7]
  2. [1, 2, 5]
  3. [2, 6]
  4. [1, 1, 6]

分析

代码

  1. // Combination Sum II
  2. // 时间复杂度O(n!),空间复杂度O(n)
  3. class Solution {
  4. public:
  5. vector<vector<int> > combinationSum2(vector<int> &nums, int target) {
  6. sort(nums.begin(), nums.end()); // 跟第 50 行配合,
  7. // 确保每个元素最多只用一次
  8. vector<vector<int> > result;
  9. vector<int> path;
  10. dfs(nums, path, result, target, 0);
  11. return result;
  12. }
  13. private:
  14. // 使用nums[start, nums.size())之间的元素,能找到的所有可行解
  15. static void dfs(const vector<int> &nums, vector<int> &path,
  16. vector<vector<int> > &result, int gap, int start) {
  17. if (gap == 0) { // 找到一个合法解
  18. result.push_back(path);
  19. return;
  20. }
  21. int previous = -1;
  22. for (size_t i = start; i < nums.size(); i++) {
  23. // 如果上一轮循环已经使用了nums[i],则本次循环就不能再选nums[i],
  24. // 确保nums[i]最多只用一次
  25. if (previous == nums[i]) continue;
  26. if (gap < nums[i]) return; // 剪枝
  27. previous = nums[i];
  28. path.push_back(nums[i]);
  29. dfs(nums, path, result, gap - nums[i], i + 1);
  30. path.pop_back(); // 恢复环境
  31. }
  32. }
  33. };

相关题目

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/cpp/dfs/combination-sum-ii.html