组合总和(回溯)

10 篇文章 0 订阅

在这里插入图片描述
思路:回溯法+剪枝法(相当不错的题目,递归三部曲)
1.递归什么时候结束:当target为0时,递归结束;

2.每个递归的返回值是什么:每个递归结束后表示已经完成了后续的剪枝操作;

3.每级递归中要做的事:遍历选取当前要剪的那个枝,即把当前的所有的数字(枝)依次过一遍(依次压入、弹出)。

如输入: candidates = [2, 3, 5, 7],target = 7,所求解集为: [[2, 2, 3],[2,5], [7]]
为了防止出现结果重复的情况(如[2,5]和[5,2]其实是同一个结果),对原始数组先进行升序排序,这样就能保证当前剪枝的值>=上一次剪枝的值。
每次剪枝都会产生多个新的子递归
在这里插入图片描述
第一次写的代码如下,发现可以继续优化:

class Solution {
public:
	vector<vector<int>> combinationSum(vector<int> &candidates, int target) {
		sort(candidates.begin(), candidates.end());//从小到大排序
		combinationSumCore(candidates, 0, target);
		return res;
	}
private:
	vector<vector<int>> res;
	vector<int> path;
	void combinationSumCore(vector<int> &candidates, int start, int target) {
		if (target == 0)
		{
			res.push_back(path);
			return; //子递归结束
		}

		for (int i = start; i < candidates.size(); i++)//核心
		{
			path.push_back(candidates[i]);
			if(target - candidates[i] >= 0)
			combinationSumCore(candidates, i, target - candidates[i]);
			path.pop_back();//上一句总是会出来的
		}

	}
};

优化后的代码如下:


#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
//DFS
class Solution {
public:
	vector<vector<int>> combinationSum(vector<int> &candidates, int target) {
		sort(candidates.begin(), candidates.end());//从小到大排序
		combinationSumCore(candidates, 0, target);
		return res;
	}
private:
	vector<vector<int>> res;
	vector<int> path;
	void combinationSumCore(vector<int> &candidates, int start, int target) {
		if (target == 0)//递归结束的条件
		{
			res.push_back(path);
			return; 
		}

		for (int i = start; i < candidates.size() && target - candidates[i] >= 0; i++)
		{
			path.push_back(candidates[i]);
			combinationSumCore(candidates, i, target - candidates[i]);//已经完成了后续的剪枝操作
			path.pop_back();
		}

		
	}
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值