码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【力扣周赛】第 112 场双周赛


    文章目录

    • 竞赛链接
    • Q1:7021. 判断通过操作能否让字符串相等 I
    • Q2:7005. 判断通过操作能否让字符串相等 II(贪心)
    • Q3:2841. 几乎唯一子数组的最大和
      • 竞赛时代码——滑动窗口
    • Q4:8050. 统计一个字符串的 k 子序列美丽值最大的数目(贪心+计数+组合数学)
      • 竞赛时代码(赛时通过,结束之后被rejudge了)🤯
      • 正确解法⭐
    • 成绩记录

    竞赛链接

    https://leetcode.cn/contest/biweekly-contest-112/

    Q1:7021. 判断通过操作能否让字符串相等 I

    https://leetcode.cn/problems/check-if-strings-can-be-made-equal-with-operations-i/

    在这里插入图片描述

    提示:
    s1.length == s2.length == 4
    s1 和 s2 只包含小写英文字母。

    class Solution {
        public boolean canBeEqual(String s1, String s2) {
            // 取出各个字符
            char a = s1.charAt(0), b = s1.charAt(1), c = s1.charAt(2), d = s1.charAt(3);
            char a2 = s2.charAt(0), b2 = s2.charAt(1), c2 = s2.charAt(2), d2 = s2.charAt(3);
            // 比较
            return (a == a2 || a == c2) && (a + c == a2 + c2) && (b == b2 || b == d2) && (b + d == b2 + d2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Q2:7005. 判断通过操作能否让字符串相等 II(贪心)

    https://leetcode.cn/problems/check-if-strings-can-be-made-equal-with-operations-ii/description/

    在这里插入图片描述

    提示:
    n == s1.length == s2.length
    1 <= n <= 10^5
    s1 和 s2 只包含小写英文字母。

    只要两个字符串的奇偶位的各个字符的数量相等,就一定可以通过交换位置换成相同的字符串。

    class Solution {
        public boolean checkStrings(String s1, String s2) {
            // 分别记录两个字符串的奇偶位字符数量
            int[] cnt1 = new int[26], cnt2 = new int[26], cnt3 = new int[26], cnt4 = new int[26];
            int n = s1.length();
            for (int i = 0; i < n; ++i) {
                if (i % 2 == 0) {
                    cnt1[s1.charAt(i) - 'a']++;
                    cnt3[s2.charAt(i) - 'a']++;
                } else {
                    cnt2[s1.charAt(i) - 'a']++;
                    cnt4[s2.charAt(i) - 'a']++;
                }
            }
            // 比较是否相等
            return Arrays.equals(cnt1, cnt3) && Arrays.equals(cnt2, cnt4);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Q3:2841. 几乎唯一子数组的最大和

    https://leetcode.cn/problems/maximum-sum-of-almost-unique-subarray/

    在这里插入图片描述
    提示:
    1 <= nums.length <= 2 * 10^4
    1 <= m <= k <= nums.length
    1 <= nums[i] <= 10^9

    竞赛时代码——滑动窗口

    滑动窗口,维护窗口内的总和以及独特元素数量。

    class Solution {
        public long maxSum(List<Integer> nums, int m, int k) {
            Map<Integer, Integer> cnt = new HashMap<>();
            int n = nums.size();
            long sum = 0, ans = 0;
            // 双指针+滑动窗口
            for (int i = 0, j = 0; i < n; ++i) {
                // 加入元素
                cnt.merge(nums.get(i), 1, Integer::sum);
                sum += nums.get(i);
                // 移除元素
                if (i - j >= k) {       
                    cnt.merge(nums.get(j), -1, Integer::sum);
                    sum -= nums.get(j);
                    if (cnt.get(nums.get(j)) == 0) cnt.remove(nums.get(j));
                    j++;
                }
                // 如果是几乎唯一子数组,就尝试更新答案
                if (i - j + 1 == k && cnt.size() >= m) ans = Math.max(ans, sum);
            }
            return ans;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    Q4:8050. 统计一个字符串的 k 子序列美丽值最大的数目(贪心+计数+组合数学)

    https://leetcode.cn/problems/count-k-subsequences-of-a-string-with-maximum-beauty/
    在这里插入图片描述

    提示:
    1 <= s.length <= 2 * 10^5
    1 <= k <= s.length
    s 只包含小写英文字母。

    竞赛时代码(赛时通过,结束之后被rejudge了)🤯

    贪心地选取出现次数最多的字符。

    如果若干个字符的出现次数一样,那么就把答案乘上对应的组合数。

    比如从 0,1,1,1,2,3 中取 k 为 4,那么 3 和 2 是一定要被选择的,然后在 3 个 1 中任意选择 2 个 1 即可。答案为 3 * 2 * 1 * C(3,2) = 18。

    class Solution {
        public int countKSubsequencesWithMaxBeauty(String s, int k) {
            if (k > 26) return 0;
    
            long[] cnt = new long[26];          // 记录各个字符的数量
            for (char ch: s.toCharArray()) {
                cnt[ch - 'a']++;
            }
            Arrays.sort(cnt);                   // 按字符数量排序
            long ans = 1, MOD = (long)1e9 + 7;
            long mn = cnt[26 - k];              // 可选择的出现次数最少的字符出现次数
            ans = mn;
            // 求组合数是几选几 
            int end = -1;
            for (int i = 26 - k + 1; i < 26; ++i) {
                if (cnt[i] != mn) {
                    if (end == -1) end = i;
                }
                ans = (ans * cnt[i]) % MOD;
            }
            if (end == -1) end = 26;
            for (int i = 0; i < end; ++i) {
                if (cnt[i] == mn) {
                    int x = end - i;
                    long y = op(x, k - 26 + end);   // 求组合数
                    ans = (ans * y) % MOD;
                    break;
                }
            }
            return (int)ans;
        }
        
        // 求组合数C(x, y)
        public long op(int x, int y) {
            long ans = 1, m = 1;
            while (y != 0) {
                ans *= x;
                m *= y;
                x--;
                y--;
            }
            return ans / m;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    错误的样例是

    "xzkilqoqfdnjextrgqpywahbmsu"
    23
    
    • 1
    • 2

    预期结果是 132,但是我的代码返回了 0。

    原因可能是因为没有考虑到 mn = 0,那后续怎么乘都还是 0。

    正确解法⭐

    在这里插入图片描述
    这种做法的好处是枚举更清晰,代码逻辑也不会混乱。

    Q:为什么 k 太大就不存在合法子序列?
    A:因为 k 太大时,独特的字母的数量会不够用。

    class Solution {
        final long MOD = (long)1e9 + 7;
    
        public int countKSubsequencesWithMaxBeauty(String s, int k) {
            // 统计每种字符出现的次数
            int[] cnt = new int[26];
            for (char ch: s.toCharArray()) {
                cnt[ch - 'a']++;
            }
            // 统计每种出现次数,以及多少种字符是这种次数
            TreeMap<Integer, Integer> cc = new TreeMap<>();
            for (int c: cnt) {
                if (c > 0) cc.merge(c, 1, Integer::sum);
            }
    
            long ans = 1;
            // .descendingMap()返回按键降序排序
            for (Map.Entry<Integer, Integer> e: cc.descendingMap().entrySet()) {    
                int c = e.getKey(), num = e.getValue();
                if (num >= k) {
                    // 乘上 c^k 和 C(num, k)
                    return (int) (ans * pow(c, k) % MOD * comb(num, k) % MOD);
                }
                ans = ans * pow(c, num) % MOD;
                k -= num;
            }
            return 0;       // k太大,没有那么多种字符
        }
    
        // 计算 x^n 快速幂
        long pow(long x, int n) {
            long res = 1;
            // 把 n 看成二进制数字,哪些位置是 1,就把它乘起来就好了
            for (; n > 0; n /= 2) {
                if (n % 2 == 1) res = res * x % MOD;
                x = x * x % MOD;
            }
            return res;
        }
    
        // 计算 C(n,k)
        long comb(long n, long k) {
            long res = n;
            for (int i = 2; i <= k; ++i) {
                res = res * --n / i;
            }
            return res % MOD;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    关于快速幂可见:【算法基础:数学知识】4.4 快速幂

    成绩记录

    在这里插入图片描述

    就,还好。
    WA 次数有点多。

    在这里插入图片描述

  • 相关阅读:
    Cholesterol-PEG-FITC,Fluorescein-PEG-CLS,胆固醇-聚乙二醇-荧光素供应
    雷军的开源情怀
    菜鸟踩坑之MybatisPlus查询时过滤不想要的字段
    二、【redux】redux 完整版求和Demo
    拖拽表单设计器易操作、好灵活,创造高效办公!
    苹果笔记本电脑可以玩steam游戏吗 MacBook支持玩steam游戏吗 在Steam上玩黑神话悟空3A大作 苹果Mac怎么下载steam
    java计算机毕业设计新生入学报到管理系统源码+系统+数据库+lw文档
    yolov5 筛选正样本流程 代码多图详解
    新手小白适合做哪个跨境电商平台?测评自养号能带来哪些收益及优势?
    ubuntu 20.04+ORB_SLAM3 安装配库教程
  • 原文地址:https://blog.csdn.net/qq_43406895/article/details/132644854
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号