Leetcode - 112双周赛

一,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,取-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;
    }
}
相关推荐
南宫生38 分钟前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步1 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara2 小时前
函数对象笔记
c++·算法
测试19982 小时前
2024软件测试面试热点问题
自动化测试·软件测试·python·测试工具·面试·职场和发展·压力测试
泉崎2 小时前
11.7比赛总结
数据结构·算法
你好helloworld2 小时前
滑动窗口最大值
数据结构·算法·leetcode
AI街潜水的八角3 小时前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
白榆maple3 小时前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少3 小时前
数据结构——线性表与链表
数据结构·c++·算法
sjsjs113 小时前
【数据结构-合法括号字符串】【hard】【拼多多面试题】力扣32. 最长有效括号
数据结构·leetcode