代码随想录算法训练营41期 回溯算法02

39. 组合总和

简单,略

40.组合总和II

要点是如何避免重复的组合出现?类似的思路其实在练习双指针的时候已经使用过。将递归的过程看作一棵树的生长过程的话,避免重复就是避免相同的数字在树的某一层中重复出现。(这里说的一层当然是由同一个父节点延申出来的)。为此只要先将存放可用数字的数组candidates进行排序,然后检查当前准备添加到track中的数字是否与candidates中在它前一位的数字相同,若相同则直接进入下一轮循环。

131.分割回文串

首先要明确怎么找出回文串?(小tip:单独一个字母也是回文串)我的思路是,回文串的两头一定是相等的,所以只需要固定开头,移动尾部,如果发现守卫相等,则首尾同步收缩,直至确认找到了回文串/当前首尾无法构成回文串。 确定了找回文串的策略之后,找回文串的函数签名也就可以确定:参数是给定的字符串以及搜索区间的左右边界,返回值是bool表明当前边界是否可以构成回文串;

搞定了回文串的搜索,再来考虑整体的递归。我采用的是从最大回文串开始搜索的方法。首先把搜索范围定为字符串的开头和结尾,搜索失败则收缩右边界直到搜索到以字符串0下标开头的最长子串,将该子串加入track。随后将搜索范围改为[right+1,end],如此反复直到搜索范围变成[end+1,end],即找到了第一种分割法。至此函数便会一路返回到第一层,继续搜索更短的以string[0]为首的回文串,最后一种被考虑的情况则是回文串仅由一个字母构成

class Solution {
public:
    vector<string> track;
    vector<vector<string>> result;
    vector<vector<string>> partition(string s) {
        backTrack(0,s);
        return result;
    }
    
    void backTrack(int index,string &s){
        if(index==s.size()){
            result.push_back(track);
            return;
        }
        
        for(int right=s.size()-1;right>=index;right--){
            if(isPalindrome(s,index,right)){
                track.push_back(s.substr(index,right-index+1));
                backTrack(right+1,s);
                track.pop_back();
            }
        }
       
        return;
    }
    bool isPalindrome(string &s,int left,int right){
        if(left>right) return false;
        while(left<=right){
            if(s[left]!=s[right]){
                return false;
            }else{
                if(left+1==right || left==right){
                    return true;
                }else{
                    left++;
                    right--;
                }
                
            }
        }
        return false;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值