【2022/05/08-第292场单周赛】复盘

总结

Q4还是要想好再做好点,先dfs超时,然后两次WA没有注意错误用例,多WA了两次,以后在做周赛的时候也要兼顾少WA。

Q1.字符串中最大的 3 位相同数字

模拟。

class Solution {
public:
    string largestGoodInteger(string s) {
        string ret;
        for(int i = 2; i < s.size(); ++i){
            if(s[i] == s[i - 1] && s[i - 1] == s[i - 2]){
                ret = max(ret, s.substr(i - 2, 3));
            }
        }
        return ret;
    }
};

Q2. 统计值等于子树平均值的节点数

递归模板题。

class Solution {
public:
    int ret = 0;
    
    int getSum(TreeNode* root, int &num){ // 返回以root为根结点的子树上所有结点值之和,num是该子树结点数
        if(!root) return 0;
        int ln = 0, rn = 0;
        int ls = getSum(root->left, ln); // 分别得到左右子树结点值之和和结点数
        int rs = getSum(root->right,rn);
        num = ln + rn + 1;
        int sum = ls + rs + root->val;
        if((sum) / num == root->val) ++ret;
        return sum;
    }
    
    int averageOfSubtree(TreeNode* root) {
        int num;
        getSum(root, num);
        return ret;
    }
};

Q3.统计打字方案数

分离子串后,对每个子串用动态规划求结果数,最后相乘。

class Solution {
public:
    int h[10] = {0, 0, 3, 3, 3, 3, 3, 4, 3, 4};
    const int M = 1000000007;
    int helper(string temp){
        int n = temp.size();
        vector<int> f(n + 1, 0); // 用动态规划计算该子串有多少种可能的文字信息
        f[0] = 1;
        for(int i = 1; i <= n; ++i){
            for(int j = 1; j <= h[temp[0] - '0'] && i - j >= 0; ++j){
                f[i] = (f[i] + f[i - j]) % M;
            }
        }
        return f[n];
    }
    
    int countTexts(string s) {
        string temp;
        long long ret = 1;
        for(int i = 0; i < s.size(); ++i){ // 分离字符相同的子串
            if(i == 0 || s[i] == s[i - 1]) temp += s[i];
            else if(s[i] != s[i - 1]){
                ret = (ret * helper(temp)) % M;
                temp.clear();
                temp += s[i];
            }
        }
        ret = (ret * helper(temp)) % M; // 遍历完会剩下一段
        return ret;
    }
};

Q4.检查是否有合法括号字符串路径

一开始暴力dfs超时,然后用bfsWA了几发后过了。

class Solution {
public:
    
    
    bool hasValidPath(vector<vector<char>>& grid) {
        int m = grid.size(), n = grid[0].size();
        if(grid[0][0] == ')' || m + n - 1 & 1 || grid[m - 1][n - 1] == '(') return false;
        vector<vector<int>> inq(m, vector<int> (n, 0));
        vector<vector<unordered_set<int>>> t(m, vector<unordered_set<int>> (n)); // set内的值表示到达该点时,路径上左括号数和右括号数之差,由于到每个点可能有多条路径,所以我们要用set来储存可能的多个值
        t[0][0].insert(1);
        queue<pair<int, int>> q;
        q.push({0, 0});
        inq[0][0] = 1;
        while(!q.empty()){
            auto k = q.front(); q.pop();
            int x = k.first, y = k.second;
            if(x == m - 1 && y == n - 1 && t[x][y].find(0) != t[x][y].end()) return true; // 到达右下点且有恰好左括号数等于右括号数的路径
            if(x + 1 < m){
                if(grid[x + 1][y] == '('){ // 下一结点为左括号,直接添加
                    for(auto i : t[x][y]) t[x + 1][y].insert(i + 1);
                    if(!inq[x + 1][y]){
                        q.push({x + 1, y});
                        inq[x + 1][y] = 1;
                    }
                }
                else{
                    bool flag = false; // 下一结点为右括号,只有当该结点有括号差值大于1的路径时,才可能到达下一结点
                    for(auto i : t[x][y]){
                        if(i >= 1) t[x + 1][y].insert(i - 1);
                        flag = true;
                    }
                    if(flag && !inq[x + 1][y]){
                        q.push({x + 1, y});
                        inq[x + 1][y] = 1;
                    }
                }
            }
            if(y + 1 < n){
                if(grid[x][y + 1] == '('){
                    for(auto i : t[x][y]) t[x][y + 1].insert(i + 1);
                    if(!inq[x][y + 1]){
                        q.push({x, y + 1});
                        inq[x][y + 1] = 1;
                    }
                }
                else{
                    bool flag = false;
                    for(auto i : t[x][y]){
                        if(i >= 1) t[x][y + 1].insert(i - 1);
                        flag = true;
                    }
                    if(flag && !inq[x][y + 1]){
                        q.push({x, y + 1});
                        inq[x][y + 1] = 1;
                    }
                }
            }
        }
        return false;
    }
};

dfs剪枝

class Solution {
public:
    
    int m, n;

    bool dfs(int x, int y, int c, vector<vector<char>>& grid, vector<vector<vector<bool>>> &vis){
         if (c > m - x + n - y - 1) return false; 
            if (x == m - 1 && y == n - 1) return c == 1; 
            if (vis[x][y][c]) return false; 
            vis[x][y][c] = true;
            c += grid[x][y] == '(' ? 1 : -1;
            return c >= 0 && (x < m - 1 && dfs(x + 1, y, c, grid, vis) || y < n - 1 && dfs(x, y + 1, c, grid, vis));
    }

    bool hasValidPath(vector<vector<char>>& grid) {
        m = grid.size(), n = grid[0].size();
        if(grid[0][0] == ')' || !((m + n) & 1) || grid[m - 1][n - 1] == '(') return false;
        vector<vector<vector<bool>>> vis(m, vector<vector<bool>> (n, vector<bool> (m + n, false)));

        return dfs(0, 0, 0, grid, vis);
    }
};

dp+bitset优化

class Solution {

    using B128 = bitset<128>;

public:
    bool hasValidPath(vector<vector<char>>& grid) {
        int m = grid.size(), n = grid[0].size();
        if(grid[0][0] == ')' || grid[m - 1][n - 1] == '(' || !((m + n) & 1)) return false;
        vector<B128> f(n, 0);
        f[0] = 2;
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                if(grid[i][j] == '('){
                    if(i) f[j] <<= 1;
                    if(j) f[j] |= (f[j - 1] << 1); 
                }
                else{
                    if(i) f[j] >>= 1;
                    if(j) f[j] |= (f[j - 1] >> 1); 
                }
            }
        }
        return f[n - 1].test(0);
    }
};
posted on 2022-05-08 20:01  damnglamour  阅读(20)  评论(0)    收藏  举报