leetcode刷题/回溯算法 40. 组合总和 II

40. 组合总和 II

题意:

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

注意:解集不能包含重复的组合。

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
解题思路:
有什么办法做到不重复?两步走,详细见下文
递归终止条件判断路径总和等于目标
单层逻辑遍历从当前坐标开始,逐个开始递归后面的数字
参数原来函数的参数,还需要加上一个start表示开始位置.一个sum来记录路径总和.
剪枝因为先排序,所有如果路径总和加上当前的数大于目标时,那么后面的数就不需要遍历了.因为都会超过.

遇到这种需要不重复的,我们需要的就是在原来递归的基础上做多两步.

  1. 排序数组,让相同的数字相邻
  2. 用一个参数来表示开始位置(start),数字往后递归.避免重复
代码:
class Solution {
private:
    //用来存储结果和去重,去的是两个相同数字在一起时的起点,也可以用flag标记是否遍历过这个数字.
    vector<vector<int>> res;
    vector<int>path;
public:
    
//递归回溯
//candidates,target 是原来的参数
//start表示起始位置
//sum表示路径总和
void backstrack(vector<int>& candidates, const int& target,const int& start,int sum)
{
    //如果路径总和等于目标就说明找到了一种可能
	if (sum == target)
	{
		res.push_back(path);
		return;
	}
	//从当前下标开始,如果路径总和加上当前的数字大于目标总和.那么就不需要再遍历了
	for (int i = start; i < candidates.size() && sum + candidates[start] <= target; i++)
	{
        //如果同一层不是第一个的同时遇到重复的就不需要再压入了,这样就可以出去相同的结果
        if(i>start&&candidates[i]==candidates[i-1])
        {
             continue;
        }
        //添加路径节点
		path.push_back(candidates[i]);
        //计算路径长度
		sum += candidates[i];
        //下一位开始递归
		backstrack(candidates, target, i + 1, sum);
        //回溯
		sum -= candidates[i];
		path.pop_back();
	}
}
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
    //先排序,让相同的数相邻出现
	sort(candidates.begin(),candidates.end());
    //递归
	backstrack(candidates, target, 0, 0);
	//返回结果
	return vector<vector<int>>(res.begin(),res.end());
    }
};
总结:

记住回溯过程如果需要不重复.那么需要再加上两步即可.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公仔面i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值