开启掘金成长之旅!这是我参与「掘金日新计划 · 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 <= 105s仅由小写英文字母组成
代码
很多题解都贴了这题,确实思路差不多。长度为3的回文做法,遍历中间的数,统计index坐标和右边相同字符的个数就可以了。
1930. 长度为 3 的不同回文子序列
思路:遍历中间的字符,统计index前,和index后相同字符的个数,用dp遍历一遍字符串,将第二个到最后的字符都统计到dp中。
从1开始遍历字符串,对于中间的index来讲,predp表示index之前26个字符分别出现的次数,dp表示index之后26个字符出现的次数,只需要遍历26个字母,就可以知道对于index作为中间字符,有多少个回文序列了。
有个坑
- 重复出现的只算一次,例如示例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();
}
}