算法训练day29 LeetCode 39.40.131

发布时间 2023-10-08 23:10:04作者: 烫烫烫汤圆

算法训练day29 LeetCode 39.40.131

39.组合总和

题目

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

题解

代码随想录 (programmercarl.com)

  • class Solution
    {
    private:
        vector<vector<int>> result;
        vector<int> path;
        void backtracking(vector<int> &candidates, int target, int sum, int startIndex)
        {
            if (sum > target)
                return;
            if (sum == target)
            {
                result.push_back(path);
            }
            for (int i = startIndex; i < candidates.size(); i++)
            {
                sum += candidates[i];
                path.push_back(candidates[i]);
                backtracking(candidates, target, sum, i);
                sum -= candidates[i];
                path.pop_back();
            }
        }
    
    public:
        vector<vector<int>> combinationSum(vector<int> &candidates, int target)
        {
            result.clear();
            path.clear();
            backtracking(candidates, target, 0, 0);
            return result;
        }
    };
    
  • 在sum>target时,依然会进入下一层循环,所以可以添加一个剪枝

  •     void backtracking(vector<int> &candidates, int target, int sum, int startIndex)
        {
           // if (sum > target)
           //     return;
            if (sum == target)
            {
                result.push_back(path);
                return;
            }
            for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) //剪枝
            {
                sum += candidates[i];
                path.push_back(candidates[i]);
                backtracking(candidates, target, sum, i);
                sum -= candidates[i];
                path.pop_back();
            }
        }
    

40.组合总和II

题目

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

题解

代码随想录 (programmercarl.com)

  • candidates 中元素重复、单个结果中元素可以重复、总结果集中不能有结果重复

  • 需要去重 ---> 将组合的形式以树形结构组织

    • 单个结果元素可重复 ---> 单次组合(单枝)中不需要去重
    • 多个结果之间不能重复 ---> 不同次组合(同一层)中需要去重 ---> 将元素排序之后组合实现去重
  • class Solution
    {
    private:
        vector<vector<int>> result;
        vector<int> path;
        void backtracking(vector<int> &candidates, int target, int sum, int startIndex, vector<bool> used)
        {
            if (sum == target)
            {
                result.push_back(path);
                return;
            }
            for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++)
            {
                if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) //同层去重
                    continue;
                sum += candidates[i];
                path.push_back(candidates[i]);
                used[i] = true;
                backtracking(candidates, target, sum, i + 1, used);
                used[i] = false;
                sum -= candidates[i];
                path.pop_back();
            }
        }
    
    public:
        vector<vector<int>> combinationSum2(vector<int> &candidates, int target)
        {
            vector<bool> used(candidates.size(), false);
            result.clear();
            path.clear();
            sort(candidates.begin(), candidates.end());
            backtracking(candidates, target, 0, 0, used);
            return result;
        }
    };
    

131.分割回文串

题目

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

题解

代码随想录 (programmercarl.com)

  • 递归用来纵向遍历,for循环用来横向遍历,切割线(就是图中的红线)切割到字符串的结尾位置,说明找到了一个切割方法。

  • class Solution
    {
    private:
        vector<vector<string>> result;
        vector<string> path;
        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;
        }
        void backtracking(const string &s, int startIndex)
        {
            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();
            }
        }
    
    public:
        vector<vector<string>> partition(string s)
        {
            result.clear();
            path.clear();
            backtracking(s, 0);
            return result;
        }
    };