6056. 字符串中最大的 3 位相同数字
https://leetcode-cn.com/problems/largest-3-same-digit-number-in-string/
思路:枚举开始点0-n-3, 判断以开始点为起点的连续3个字符是否一样,一样则更新最大值
class Solution {
public String largestGoodInteger(String num) {
int n=num.length();
int ans=-1;
for(int i=0;i<n-2;i++) {
if(num.charAt(i)==num.charAt(i+1)&&num.charAt(i+1)==num.charAt(i+2)){
int val=Integer.parseInt(num.substring(i,i+3));
ans=Math.max(ans, val);
}
}
if(ans==-1)
return "";
else if(ans==0)
return "000";
else {
return ans+"";
}
}
}
6057. 统计值等于子树平均值的节点数
思路:递归计算以每个节点形成的子树的节点数目和节点数值和,当某个节点形成的子树遍历完后,判断是否平均值=节点值,是的话令成员变量ans加一,然后以数组的形式将结点数和数值和返回给上一层递归
class Solution {
int ans=0;
public int averageOfSubtree(TreeNode root) {
if(root==null)
return 0;
dfs(root);
return ans;
}
public int[] dfs(TreeNode node) {
if(node==null)
return new int[] {0,0};
int[] leftAns=dfs(node.left);
int[] rightAns=dfs(node.right);
int nodes=leftAns[0]+rightAns[0]+1;
int sum=leftAns[1]+rightAns[1]+node.val;
if(sum/nodes==node.val)
ans++;
return new int[] {nodes,sum};
}
}
6058. 统计打字方案数
https://leetcode-cn.com/problems/count-number-of-texts/
思路:对于按键7和9,上面有4个字符,考虑有连续的n个7,则这n个7可以形成多少种字母的组合?
由于最多可以选取4个连续的数字形成1个字符,所以对于7个9而言,当前的数字个数是n. n个数字可以构成的字符总和为: f[n]=f[n-1]+f[n-2]+f[n-3]+f[n-4]
因为新加入一个字符,该字符可以和之前的n-1个字符形成一个组合,也可以和之前的n-2个字符形成一个组合…(类似于跳台阶问题)
同理,对于除7和9之外的按键,上面只有3个字符,计算公式为:f[n]=f[n-1]+f[n-2]+f[n-3
计算出给定连续的数字所能形成的字符数目之后,后面只需要统计出每一段连续的字符个数,然后根据组合中的乘法定理对各部分得到的字符数相乘即可
class Solution {
public int countTexts(String pressedKeys) {
int n=pressedKeys.length();
long mod=(long) (1e9+7);
long[] dp3=new long[100000+1];
long[] dp4=new long[100000+1];
dp3[1]=dp4[1]=1;
dp3[2]=dp4[2]=2;
dp3[3]=dp4[3]=4;
dp3[4]=7;
dp4[4]=8;
for(int i=5;i<=n;i++){
dp3[i]=(dp3[i-1]+dp3[i-2]+dp3[i-3])%mod;
dp4[i]=(dp4[i-1]+dp4[i-2]+dp4[i-3]+dp4[i-4])%mod;
}
long ans=1;
int i=0;
while(i<n){
int j=i;
while(j<=n-2&&pressedKeys.charAt(j)==pressedKeys.charAt(j+1))
j++;
int cnt=j-i+1;
if(pressedKeys.charAt(i)=='7'||pressedKeys.charAt(i)=='9')
ans=ans*dp4[cnt]%mod;
else
ans=ans*dp3[cnt]%mod;
j++;
i=j;
}
return (int)(ans%mod);
}
}
6059. 检查是否有合法括号字符串路径
https://leetcode-cn.com/problems/check-if-there-is-a-valid-parentheses-string-path/
思路:动态规划
-
用一个变量c来来记录当前遍历得到的字符串中左括号和右括号的数量差,遇到左括号c加一,遇到右括号c减一,如果某个时刻c<0, 说明后面无论怎么添加括号都不会形成有效的括号序列,因此只有c>=0时后面才有可能得到一个有效的括号组合,对于右下角的格子(终点),记作其状态为
dp[m-1][n-1][c]
,则最终的路径是否可以得到一个合法的字符串取决于dp[m-1][n-1][0]
是否为true -
假设当前位置是
(i,j)
,那么对于当前格子的状态c值的范围是[0,i+1+j+1-1]=[0,i+j-1]
, 对于某个位置(i,j),它可以从左到右移动得到,也可以从上到下移动得到,根据当前格子是左括号还是右括号决定当前格子c值的变化,更新后的c值如果>=0说明可以继续往下走
class Solution {
public boolean hasValidPath(char[][] grid) {
int m=grid.length,n=grid[0].length;
boolean[][][] dp=new boolean[m][n][m+n];
if(grid[0][0]==')')
return false;
dp[0][0][1]=true;//第一个位置要求是左括号
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
for(int k=0;k<=i+j+1;k++){
if(dp[i][j][k]){//当前位置往后遍历可能得到有效的字符串
if(i+1<m){//可以往右走
int nk=k+(grid[i+1][j]=='('?1:-1);
if(nk>=0)//更新后的c值>=0 说明当前位置往后遍历可能得到有效的字符串
dp[i+1][j][nk]=true;
}
if(j+1<n){//可以往下走
int nk=k+(grid[i][j+1]=='('?1:-1);
if(nk>=0)//更新后的c值>=0 说明当前位置往后遍历可能得到有效的字符串
dp[i][j+1][nk]=true;
}
}
}
}
}
return dp[m-1][n-1][0];//最后一个格子的状态c=0如果满足 说明可以找到一个有效的字符串
}
}