[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];
}
}