该题的题意就是看 单数下标 和 偶数下标的 s1 和 s2 中的字母及其数量是否相等。
代码如下(也可以使用哈希表来做):
- class Solution {
- public boolean canBeEqual(String s1, String s2) {
- int[] a = new int[26];//统计偶数下标
- int[] b = new int[26];//统计奇数下标
- for(int i=0; i<s1.length(); i+=2){
- a[s1.charAt(i)-'a']++;
- a[s2.charAt(i)-'a']--;
- if(i+1 < s1.length()){
- b[s1.charAt(i+1)-'a']++;
- b[s2.charAt(i+1)-'a']--;
- }
- }
- for(int i=0; i<26; i++){
- if(a[i]!=0 || b[i]!=0)
- return false;
- }
- return true;
- }
- }

这题和上面那题是一个意思,直接复用上面的代码就行,改都不用改,这里就不在写了。

该题一看就是一道滑动窗口的题目,要找的是长度为 k 的子数组并且子数组中有 >= m 个不同的值,求满足上述条件的子数组中,最大子数组和。
代码如下:
- class Solution {
- public long maxSum(List<Integer> nums, int m, int k) {
- long ans = 0;
- long cur = 0;
- Map<Integer,Integer> map = new HashMap<>();
- for(int i=0; i<nums.size(); i++){
- cur += nums.get(i);
- map.put(nums.get(i),map.getOrDefault(nums.get(i),0)+1);
- if(i >= k-1){//子数组长度已满
- if(map.size() >= m){
- ans = Math.max(ans,cur);
- }
- int out = i - k + 1;//要滑出去的下标
- int val = map.get(nums.get(out));
- if(val == 1){
- map.remove(nums.get(out));
- }else{
- map.put(nums.get(out),val-1);
- }
- cur -= nums.get(out);
- }
- }
- return ans;
- }
- }

这道题题目很长,我们先举几个例子来理解一下:
1. k = 1,s = "aabbbc"
ans = 3
2. k = 1,s = "aaabbb"
ans = 3^k*C(2,k) = 6
3. k = 2, s = "aaabbb"
ans = 2*3 = 6
//乘法原理
4. k = 2, s = "aaabbbccc"
ans = 3^k*C(3,k)
//C(3,k)实际就是从a,b,c中选两个有多少选法,就是数学中的排列组合
5. k = 4, s = "aabbbccdd"
先选择b,ans = 3,k -= 1
然后变成 k = 3,s = "aaccdd"
ans = ans * 2^3 * C(3,3)
根据上面举的例子可知,我们需要知道:
1. 每个字母的出现次数
2. 出现次数相同的字母个数
3. 按照出现次数从大到小枚举
- class Solution {
- private static final long MOD = (long) 1e9 + 7;
- /**
- TreeMap中存储是有顺序的!!!
- TreeMap使用Map.entrySet()是从小到大输出的!!!
- HashMap使用Map.entrySet()是随机输出的!!!
- */
- public int countKSubsequencesWithMaxBeauty(String s, int k) {
- int[] cnt = new int[26];
- for(int i=0; i<s.length(); i++){
- cnt[s.charAt(i)-'a']++;//统计每个字母的出现次数
- }
- Map<Integer,Integer> map = new TreeMap<>();
- for(int x : cnt){
- if(x > 0)//TreeMap是从小到大存储数据,我们要从大到小枚举,因此存-x,取-x
- map.put(-x,map.getOrDefault(-x,0)+1);
- }
- //aaabbbcccddd
- //<3,4>
- //<出现次数,出现次数相同的字母有几个>
- long ans = 1;
- for(Map.Entry<Integer,Integer> entry : map.entrySet()){
- int key = -entry.getKey();//出现次数
- int value = entry.getValue();//出现次数相同的字母有几个
- if(value >= k)
- return (int)(ans*pow(key,k)%MOD*comb(value,k)%MOD);//key^k*C(value,k)
- ans = ans*pow(key,value)%MOD;
- k -= value;
- }
- return 0;
- }
- long pow(long x, int n){//快速幂算法 x^n
- long res = 1;
- while(n != 0){
- if(n%2 != 0){
- res = res*x%MOD;
- }
- x = x*x%MOD;
- n/=2;
- }
- return res;
- }
- long comb(long n, int k){//数学中的组合排序算法 C(n,k)
- long res = n;
- for(int i=2; i<=k; i++){
- res = res*(--n)/i;
- }
- return res%MOD;
- }
- }