week31

好家伙上来就这么硬核的吗...

301 - 删除无效的括号

记得复习一下leetcode 32.最长有效括号

有效括号序列要满足的要求:

  • 左右括号数量相同

  • 任意一个前缀中,左括号数量 >= 右括号数量

第一步:统计要删掉多少左括号和右括号

l 表示还剩多少未匹配的左括号 r表示多少非法的右括号

那么l ++代表当前未匹配的左括号,如果遇到右括号并且当前未匹配的左括号个数大于0,那么l --,说明当前右括号前面有与之匹配的左括号,如果未匹配的左括号个数等于0,说明当前这个括号是不合法的,r ++

最后l代表还没有匹配的左括号个数,r表示非法的右括号个数,都是我们需要删除的个数。

第二步:DFS搜索+剪枝

这里的剪枝策略有两部分:

  • 预处理删除的括号数

  • 重复去重 ((( 对于这种连续的括号序列删除那个都是一样的 所以这里枚举的是删除的个数

函数签名void dfs(string& s, int u, string path, int cnt, int l, int r)

这里面cnt和上面的l含义一致,还有多少未匹配的左括号, l r都是还需要删除的括号数量

class Solution {
public:
    vector<string> res;
public:
    vector<string> removeInvalidParentheses(string s) {
        int l = 0, r = 0;
        // 第一步:统计待删除的字符数量
        for(auto x : s)
        {
            if(x == '(') l++;
            else if (x == ')')
            {
                if(l == 0) r++;
                else l--;
            }
        }
        dfs(s, 0, "", 0, l, r);
        return res;
    }
    void dfs(string& s, int u, string path, int cnt, int l, int r)
    {
        if(u == s.size())
        {
            if(!cnt) res.push_back(path); // 合法条件:左右括号数量一致
            return;
        }
        if(s[u] != '(' && s[u] != ')') dfs(s, u + 1, path + s[u], cnt, l, r);
        else if (s[u] == '(')
        {
            int k = u;
            while(k < s.size() && s[k] == '(') k++;
            // 按照数量枚举,先把所有的都删了
            l -= k - u;
            for(int i = k - u; i >= 0; i--)
            {
                if(l >= 0) dfs(s, k, path, cnt, l, r);
                path += '(';
                cnt++, l++; // 
            }
        }
        else if (s[u] == ')')
        {
            int k = u;
            while(k < s.size() && s[k] == ')') k++;
            r -= k - u;
            for(int i = k - u; i >= 0; i--)
            {
                if(cnt >= 0 && r >= 0) dfs(s, k, path, cnt, l, r); // 注意这里的 cnt >= 0
                path += ')';
                cnt--, r++;
            }
        }
    }
};

303 - 区域和检索 - 数组不可变

这题简单 一维前缀和罢了

304 - 二维区域和检索 - 数组不可变

这题就是上一题的推广 二维前缀和

注意的点一个是下标要从0映射到1 另一个是是闭区间 所以row1col1都要减去1

306 - 累加数

判断一个字符串是不是斐波那契数列 但是没有分隔符

用高精度的方式来存每个数

枚举第一个数的长度和第二个数的长度,然后递归判断是不是斐波那契数列, 所以三个数分别是 [a + 1, b][b + 1, c][c + 1, c + z.size()], 不断往后指就可以了

时间复杂度:o(n^3) 枚举+判断

不能枚举有前导0的数

307 - 区域和检索 - 数组可修改

能用树状数组就用树状数组,不行再用线段树;

树状数组:代码更短 空间更少 时间更快

所以本题就是树状数组的应用

309 - 最佳买卖股票时机含冷冻期

经典的买卖股票问题了-> 状态机模型

这里含冷冻期的状态共有三个:

  • 在冷冻期

  • 已买入

  • 今天卖出

avatar 有没有冷冻期的区别无非是把之前只有一个的卖出状态 拆成了今天卖出(手里有股票且不能买 和 在冷冻期(手里有股票且可以买 两个状态

同样的 只需要前一个状态 那个空间可以优化成o(1) 注意缓存历史状态就行了

310 - 最小高度树

记录最大距离最小的点

avatar

剩下的细节大概就是要建双向边,dfs的时候额外记录father就行了

Last updated