20230712-CodeTop

36 阅读2分钟

leetcode-494 目标和

可以看作所有数字默认为正的情况下,有多少个子集满足差集的和减去这个子集的和等于目标值。即寻找应该为负数的组合数。所有数字不能重复用——01背包。因此,01背包——容量从大到小遍历,而组合数——外层物品内层容量,确定了遍历顺序。剩下的就是状态转移,典型的背包求组合、排列数的状态转移,base case容量为0的子集数量为1(空集也算,不然后面都是0了)。背包问题不特意上难度的话就是比较公式化。

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0, n = nums.size();
        for(int i = 0; i < n; ++i) sum += nums[i];
        int negative = sum - target;
        if(negative < 0 || negative % 2 != 0) return 0;
        int target_neg = negative / 2;
        vector<int> dp(target_neg + 1);
        dp[0] = 1;
        for(int i = 0; i < n; ++i){
            for(int j = target_neg; j >= nums[i]; --j){
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[target_neg];
    }
};

leetcode-32 最长有效括号

核心思想是设dp[i]为以s[i]结尾的子串如果有效,最长长度是多少,有效的子串必然以')'结尾,且每个有效的括号所对应的另一个括号的位置是唯一的,不存在多种解。

考虑上一个位置s[i - 1]的两种情况。如果s[i - 1] == '(',那么必然是s[i - 1]和s[i]为一对有小括号,即.........(),此时dp[i] = dp[i - 2] + 2。

如果s[i - 1] == ')',那么情况必然是....(....(...)),即s[i - 1]位置的')'已经有了自己的有效括号串,且是以s[i]结尾的有效括号串的子串,s[i]对应的'('必然在s[i - 1]对应的'('之前。逻辑推理:(....(...))是有效的,其中以s[i]结尾的子串是有效的,那么(....(...))必然也是有效的,那么....(...)也就等于是(.......),那么得出结论:s[i]对应的'('只有在以s[i]结尾的子串的上一个位置,整个子串才是有效的。那么dp[i]就等于dp[i - 1]对应的内部有效子串长度+2个括号长度+再前面也就是dp[i - dp[i - 1] - 2]位置的有效长度,dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2]

注意dp的定义,是以s[i]结尾的子串如果有效,最长长度是多少。如果当前位置无效,不可以让dp[i] = dp[i - 1],而是必须为0。

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.size();
        if(n <= 1) return 0;
        vector<int> dp(n);
        int ans = 0;
        for(int i = 1; i < n; ++i){
            if(s[i - 1] == '(' && s[i] == ')'){
                if(i >= 2) dp[i] = dp[i - 2] + 2;
                else dp[i] = 2;
                ans = max(ans, dp[i]);
                continue;
            }
            else if(s[i - 1] == ')' && s[i] == ')' && i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '('){
                if(i - dp[i - 1] - 2 >= 0) dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2];
                else dp[i] = dp[i - 1] + 2;
                ans = max(ans, dp[i]);
                continue;
            }
            // else{
            //     dp[i] = dp[i - 1];
            // }
        }
        return ans;
    }
};