Day27_39组合总和_40组合总和Ⅱ_131回文串的切割

39 组合总和

  1. candidates无重复,其中数字可以无限制的重复选取。
  2. 由于可以选取,递归的时候就不是从 i+1 开始,而是从 i 开始的(重复的含义,最大的不同)。
  3. 回溯三部曲:
  • 参数和返回值: candidates提供基础数据,target表示path中的数据中和,startIndex表示当层的开始,提供树的纵向遍历。
  • 结束条件:
if (target == 0) {
	result.push_back(path);
	return;
  • 单层逻辑
for(int i = startIndex; i<candidates.size() && target - candidates[i] >= 0; i++){
	path.push_back(candidates[i]);
	target -= candidates[i];
	backtracking(candidates, target, i);
	path.pop_back();
	target += candidates[i];
}

40 组合总和Ⅱ

  1. candidates是有重复的,最后的组合是无重复的。
  2. 去除重复的元素:
  • 同一层的重复元素;
  • 同一树枝的重复元素;
  1. 根据本题的要求,由于不能解集不能包括重复的集合,所以同一层如果未加入组合的数和已加入组合的数出现重复,需要跳过不处理,否则将导致同一层出现两个相同的元素,最后有相同的组合。
  • 为便于找集合外和集合内的,排序后使用candidates[i] == candadates[i-1]即可,排序用快排的sort(candidates.begin(), candidates.end())实现。
  • candidates[i] == candidates[i-1]只能说明candidates中有重复的元素,不能说明两者是否在同一层,有可能是同一树枝,则这是满足要求的。两种方法说明两个相同元素是不是在同一层:一是vector<bool> used实现,如果used[i-1]=false;说明当前值是前一个的回溯,两个在同一层,continue,如果used[i-1]=true;说明当前值是前一个的同一树枝,继续执行。二是比较startIndex和i的大小,如果 i > startIndex 则说明同一层,continue。
  1. 回溯三部曲:
  • 返回值和参数:参数candidates提供基础数据、target提供path中数据的和、startIndex提供应该从candidates的哪个开始,形成树的纵向遍历。
  • 终止条件:遇到path中的和等于target
if(target == 0){
	result.push_back(path);
	return;
}
  • 单层逻辑
    used数组
for(int i = startIndex; i < candidates.size() && target - candidates[i] >= 0; i++){
	//与39不同的地方,需要处理是否树的当层重复
	if(i > 0 && candidates[i] == candidates[i-1] && used[i-1] == false) continue;
	used[i] = true;//
	path.push_back(candidates[i]);
	target -= candidates[i];
	backtracking(candidates, target, i+1);
	used[i] = false;//回溯
	path.pop_back();
	target += candidates[i];
}

startIndex与i的比较

for(int i = startIndex; i < candidates.size() && target - candidates[i] >= 0; i++){
	//与39不同的地方,需要处理是否树的当层重复
	if(i > 0 && candidates[i] == candidates[i-1] && i > startIndex) continue;
	path.push_back(candidates[i]);
	target -= candidates[i];
	backtracking(candidates, target, i+1);
	path.pop_back();//回溯
	target += candidates[i];
}

131 回文串的切割

切割问题转为组合问题

  1. 切割用切割线表示,树形结构与组合的树形结构的值不同。
  2. 如何收集切割的过程值vecctor<string> path收集。
  3. 如何把判断回文的逻辑放入到单层逻辑, bool isParlindromes(string s, int begin, int end){}。
  4. 如何表示切割的字串,字串的产生是在for(int i = startIndex; i<s.size(); i++){ [startIndex, i]; }。

回溯三部曲:
5. 参数与返回值:字符串s和在s中开始的位置startIndex。
6. 终止条件:切割的切割线到了最后一个字符的后面:aab|。

if (startIndex >= s.size()){
	result.push_back(path);
	return;	
}
  1. 单层逻辑
  • 切割字符串s得到字串。
  • 判读是否是回文串的逻辑。
bool isParlindrome(string s, int begin, int end){
	while(begin <= end) {
		if(s[begin] != s[end]) return false;
	}
	return true;
}
for(int i = startIndex; i< s.size(); i++){//横向遍历
	if(isParlindrome(s, startIndex, i)){//判断是回文串
		string str = s.substr(startIndex, i - startIndex + 1);
		path.push_back(str);
}
	else{ continue; }
	backtracking(s, i+1);//纵向遍历,切割下一个
	path.pop_back();
}
  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值