当前位置:   article > 正文

Day27|Leetcode 39. 组合总和 Leetcode 40. 组合总和 II Leetcode131. 分割回文串

组合总和 leetcode

Leetcode 39. 组合总和

题目链接 39 组合总和

本题目和前面的组合问题差不多,只不过这里能重复选取数字,还是要注意组合的定义,交换数字顺序还是算一个组合,所以这里还是用我们的startIndex来记录取的数字到哪里了,下面上代码:

  1. class Solution {
  2. private:
  3. vector<int> path;
  4. vector<vector<int>> result;
  5. void backtracking(vector<int>& candidates, int target,int sum,int startIndex){
  6. if(sum>target){
  7. return ;
  8. }
  9. if(sum==target){
  10. result.push_back(path);
  11. return ;
  12. }
  13. for(int i=startIndex;i<candidates.size()&&sum+candidates[i]<=target;i++){
  14. //其实如果已经知道下一层的sum会大于target,就没有必要进入下一层递归了。
  15. //对总集合排序之后,如果下一层的sum(就是本层的 sum + candidates[i])已经大于target,就可以结束本轮for循环的遍历。
  16. path.push_back(candidates[i]);
  17. sum+=candidates[i];
  18. backtracking(candidates, target,sum,i);// 不用i+1了,表示可以重复读取当前的数
  19. sum-=candidates[i];
  20. path.pop_back();
  21. }
  22. }
  23. public:
  24. vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
  25. sort(candidates.begin(), candidates.end());//从小到大排序
  26. backtracking(candidates, target,0,0);
  27. return result;
  28. }
  29. };

Leetcode 40. 组合总和 II

题目链接 40 组合总和 II

本题目的要求是每个集合的元素只能出现一次,所以说我们需要去重,如何去重才是本题目的关键,其他的地方和上面的题目一样,我们将回溯函数转化为树状图,其实可以分为两个去重,一个是树枝去重,一个是树层去重,下面用一个图片来体现如何去重:

(默认sort排序)在树枝上的去重我们已经完成,我们再看在树层上,取第二个1的时候下面的情况1,2,已经在取第一个1时下面的情况中涉及到了,因为,第一个1后面既有重复的第二个1,也有第二个1后面的元素,所以第一种1一定会包含第二种1的情况。去重我们就完成了,下面直接上代码:

  1. class Solution {
  2. private:
  3. vector<int> path;
  4. vector<vector<int>> result;
  5. void backtracking (vector<int>& candidates,int target,int sum,int startIndex,vector<bool>& used){
  6. if(sum==target){
  7. result.push_back(path);
  8. return ;
  9. }
  10. for(int i=startIndex;i<candidates.size()&&sum+candidates[i]<=target;i++){
  11. // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
  12. // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
  13. // 要对同一树层使用过的元素进行跳过
  14. if(i>0&&candidates[i]==candidates[i-1]&&used[i-1]==false){
  15. continue;
  16. }
  17. path.push_back(candidates[i]);
  18. used[i] = true;
  19. sum+=candidates[i];
  20. backtracking(candidates,target,sum,i+1,used);
  21. sum-=candidates[i];
  22. used[i] = false;
  23. path.pop_back();
  24. }
  25. }
  26. public:
  27. vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
  28. vector<bool> used(candidates.size(),false);初始化
  29. sort(candidates.begin(),candidates.end());
  30. backtracking(candidates,target,0,0,used);
  31. return result;
  32. }
  33. };

Leetcode131. 分割回文串

题目链接 131 分割回文串

上面的题目都是组合类的,从这个题目开始就进入分割类题目了,其实组合和分割是一个意思,同样能用树状结构来解决。

除此之外还有几个需要注意的点,第一个就是将子字符串传递给path,用到了substr (s.substr(pos, len),pos默认值为0,len的默认值是s.size() - pos)转化字符串,第二个就是回文字符串的判断,最后就是回溯函数的模板了,上代码:

  1. class Solution {
  2. private:
  3. vector<string> path;
  4. vector<vector<string>> result;
  5. void backtracking (const string& s,int startIndex){
  6. if(startIndex>=s.size()){
  7. result.push_back(path);
  8. return ;
  9. }
  10. for(int i=startIndex;i<s.size();i++){
  11. if(isPalindrome(s,startIndex,i)){
  12. string str = s.substr(startIndex,i-startIndex+1);//转化子字符串
  13. path.push_back(str);
  14. }else{
  15. continue;
  16. }
  17. backtracking(s,i+1);//递归
  18. path.pop_back();//回溯
  19. }
  20. }
  21. bool isPalindrome(const string & s,int start,int end){
  22. for(int i=start,j=end;i<j;i++,j--){
  23. if(s[i]!=s[j]){
  24. return false;
  25. }
  26. }
  27. return true;
  28. }
  29. public:
  30. vector<vector<string>> partition(string s) {
  31. backtracking(s,0);
  32. return result;
  33. }
  34. };

end,状态不佳啊

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号