力扣刷题||39. 组合总和、40.组合总和II、131.分割回文串

39. 组合总和 - 力扣(LeetCode)

思路:

本题难就难在,如何避免第二次使用到我们重复的数组。基本思路

1、依次遍历传入进来的数组,从第一个值开始遍历

2、用一个全局变量sum来统计和,若等于目标值,说明已经找到合适的数组,并将其加入到result结果数组中

3、在回溯的过程中,为了避免出现重复出现的元素,其起始位置应改为当前遍历位置也就是i值,这样才能避免又反过去重新来一遍。

最后依次往复。

class Solution {
private:
    vector<vector<int>>result;
    void backtracking(vector<int>&condidates,int target,vector<int>&pathvary,int &sum,int startIndex)
    {
        if (sum == target)
        {
            result.push_back(pathvary);
            return;
        }
        if (sum > target)return;
        //其中有一个终止条件的判断
        for (int i = startIndex; i < condidates.size(); i++)//必须得控制一个大小,这样才能方便其完成一定的值,才能不是无限往下循环。//此代码会出现一种情况,排序顺序的出现,要避免这种情况
        {
            pathvary.push_back(condidates[i]);
            sum += condidates[i];
            if (sum <= target) {
                backtracking(condidates, target, pathvary, sum,i);//这里需要对自己的I进行一个进入,这样才能避免出现重复的操作
            }
            pathvary.pop_back();
            sum -= condidates[i];
        }

    }
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) 
    {
        int sum = 0;
        vector<int>pathvary;
        backtracking(candidates, target, pathvary, sum,0);
        return result;
    }
};

40. 组合总和 II - 力扣(LeetCode)

思路:

一开始认为本题跟39差不多,自己先对数组进行了排序,然后再去除重复元素,但发现会删除掉一些符合条件的元素,才发现出问题了,也就是不知道如何动态的去重。后面看卡哥的才发现应该如何去重。

树形重复和树层重复,这里是不能采用树层重复的。

1、为每一个candidates数组都设置一个标签位,若此数正在使用,将标签置为true,若未使用置为false。

2、在这里我们应该知道如何去重,对candidates拍完序之后,倘若遇到前后两数都相同,并且需要判断标签位数组的[i-1]是否为false,如果为false,那么我们将直接跳过此数,因为在之前,我们就基于此数进行了组合,

3、若我们在用此数,相当于又进行了一次组合,也就是前者数的组合是包含后者数的组合。

4、每个数只能使用一次,所以我们startIndex=i+1.

class Solution {
private:
    vector<vector<int>>result;
    void backtracking(vector<int>& condidates, int target, vector<int>& pathvary, int& sum, int startIndex,vector<bool>&used)
    {
        if (sum == target)
        {
            result.push_back(pathvary);
            return;
        }
        if (sum > target)return;//有了这一段,就可以返回了
        //其中有一个终止条件的判断
        for (int i = startIndex; i < condidates.size(); i++)//必须得控制一个大小,这样才能方便其完成一定的值,才能不是无限往下循环。//此代码会出现一种情况,排序顺序的出现,要避免这种情况
        {
            if (i > 0 && condidates[i - 1] == condidates[i] && used[i - 1] == false) continue;
            sum += condidates[i];
            pathvary.push_back(condidates[i]);
            used[i] = true;
            if(sum<=target)
            {
            backtracking(condidates, target, pathvary, sum, i +1,used);//这里需要对自己的I进行一个进入,这样才能避免出现重复的操作
            }
            used[i] = false;
            pathvary.pop_back();
            sum -= condidates[i];
        }

    }
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
    {
        vector<bool>used(candidates.size(), false);
        int sum = 0;
        vector<int>pathvary;
        sort(candidates.begin(), candidates.end());
        backtracking(candidates, target, pathvary, sum, 0,used);
        return result;
    }
};

131. 分割回文串 - 力扣(LeetCode)

不知道大家有没有这种想法,自己想怎么也想不出来,一看卡哥的视频一下子就能写出来,就是一下子就能理解题目的做法。这可能就是眼高手低。

本题难点,如何切割,一步一步切割问题是一个难点,

采用的

substr(startIndex,i-startIndex+1)

这句语句的意思是,从传入的startIndex开始,随着I每加一,我就取一段出来,然后放入判断是否否回文子串的函数 isPalindrome(const string& s, int start, int end)中

 bool isPalindrome(const string& s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            if (s[i] != s[j]) {
                return false;
            }
        }
        return true;
    }

若满足,那么我就对path进行添加。不满足就跳过。

回溯的终止条件为:开始位置大于等于字符串的长度,说明我已经全部遍历完

因为我每一次的这个判断都是对我上一层的一个判断。

其次这是对一个字符串,从左到右,分别取一个,再取两个,依次叠加,直到全部取完。

class Solution {
private:
    vector<vector<string>>result;
    vector<string>path;
    void backtracking(const string& s, int startIndex)
    {
        //如果当前传入的起始位置比s的长度还长,或者相等,说明已经检索完毕,已经找到合适的分割方案
        if (startIndex >= s.size())
        {
            result.push_back(path);
            return;
        }
        for (int i = startIndex; i < s.size(); i++)
        {
            if (isPalindrome(s, startIndex, i))
            {
                string str = s.substr(startIndex, i - startIndex + 1);
                path.push_back(str);
            }
            else {
                continue;//不满足就继续,跳过
            }
            backtracking(s, i + 1);
            path.pop_back();
        }

    }

    bool isPalindrome(const string& s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            if (s[i] != s[j]) {
                return false;
            }
        }
        return true;
    }
public:
    vector<vector<string>> partition(string s) {
        result.clear();
        path.clear();
        backtracking(s, 0);
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值