[Leetcode Weekly Contest]292

链接:LeetCode

[Leetcode]2264. 字符串中最大的 3 位相同数字

给你一个字符串 num ,表示一个大整数。如果一个整数满足下述所有条件,则认为该整数是一个 优质整数 :

  • 该整数是 num 的一个长度为 3 的 子字符串 。
  • 该整数由唯一一个数字重复 3 次组成。

以字符串形式返回 最大的优质整数 。如果不存在满足要求的整数,则返回一个空字符串 "" 。
注意:

  • 子字符串 是字符串中的一个连续字符序列。
  • num 或优质整数中可能存在 前导零 。

遍历即可。

class Solution {
    public String largestGoodInteger(String num) {
        char cur = 'N';
        char pre = 'N';
        int n = 0;
        for(char ch:num.toCharArray()) {
            if(cur != 'N' && ch < cur){
                n = 0;
                pre = 'N';
                continue;
            }
            else {
                if(ch == pre) n ++;
                else n = 1;
                if(n == 3) cur = ch;
                pre = ch;
            }
        }
        if(cur == 'N') return "";
        return ""+cur+cur+cur;
    }
}

[Leetcode]2265. 统计值等于子树平均值的节点数

给你一棵二叉树的根节点 root ,找出并返回满足要求的节点数,要求节点的值等于其 子树 中值的 平均值 。
注意:

  • n 个元素的平均值可以由 n 个元素 求和 然后再除以 n ,并 向下舍入 到最近的整数。
  • root 的 子树 由 root 和它的所有后代组成。

dfs 保存总和、节点数量, 自底向上递归。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int res = 0;
    public int averageOfSubtree(TreeNode root) {
        dfs(root);
        return res;
    }

    public int[] dfs(TreeNode root) {
        if(root.left == null && root.right == null) {
            res++;
            return new int[]{ root.val, 1};
        }
        int[] leftRes = new int[2];
        int[] rightRes = new int[2];
        if(root.left!=null) leftRes = dfs(root.left);
        if(root.right!=null) rightRes = dfs(root.right);
        int curSum = root.val + leftRes[0] + rightRes[0];
        int curCount = 1 + leftRes[1] + rightRes[1];
        if(curSum / curCount == root.val) res ++;
        return new int[]{curSum, curCount};
    }
}

[Leetcode]2266. 统计打字方案数

Alice 在给 Bob 用手机打字。
为了 打出 一个字母,Alice 需要 按 对应字母 i 次,i 是该字母在这个按键上所处的位置。

  • 比方说,为了按出字母 's' ,Alice 需要按 '7' 四次。类似的, Alice 需要按 '5' 两次得到字母 'k' 。
  • 注意,数字 '0' 和 '1' 不映射到任何字母,所以 Alice 不 使用它们。

但是,由于传输的错误,Bob 没有收到 Alice 打字的字母信息,反而收到了 按键的字符串信息 。

  • 比方说,Alice 发出的信息为 "bob" ,Bob 将收到字符串 "2266622" 。

给你一个字符串 pressedKeys ,表示 Bob 收到的字符串,请你返回 Alice 总共可能发出多少种文字信息 。由于答案可能很大,将它对 \(10^9 + 7\) 取余 后返回。

动态规划。把相同字符分为一组,每组内只有一种字符,考虑如下 DP:

对于字符不为 \(\texttt{7}\)\(\texttt{9}\) 的情况,定义 \(f[i]\) 表示长为 \(i\) 的只有一种字符的字符串对应的文字信息种类数,我们可以将末尾的 1 个、2 个或 3 个字符单独视作一个字母,那么有转移方程

\(f[i] = f[i-1]+f[i-2]+f[i-3]\)

对于字符为 \(\texttt{7}\)\(\texttt{9}\) 的情况,定义 \(g[i]\) 表示长为 i 的只有一种字符的字符串对应的文字信息种类数,可以得到类似的转移方程

\(g[i] = g[i-1]+g[i-2]+g[i-3]+g[i-4]\)

这样能算出每组字符串的文字信息种类数。

class Solution {
    public int countTexts(String pressedKeys) {
        int MOD = (int)Math.pow(10,9) + 7;
        int n = pressedKeys.length();
        long[] dp = new long[n];
        dp[0] = 1;
        for(int i = 1; i < n; ++i) {
            dp[i] = dp[i-1];
            int j = 3;
            if(pressedKeys.charAt(i) == '7' ||pressedKeys.charAt(i) == '9') j = 4;
            for(int k = 1; k < j;++k) {
                if(i-k >=0 && pressedKeys.charAt(i) == pressedKeys.charAt(i-k))
                    if (i-k-1>=0) dp[i] += dp[i-k-1]%MOD;
                    else dp[i] += 1;
                else break;
            }
        }
        return (int)(dp[n-1]%MOD);
    }
}

[Leetcode]2267. 检查是否有合法括号字符串路径

一个括号字符串是一个 非空 且只包含 '(' 和 ')' 的字符串。如果下面 任意 条件为 真 ,那么这个括号字符串就是 合法的 。

字符串是 () 。
字符串可以表示为 AB(A 连接 B),A 和 B 都是合法括号序列。
字符串可以表示为 (A) ,其中 A 是合法括号序列。
给你一个 m x n 的括号网格图矩阵 grid 。网格图中一个 合法括号路径 是满足以下所有条件的一条路径:

路径开始于左上角格子 (0, 0) 。
路径结束于右下角格子 (m - 1, n - 1) 。
路径每次只会向 下 或者向 右 移动。
路径经过的格子组成的括号字符串是 合法 的。
如果网格图中存在一条 合法括号路径 ,请返回 true ,否则返回 false 。

动态规划。判断一个括号序列是否合法是经典问题。对于一个括号序列,我们从左向右遍历每个字符,同时维护变量 now(初值为 0)。遇到左括号时,now += 1,遇到右括号时,now -= 1。如果过程中 now 始终非负,且最后 now 变成 0 则序列合法。

class Solution {
    // DP
    public boolean hasValidPath(char[][] grid) {
        int n = grid.length, m = grid[0].length;
        if(((n+m) & 1) == 0) return false;
        if(grid[0][0]!='(' || grid[n-1][m-1]!=')') return false;
        int k = (n+m+1) / 2;
        boolean[][][] dp = new boolean[n][m][k+2];
        for(int i=0;i<n;++i) {
            for(int j=0;j<m;++j) {
                if(i == 0 && j == 0) {
                    dp[0][0][1] = true;
                    continue;
                }
                for(int kk=0;kk<=k+1;++kk) {
                    if(grid[i][j] == '(') {
                        if(kk==0) continue;
                        if(i==0) dp[i][j][kk] = dp[i][j-1][kk-1];
                        else if(j == 0) dp[i][j][kk] = dp[i-1][j][kk-1];
                        else dp[i][j][kk] = dp[i][j-1][kk-1] || dp[i-1][j][kk-1];
                    }
                    else {
                        if(kk==k+1) continue;
                        if(i==0) dp[i][j][kk] = dp[i][j-1][kk+1];
                        else if(j == 0) dp[i][j][kk] = dp[i-1][j][kk+1];
                        else dp[i][j][kk] = dp[i][j-1][kk+1] || dp[i-1][j][kk+1];
                    }
                }
            }
        }
        return dp[n-1][m-1][0];
    }
}
posted @ 2022-06-16 09:52  Jamest  阅读(21)  评论(0编辑  收藏  举报