当前位置:首页 > 力扣 > 力扣2842题解析:子序列计数与组合数学优化(含代码详解)

力扣2842题解析:子序列计数与组合数学优化(含代码详解)

7个月前 (08-14)

力扣2842题解析:子序列计数与组合数学优化(含代码详解) 力扣题解 组合数学 动态规划 哈希表 频率统计 第1张

一、题目解读

力扣2842题要求给定字符串s和整数k,计算s中长度为k子序列数量。返回结果对10^9+7取模。题目难点在于平衡字符频率统计组合数学计算,避免超时。

二、解题思路

采用“频率统计+组合数计算”策略:

1. 利用哈希表(unordered_map)统计s中各字符频率,快速获取不同字符数。

2. 若不同字符数不足k,直接返回0,减少无效计算。

3. 对频率降序排序,确保优先处理高频字符,降低后续组合计算复杂度。

4. 通过滑动窗口统计相同频率字符的个数,结合组合数学公式计算重复字符的组合方案数,最终乘积取模。

三、解题步骤

1. 频率统计:遍历s,用哈希表记录每个字符的出现次数,获取不同字符数(即潜在美观度)。

2. 边界判断:若不同字符数< k,无解,直接返回0。

3. 频率排序:将频率存入vector并降序排序,便于后续组合计算。

4. 核心计算:

○ 遍历前k个频率,累乘每个频率作为子序列基数(res *= counts[i])。

○ 使用last和same_count记录当前频率的连续相同次数。

5. 处理重复频率:计算相同频率字符的总数(total_same)与组合数C(total_same, same_count),乘积并入结果。

6. 取模优化:所有乘积均对MOD取模,防止溢出。

四、代码与注释

class Solution {
public:
    int countKSubsequencesWithMaxBeauty(string s, int k) {
        const int MOD = 1e9 + 7;
        
        // 统计每个字符的出现频率
        unordered_map<char, int> freq;
        for (char c : s) {
            freq[c]++;
        }
        
        // 如果不同字符数小于k,不可能有k子序列,返回0
        if (freq.size() < k) {
            return 0;
        }
        
        // 将频率从高到低排序
        vector<int> counts;
        for (auto& [c, cnt] : freq) {
            counts.push_back(cnt);
        }
        sort(counts.rbegin(), counts.rend());
        
        long long res = 1;
        int last = -1;
        int same_count = 0;
        
        for (int i = 0; i < k; ++i) {
            res = (res * counts[i]) % MOD;
            
            // 统计有多少个字符的频率等于当前处理的频率
            if (counts[i] == last) {
                same_count++;
            } else {
                last = counts[i];
                same_count = 1;
            }
        }
        
        // 处理相同频率的情况
        int total_same = 0;
        for (int cnt : counts) {
            if (cnt == last) {
                total_same++;
            }
        }
        
        // 计算组合数 C(total_same, same_count)
        long long comb = 1;
        for (int i = 1; i <= same_count; ++i) {
            comb = comb * (total_same - same_count + i) / i;
        }
        
        res = (res * comb) % MOD;
        
        return res;
    }
};

五、总结

本解法核心在于将子序列计数转化为频率排序与组合数学问题,通过预处理频率、降序遍历与动态统计重复次数,大幅降低计算复杂度。此外,取模操作贯穿全程,确保大数据场景下的正确性。该方案兼顾效率与可读性,是解决此类子序列计数问题的典型范式。


原创内容 转载请注明出处

分享给朋友:

相关文章

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

一、题目解读    2024年GESP(青少年软件编程能力等级考试)五级中的“武器强化”(洛谷平台题目编号B4071)是一道典型的算法优化问题。题目要求通过合理...

LeetCode 120题三角形最小路径和最优解法:动态规划详解与代码实现

LeetCode 120题三角形最小路径和最优解法:动态规划详解与代码实现

一、题目解读LeetCode 120题“三角形最小路径和”要求给定一个由数字组成的三角形,从顶部开始向下移动,每次可向左或向右移动一格,计算从顶至底的最小路径和。三角形以二维向量形式给出,每层元素数量...

洛谷2789题解:直线交点数的递归求解与优化(附代码详解)

洛谷2789题解:直线交点数的递归求解与优化(附代码详解)

一、题目解读洛谷2789题要求计算n条直线在平面上两两相交时产生的不同交点数量。题目强调“不同”交点,需排除重复情况。解题关键在于如何高效枚举所有可能的交点组合,并避免重复计数。二、解题思路参考代码采...

牛客25461题解析:花园喷泉距离优化算法(动态规划+后缀数组解法)

牛客25461题解析:花园喷泉距离优化算法(动态规划+后缀数组解法)

一、题目解读牛客25461题要求计算一个花园中n朵花到两个喷泉的最小距离平方和。用户需输入喷泉坐标(x1,y1)和(x2,y2),以及n朵花的坐标(x,y),通过合理分配每朵花到两个喷泉的距离,使总距...

2022 CSP-J 上升点序(洛谷P8816)解题报告:动态规划求解最长上升序列

2022 CSP-J 上升点序(洛谷P8816)解题报告:动态规划求解最长上升序列

一、题目解读2022年CSP-J题目“上升点序”(洛谷P8816)要求给定一个平面点集,每个点的坐标(x,y)均为整数。题目需要构造一个最长的上升序列,序列中相邻点的坐标满足x和y均严格递增。允许使用...

牛客网288555题解题指南:动态规划求解小红的暑假(附代码解析)

牛客网288555题解题指南:动态规划求解小红的暑假(附代码解析)

一、题目解读牛客网288555题要求解决一个组合数学问题:有三位朋友,每天需邀请其中一位参加聚会,但不能连续两天邀请同一位朋友。给定天数n,求满足条件的不同邀请方案总数。题目考察动态规划、状态转移及组...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。