039 Combination Sum[M]

1 题目描述

Given a set of candidate numbers (C) (without duplicates) 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.
  • The solution set must not contain duplicate combinations.

难度:Medium

2 题目样例

For example, given candidate set [2, 3, 6, 7] and target 7, 
A solution set is: 
[
  [7],
  [2, 2, 3]
]

3 题意分析

有一个正整数集合C和一个正整数目标T。现从C中选出一些数,使其累加和恰好等于T(C中的每个数都可以取若干次),求所有不同的取数方案。

注意正整数集合中可能存在重复的数字,而这些数字用于组合的时候,会产生重复的排列。题目要求相同的排列只出现一次。

4 思路分析

这个问题我以前是见过的…NYOJ上出现过题设和本题极其相似的部分和问题。用深度优先搜索可以解决。

(PS:这题和上学期算法课上反复操练的整数划分问题也有些相似,可以尝试DP解法。)

1.DFS解法:

先排序,再利用unique进行去重,最后DFS搜索最后结果即可。

代码实现如下

class Solution 

{
    
public:
    
    vector<int> temp;
    
    vector<vector<int> > result;
    
    void DFS(vector<int> &candidates, vector<int> &temp, size_t index, int target)
        
    {
        if (target == 0)
            
        {
            result.push_back(temp);
            
            return;
        }

        else
            
        {
            for (size_t i = index; i < candidates.size(); i++)
                
            {
                if (candidates[i] > target)
                    
                    return;

                temp.push_back(candidates[i]);
                
                DFS(candidates, temp, i, target - candidates[i]);
                
                temp.pop_back();
            }
        }
    }
    
    vector<vector<int>> combinationSum(vector<int>& candidates, int target)
    
    {
        sort(candidates.begin(), candidates.end());
        
        candidates.erase(unique(candidates.begin(),candidates.end()),candidates.end());
        
        DFS(candidates, temp, 0, target);
        
        return result;
    }
};

2.DP解法:

思想类似于经典的子集和问题。

代码实现如下(直接使用讨论区里的代码)

class Solution 
{  
public:
        vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> result;
        int size = candidates.size();
        if (size == 0) return result;
        sort(candidates.begin(), candidates.end());
        vector<vector<vector<int>>> dp(target + 1, vector<vector<int>>());
        dp[0].push_back(vector<int>());

        for (int i = 1; i <= target; ++i) {
            for (int j = 0; j < size && candidates[j] <= i; ++j) {
                for (int k = 0; k < dp[i - candidates[j]].size(); ++k) {
                    vector<int> temp = dp[i - candidates[j]][k];
                    if (temp.size() && (temp[temp.size() - 1] > candidates[j])) continue;
                    temp.push_back(candidates[j]);
                    dp[i].push_back(temp);
                }
            }
        }
        return dp[target];
    }
};

5 后记

不知道为什么,本题目DP解法反而要比深搜解法慢上许多……

    原文作者:Lolita
    原文地址: https://zhuanlan.zhihu.com/p/34253687
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞