LeetCode 第27天

39. 组合总和

组合中无重复元素,所有元素可以随便取多少次。那么startIndex就可以从本次遍历处开始。

class Solution {
public:
// 老套路,两个数组前一个存储中间结果,后一个存储总结果集
    vector<int> vec;
    vector<vector<int>> res;
    // 回溯
    void backtracking(vector<int>& candidates, int target, int startIndex){
        if (target == 0){
            res.push_back(vec);
            return;
        }
        // 如果小于0则表示不满足,不需要加入结果集
        else if (target < 0){
            return;
        }
        // 对于n叉树的遍历
        for (int i = startIndex;i<candidates.size();i++){
            target -= candidates[i];
            vec.push_back(candidates[i]);
            // 还是需要传递startIndex,但是下一级递归可以使用这一级的数,因为可重复
            backtracking(candidates, target, i);
            target += candidates[i];
            vec.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        backtracking(candidates, target, 0);
        return res;
    }
};

39. 组合总和

这一次变为组合中有重复元素,但是每一个元素只能使用一次。那么就需要先对组合元素排序,如果相邻元素相同只需要遍历一次,否则可能造成结果集重合。

class Solution {
public:
    vector<int> path;
    vector<vector<int>> res;
    void backtracking(vector<int>& candidates, int target, int startIndex){
        if (target == 0){
            res.push_back(path);
            return;
        }
        if (target < 0){
            return;
        }
        for (int i = startIndex; i<candidates.size();i++){
            // 这里同层的相同元素直接跳过,否则会出现重复
            if (i > startIndex && candidates[i] == candidates[i-1])
                continue;
            target -= candidates[i];
            path.push_back(candidates[i]);
            backtracking(candidates, target, i+1);
            target += candidates[i];
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        // 这个方法需要先排序
        sort(candidates.begin(), candidates.end());
        backtracking(candidates, target,0);
        return res;
    }
};

131. 分割回文串

没想到分割回文串也是组合问题的延续。难点在于分割点的选取,子串获取,回文串判断要单独写出。总之是一道经典难题吧。还需要再练习。

class Solution {
private:
// 不会写,抄的
    vector<string> path;
    vector<vector<string>> res;
    void backtracking(const string& s, int startIndex){
        // 结束条件 startIndex表示切割的起始位置
        if (startIndex >= s.size()){
            res.push_back(path);
            return;
        }
        // 横向切割
        for (int i = startIndex; i < s.size(); i++){
            if (isPalindrome(s, startIndex, i)){
                // substr函数的参数为begin,len,表示[begin, begin+len)的子串
                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) {
        backtracking(s, 0);
        return res;
    }
};

你可能感兴趣的:(leetcode,算法,职场和发展)