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;
    }
}
相关推荐
纠结哥_Shrek1 小时前
AI常见的算法
人工智能·算法
Oracle_6661 小时前
C语言------数组从入门到精通
c语言·算法·排序算法
南宫生2 小时前
力扣动态规划-15【算法学习day.109】
java·学习·算法·leetcode·动态规划
ThE.wHIte.2 小时前
Leetcode 131 分割回文串(纯DFS)
算法·leetcode·职场和发展
xiaoshiguang32 小时前
LeetCode:96.不同的二叉搜索树
java·算法·leetcode·动态规划
hamster20212 小时前
力扣【416. 分割等和子集】详细Java题解(背包问题)
java·算法·leetcode
纠结哥_Shrek3 小时前
Q学习 (Q-Learning):基于价值函数的强化学习算法
学习·算法
charlie1145141913 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(动态菜单组件实现)
c语言·驱动开发·stm32·单片机·算法·教程·oled
cccc楚染rrrr4 小时前
572. 另一棵树的子树
java·数据结构·算法