leecode 解题总结:40 Combination Sum II

#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <algorithm>


using namespace std;
/*
问题:
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.
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]
]
分析:
此题在递归求解的过程中必须确保每个数字出现的次数不能超过实际出现的次数
只需要修改for循环中i * candidate <= target中的条件为 i <= numToTimes[i] && i * candidate <= target


输入:
7(数组元素个数) 8(目标值)
10 1 2 7 6 1 5
输出:
1 7,1 2 5,2 6,1 1 6


关键:
1 用回溯来做,如果目标值为0,就将结果压入结果集。回溯适用于求解含有多个结果的集合
回溯基本格式:
尝试某一数值
递归
清空尝试的数值
与可重复累加和的区别在于:
可重复累加和一直尝试当前值,直到目标值 < 当前候选值,则选取下一个候选值。
  如果目标值>0,继续尝试下一个值,尝试过后,弹出之前压入的值
	//如果目标变成0,说明得到结果,将结果加入结果集
	if(0 == target)
	{
		results.push_back(path);
		return;
	}
		
	//此种情况不可能
	if(target < 0)
	{
		return;
	}
	int size = candidates.size();
	for(int i = cur ; i < size ; i++)
	{
		//防止添加重复元素,如果当前元素和之前元素重复,就跳过
		if(i > cur && candidates.at(i) == candidates.at(i-1))
		{
			continue;
		}
		path.push_back(candidates.at(i));
		//尝试下一个候选值
		combineSum(candidates , target - candidates.at(i) , i + 1 , path , results);
		//回溯
		path.pop_back();
	}


2 求组合值为sum的解法
 void combinationSum(std::vector<int> &candidates, int target, std::vector<std::vector<int> > &res, std::vector<int> &combination, int begin) {
		if  (!target) {
			res.push_back(combination);
			return;
		}
        for (int i = begin; i != candidates.size() && target >= candidates[i]; ++i) {
            combination.push_back(candidates[i]);
            combinationSum(candidates, target - candidates[i], res, combination, i);
            combination.pop_back();
        }
	}
*/


class Solution {
public:


	//尝试用摆放来做,问题转化为递归问题
	void combineSum(vector<int>& candidates, int target , int cur , vector<int> path , vector< vector<int> >& results)
	{
		vector< vector<int> > totalResults;
		if(candidates.empty())
		{
			return ;
		}
		//如果目标变成0,说明得到结果,将结果加入结果集
		if(0 == target)
		{
			results.push_back(path);
			return;
		}
		
		//此种情况不可能
		if(target < 0)
		{
			return;
		}
		int size = candidates.size();
		for(int i = cur ; i < size ; i++)
		{
			//防止添加重复元素,如果当前元素和之前元素重复,就跳过
			if(i > cur && candidates.at(i) == candidates.at(i-1))
			{
				continue;
			}
			path.push_back(candidates.at(i));
			//尝试下一个候选值
			combineSum(candidates , target - candidates.at(i) , i + 1 , path , results);
			//回溯
			path.pop_back();
		}
	}


    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
		vector<vector<int>> results;
		if(candidates.empty())
		{
			return results;
		}
        //必须确保候选值从大到小排序
		sort(candidates.begin() , candidates.end());
		vector<int> path;
		combineSum(candidates, target , 0 , path , results);
		return results;
    }
};


void print(vector<vector<int>>& results)
{
	if(results.empty())
	{
		cout << "no result" << endl;
		return;
	}
	int size = results.size();
	for(int i = 0 ; i < size ; i++)
	{
		int len = results.at(i).size();
		for(int j = 0 ; j < len ; j++)
		{
			cout << results.at(i).at(j) << " ";
		}
		cout << ",";
	}
	cout << endl;
}


void process()
{
	int num;
	vector<int> nums;
	int target;
	int value;
	Solution solution;
	vector< vector<int> > results;
	while(cin >> num >> target)
	{
		nums.clear();
		for(int i = 0 ; i < num ; i++)
		{
			cin >> value;
			nums.push_back(value);
		}
		results = solution.combinationSum2(nums , target);
		print(results);
	}
}


int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值