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

文章目录

      • [39 组合总和](https://programmercarl.com/0039.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE)
      • [40 组合总和Ⅱ](https://programmercarl.com/0040.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CII.html#%E6%80%9D%E8%B7%AF)
      • [131 回文串的切割](https://programmercarl.com/0131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.html#%E6%80%9D%E8%B7%AF)

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 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 path收集。
  3. 如何把判断回文的逻辑放入到单层逻辑, bool isParlindromes(string s, int begin, int end){}。
  4. 如何表示切割的字串,字串的产生是在for(int 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();
}

你可能感兴趣的:(算法,数据结构,力扣,leetcode)