一,2839. 判断通过操作能否让字符串相等 I
该题的题意就是看 单数下标 和 偶数下标的 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;}
}
二,2840. 判断通过操作能否让字符串相等 II
这题和上面那题是一个意思,直接复用上面的代码就行,改都不用改,这里就不在写了。
三,2841. 几乎唯一子数组的最大和
该题一看就是一道滑动窗口的题目,要找的是长度为 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;}
}
四,2842. 统计一个字符串的 k 子序列美丽值最大的数目
这道题题目很长,我们先举几个例子来理解一下:
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,取-xmap.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^nlong 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;}
}