长度为 3 的不同回文子序列
难度:
标签:
题目描述
代码结果
运行时间: 107 ms, 内存: 21.2 MB
/*
* 思路:
* 1. 使用Java Stream API实现查找回文子序列的逻辑。
* 2. 对于每个字符作为中心字符,使用stream来找到所有可能的回文子序列。
* 3. 将找到的回文子序列存储在Set中以去重。
*/
import java.util.HashSet;
import java.util.Set;
import java.util.stream.IntStream;
public class PalindromicSubsequenceStream {
public static int countPalindromicSubsequences(String s) {
Set<String> palindromes = new HashSet<>();
int n = s.length();
IntStream.range(1, n - 1).forEach(i -> { // i是中心字符
char mid = s.charAt(i);
IntStream.range(0, i).forEach(j -> { // 遍历左边的字符
IntStream.range(i + 1, n).forEach(k -> { // 遍历右边的字符
if (s.charAt(j) == s.charAt(k)) { // 左右字符相同
String palindrome = "" + s.charAt(j) + mid + s.charAt(k);
palindromes.add(palindrome);
}
});
});
});
return palindromes.size();
}
public static void main(String[] args) {
System.out.println(countPalindromicSubsequences("aabca")); // 输出:3
System.out.println(countPalindromicSubsequences("adc")); // 输出:0
System.out.println(countPalindromicSubsequences("bbcbaba")); // 输出:4
}
}
解释
方法:
本题解采用了哈希表和二分查找的结合策略。首先,使用一个哈希表idx来存储每个字符在字符串s中出现的所有索引。接着,遍历哈希表的每个键值对,将当前键作为回文子序列的中心字符。如果中心字符出现次数超过2次,则直接将结果ret加1,因为可以形成如'aaa'这样的回文子序列。然后,对于每一个非中心的字符,使用二分查找检查它是否能够在中心字符的两侧出现,从而形成如'aba'这样的回文子序列。如果可以,结果ret加1。最终,返回结果ret。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在这个算法中,如果一个字符在字符串中出现超过两次,就可以直接计数为一个合法的回文子序列‘aaa’?
▷🦆
在使用二分查找确定两侧字符时,为什么选择使用`bisect_left`而不是`bisect_right`?
▷🦆
在遍历非中心字符时,为什么要跳过与中心字符相同的字符,它们不可能形成有效的回文子序列吗?
▷🦆
在二分查找中,`l` 和 `r` 的比较为什么可以确定存在一个有效的‘aba’型回文子序列?具体是基于哪些位置条件?
▷