代码随想录第二十七天|39. 组合总和、40.组合总和II、131.分割回文串

39. 组合总和

思路:

变量:

全局变量:

vector<vector<int>> result; vector<int>path;int sum=0;

函数变量:

vector<int>&candidates,int target, int startIndex

终止条件:

sum==target时将path放进result;

单层逻辑:

for(int i=startIndex;i<candidates.size();i++)

sum+=;path.push();backtracking(candidates,target,i);path.pop();sum-=;

注意:本题可以重复选取元素,因此单层内的嵌套回溯i不需要i+1;

剪枝:

if(sum>target) return;

看视频后:

和视频思路相同。



40.组合总和II

思路:

按照上一题进星类似思路,可以取相同值,因此单层搜索中i;但是由于有重复元素,不知道如何进行去重

看视频后:

组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过。我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重树层去重的话,需要对数组排序!


因此涉及去重的操作为

1. sort排序数组

2.增加一个bool的数组记录取元素的情况,并用以下判断

 if(i>0&&candidates[i]==candidates[i-1]&&used[i-1]==false){continue;}

剪枝:sum>target


131.分割回文串

思路:

无。

看视频后:

1. 写一个判断回文子串的函数

2. backtracking

变量:

全局:result,path

函数变量:string s,int starti;

终止条件:

if(starti==s.size()) //starti为切割的线

单层循环:

for(int i=starti;i<s.size();i++)

        {

            if(rv(s,starti,i))//判断是否为回文子串

            {

                string str=s.substr(starti,i-starti+1);//记录子串,范围是starti-i,切割范围

                path.push_back(str);

            }

            else 

                continue;//不是子串就跳过


            backtracking(s,i+1);

            path.pop_back();

        }

切割其实是一种组合问题,重要的是切割线和切割范围。注意切割过的位置,不能重复切割,所以,backtracking(s, i + 1); 传入下一层的起始位置为i + 1

本题难点:

切割问题可以抽象为组合问题

如何模拟那些切割线

切割问题中递归如何终止

在递归循环中如何截取子串

如何判断回文

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容