[杨小白]_leetcode_力扣_第 92 场双周赛第四题

227 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标1900分,现在1806!!

力扣第 92 场双周赛-力扣

第 92 场双周赛 - 力扣(LeetCode)

前三题都不咋难,第四题没做出来,,一直超时,确实有点难。

周日打周赛的人都不多了,周六的双周赛更少了。

image.png

2484. 统计回文子序列数目

给你数字字符串 s ,请你返回 s 中长度为 5 的 回文子序列 数目。由于答案可能很大,请你将答案对 109 + 7 取余 后返回。

提示:

如果一个字符串从前往后和从后往前读相同,那么它是 回文字符串 。

子序列是一个字符串中删除若干个字符后,不改变字符顺序,剩余字符构成的字符串。

示例 1:

输入:s = "103301"

输出:2

解释:

总共有 6 长度为 5 的子序列:"10330" ,"10331" ,"10301" ,"10301" ,"13301" ,"03301" 。 它们中有两个(都是 "10301")是回文的。

示例 2:

  • 输入: s = "9999900000"
  • 输出: 2
  • 解释: 仅有的两个回文子序列是 "99999" 和 "00000" 。

示例 3:

  • 输入: s = "0000000"
  • 输出: 21
  • 解释: 所有 21 个长度为 5 的子序列都是 "00000" ,都是回文的。

提示:

  • 1 <= s.length <= 104
  • s 只包含数字字符。

代码

很多题解都贴了这题,确实思路差不多。长度为3的回文做法,遍历中间的数,统计index坐标和右边相同字符的个数就可以了。

[杨小白]_leetcode_力扣_1930. 长度为 3 的不同回文子序列 - 掘金 (juejin.cn)

1930. 长度为 3 的不同回文子序列

那么本题长度为5的回文,做法相似。首先dp[i][j][k]表示,包括i之后的所有字符中,jk出现的次数。

从后向前遍历整个字符串,更新dp。

现在从前往后更新predp[j][k],表示index往前的字符中,出现jk的次数。

这样对于index,前面出现jk的次数 * 后面出现kj的次数,就是一个回文,启聪jk从00到99共100种,进行遍历即可。

空间复杂度是O(nmm) 时间复杂度是O(nmm),m为10,n为字符串长度

class Solution {
    public int countPalindromes(String s) {
        if(s.length() < 5) return 0;
        int MOD = 1_000_000_007;
        int[][][] dp = new int[s.length() + 2][10][10];
        int[] num = new int[10];
        for(int i = s.length() - 1; i >= 0; i--) {
            int b = s.charAt(i) - '0';
            for (int j = 0; j < 10; j++) {
                for (int k = 0; k < 10; k++) {
                    dp[i][j][k] = dp[i + 1][j][k];
                }
            }
            for(int j = 0; j < 10; j++) {
                dp[i][b][j] = (dp[i + 1][b][j] + num[j]) % MOD;
            }
            num[b]++;
        }
        long res = 0;
        long[][] predp = new long[10][10];
        num = new int[10];
        num[s.charAt(0) - '0']++;
        num[s.charAt(1) - '0']++;
        predp[s.charAt(0) - '0'][s.charAt(1) - '0']++;
        for(int i = 2; i < s.length(); i++) {
            for(int j = 0; j < 10; j++) {
                for(int k = 0; k <10; k++) {
                    res = res + (predp[j][k] * dp[i +1][k][j]) % MOD;
                    res = res % MOD;
                }
            }
            int b = s.charAt(i) - '0';
            for(int j = 0; j < 10; j++){
                predp[j][b] = (predp[j][b] + num[j]) % MOD;
            }
            num[b]++;
        }
        return (int)res;
    }
}

3.结束

image.png

前三题太简单,第四题太难,真是无语,好歹手速快还是能涨个20大几分。