• 第 112 场 LeetCode 双周赛题解


    A 判断通过操作能否让字符串相等 I

    在这里插入图片描述

    s 1 s1 s1 s 2 s2 s2 1 1 1 2 2 2位若同位置不等,则 s 1 s1 s1交换对应的 i i i j j j位置,之后判断 s 1 s1 s1 s 2 s2 s2是否相当

    class Solution {
    public:
        bool canBeEqual(string s1, string s2) {
            for (int i = 0; i + 2 < 4; i++)
                if (s1[i] != s2[i])
                    swap(s1[i], s1[i + 2]);
            return s1 == s2;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    B 判断通过操作能否让字符串相等 II

    在这里插入图片描述

    排序:一个字符串中下标奇偶性相同的位置可以任意交换,所以将字符串按下标奇偶划分成两个子串,再对子串分别排序,再分别比较两个串的子串

    class Solution {
    public:
        bool checkStrings(string s1, string s2) {
            string a1, b1, a2, b2;
            for (int i = 0; i < s1.size(); i++)
                if (i & 1)
                    a1.push_back(s1[i]);
                else
                    b1.push_back(s1[i]);
            for (int i = 0; i < s2.size(); i++)
                if (i & 1)
                    a2.push_back(s2[i]);
                else
                    b2.push_back(s2[i]);
            sort(a1.begin(), a1.end());
            sort(b1.begin(), b1.end());
            sort(a2.begin(), a2.end());
            sort(b2.begin(), b2.end());
            return a1 == a2 && b1 == b2;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    C 几乎唯一子数组的最大和

    在这里插入图片描述

    滑动窗口+哈希:用滑动窗口枚举长为 k k k 的子数组,用哈希表记录子数组中各元素出现的次数,以维护当前子数组中不同元素的个数

    class Solution {
    public:
        long long maxSum(vector<int> &nums, int m, int k) {
            unordered_map<int, int> f;//子数组中各元素出现的次数
            int cnt = 0;//当前子数组中不同元素的个数
            long long s = 0;//当前子数组元素和
            for (int i = 0; i < k - 1; i++) {
                if (++f[nums[i]] == 1)
                    cnt++;
                s += nums[i];
            }
            long long res = 0;
            for (int l = 0, r = k - 1; r < nums.size(); l++, r++) {//枚举长为k的子数组nums[l,r]
                if (++f[nums[r]] == 1)
                    cnt++;
                s += nums[r];
                if (cnt >= m)
                    res = max(res, s);
                if (--f[nums[l]] == 0)
                    cnt--;
                s -= nums[l];
            }
            return res;
        }
    };
    
    • 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

    D 统计一个字符串的 k 子序列美丽值最大的数目

    在这里插入图片描述

    排序+计数:当 k > 26 k>26 k>26 时显然不存在 k k k 子序列,所以答案为0。当 k ≤ 26 k\le 26 k26 时,将字符出现次数数组 f f f 降序排序,设排序后的 f f f 中大小关系有: f 0 ≥ ⋯ > f l = ⋯ = f k − 1 = ⋯ = f r > ⋯ f_0\ge\cdots>f_l=\cdots=f_{k-1}=\cdots=f_r>\cdots f0>fl==fk1==fr>
    则在美丽值最大的 k k k 子序列中,前 l l l 个不同字符是必选的,之后会在 [ l , r ] [l,r] [l,r] 范围内选 k − l k-l kl 个不同的字符,所以答案即为(注意取模): ( ∏ i = 0 i < l f i ) × ( r − l + 1 k − l ) × ( f k − 1 ) k − l \left ( \prod_{i=0}^{i(i=0i<lfi)×(klrl+1)×(fk1)kl

    class Solution {
    public:
        using ll = long long;
        ll mod = 1e9 + 7;
        ll c[27][27];
    
        ll get(int n, int k) {//求组合数: C(n,k)
            if (c[n][k] != INT64_MIN)
                return c[n][k];
            if (k == 0 || n == k)
                return c[n][k] = 1;
            return c[n][k] = (get(n - 1, k) + get(n - 1, k - 1)) % mod;
        }
    
        ll fpow(ll x, ll n) {//快速幂: x^n
            ll res = 1;
            for (ll e = x; n; e = (e * e) % mod, n >>= 1)
                if (n & 1)
                    res = (res * e) % mod;
            return res;
        }
    
        int countKSubsequencesWithMaxBeauty(string s, int k) {
            if (k > 26)
                return 0;
            vector<ll> f(26);
            for (auto &c: s)
                f[c - 'a']++;
            sort(f.begin(), f.end(), greater<int>());//降序排序
            if (f[k - 1] == 0)//不存在k子序列
                return 0;
            int r = k - 1;
            while (r + 1 < 26 && f[r] == f[r + 1])//定位r
                r++;
            ll res = 1;
            int l = 0;
            for (; f[l] != f[k - 1]; l++)
                res = (res * f[l]) % mod;
            for (int i = 0; i <= 26; i++)
                for (int j = 0; j <= 26; j++)
                    c[i][j] = INT64_MIN;//初始化标志
            res = (res * fpow(f[k - 1], k - l) % mod * get(r - l + 1, k - l)) % mod;
            return (res + mod) % 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
  • 相关阅读:
    编程语言的类型划分
    拥有自己的数藏平台难不难
    Linux Shell 基础语法 流程控制 逻辑运算 字符串操作详细解析
    当我们谈论量化时,我们在谈论什么?量化投资常见策略有哪些?| 融券T0和高频交易详解【邢不行】
    Unity中Shader反射环境
    数据结构题目收录(四)
    【ACL2023】Event Extraction as Question Generation and Answering
    二造考生必看|巩固优选题库助力考生最后冲刺
    实现Springcloud跨项目相互调用(简易版)
    UG\NX二次开发 连接曲线、连结曲线 UF_CURVE_auto_join_curves
  • 原文地址:https://blog.csdn.net/weixin_40519680/article/details/132644053