[杨小白]_leetcode_力扣_1930. 长度为 3 的不同回文子序列

192 阅读1分钟

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

前言

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

困难版本: [杨小白]_leetcode_力扣_第 92 场双周赛第四题-2484. 统计回文子序列数目)

简单版本:

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

给你一个字符串 s ,返回 s 中 长度为 3 的不同回文子序列 的个数。

即便存在多种方法来构建相同的子序列,但相同的子序列只计数一次。

回文 是正着读和反着读一样的字符串。

子序列 是由原字符串删除其中部分字符(也可以不删除)且不改变剩余字符之间相对顺序形成的一个新字符串。

例如,"ace" 是 "abcde" 的一个子序列。

示例 1:

输入:s = "aabca"

输出:3

解释:长度为 3 的 3 个回文子序列分别是:

  • "aba" ("aabca" 的子序列)
  • "aaa" ("aabca" 的子序列)
  • "aca" ("aabca" 的子序列)

示例 2:

  • 输入: s = "adc"
  • 输出: 0
  • 解释: "adc" 不存在长度为 3 的回文子序列。

示例 3:

输入:s = "bbcbaba"

输出:4

解释:长度为 3 的 4 个回文子序列分别是:

  • "bbb" ("bbcbaba" 的子序列)
  • "bcb" ("bbcbaba" 的子序列)
  • "bab" ("bbcbaba" 的子序列)
  • "aba" ("bbcbaba" 的子序列)

提示:

  • 3 <= s.length <= 105
  • s 仅由小写英文字母组成

代码

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

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

思路:遍历中间的字符,统计index前,和index后相同字符的个数,用dp遍历一遍字符串,将第二个到最后的字符都统计到dp中。

从1开始遍历字符串,对于中间的index来讲,predp表示index之前26个字符分别出现的次数,dp表示index之后26个字符出现的次数,只需要遍历26个字母,就可以知道对于index作为中间字符,有多少个回文序列了。

有个坑

  1. 重复出现的只算一次,例如示例3 当中间的字符又出现b,bbb只能算一次。这是个大坑,所有用了set保证不重复

用vis也是来去重,会比set快,一个是41ms 一个是1156ms

vis[i][j]=1,表示iji出现过;等于0表示没出现过。

//41 ms | 41.6 MB |
class Solution {
    public int countPalindromicSubsequence(String s) {
        char[] chars = s.toCharArray();
        int[] dp = new int[26];
        int[][] vis = new int[26][26];
        int res = 0;
        for(int i = 2; i < chars.length; i++) {
            dp[chars[i] - 'a']++;
        }
        int[] predp = new int[26];
        predp[chars[0] - 'a']++;
        for(int i = 1; i < chars.length - 1; i++) {
            for(int j = 0; j < 26; j++) {
                if(predp[j] != 0 && dp[j] != 0 && vis[j][chars[i]-'a'] == 0) {
                    res++;
                    vis[j][chars[i]-'a']++;
                }
            }
            dp[chars[i + 1] - 'a']--;
            predp[chars[i] - 'a']++;
        }
        return res;
    }
}
//1156 ms | 46.3 MB |
class Solution {
    public int countPalindromicSubsequence(String s) {
        char[] chars = s.toCharArray();
        int[] dp = new int[26];
        HashSet<String> res = new HashSet<>();
        for(int i = 2; i < chars.length; i++) {
            dp[chars[i] - 'a']++;
        }
        int[] predp = new int[26];
        predp[chars[0] - 'a']++;
        for(int i = 1; i < chars.length - 1; i++) {
            for(int j = 0; j < 26; j++) {
                if(predp[j] != 0 && dp[j] != 0) {
                    res.add(chars[i] +""+ (char)('a' + j));
                }
            }
            dp[chars[i + 1] - 'a']--;
            predp[chars[i] - 'a']++;
        }
        return res.size();
    }
}