Maximum Difference Between Even and Odd Frequency II

Maximum Difference Between Even and Odd Frequency II

You are given a string s and an integer k. Your task is to find the maximum difference between the frequency of two characters, freq[a] - freq[b], in a substring subs of s, such that:

  • subs has a size of at least k.
  • Character a has an odd frequency in subs.
  • Character b has an even frequency in subs.

Return the maximum difference.

Note that subs can contain more than 2 distinct characters.

 

Example 1:

Input: s = "12233", k = 4

Output: -1

Explanation:

For the substring "12233", the frequency of '1' is 1 and the frequency of '3' is 2. The difference is 1 - 2 = -1.

Example 2:

Input: s = "1122211", k = 3

Output: 1

Explanation:

For the substring "11222", the frequency of '2' is 3 and the frequency of '1' is 2. The difference is 3 - 2 = 1.

Example 3:

Input: s = "110", k = 3

Output: -1

 

Constraints:

  • 3 <= s.length <= 3 * 104
  • s consists only of digits '0' to '4'.
  • The input is generated that at least one substring has a character with an even frequency and a character with an odd frequency.
  • 1 <= k <= s.length

 

解题思路

  一开始想的做法太复杂了,赛时没做出来,赛后磨了快一个小时才过。

  关键是要想到,对于任意一段子串,必然会选出一个出现频率是奇数的数字 a,以及出现频率是偶数的数字 b。观察到数字范围非常小只有 04,意味着我们可以暴力枚举 ab。对于 [l,r] 的子串,答案为 sarsal1(sbrsbl1),其中 sai=j=1i[sj=a]sbi=j=1i[sj=b]。该式子可以等价为 sarsbr+sbl1sal1,因此我们可以枚举右端点 r,然后快速得到满足条件的左端点 l 关于 sbl1sal1 的最大值。

  另外在 [l,r] 中由于 a 要出现奇数次,b 要出现偶数次,因此 sal1 的奇偶性要与 sar 不同,sbl1 的奇偶性要与 sbr 相同。为此定义 g(0/1,0/1) 表示在满足条件的 l 中,sal1 是奇/偶,sbl1 是奇/偶时,关于 sbl1sal1 的最大值。

  下面考虑 l 应该满足什么条件。首先由于子串的长度至少为 k,因此有 rl+1k。另外由于区间内必须要出现 ab,因此有 sarsal1>0sbrsbl1>0。注意到 sarsbr 随着 r 递增而递增,因此满足条件的 l 实际上是一个前缀,且随着 r 递增而往右扩展。因此我们可以用一个指针来维护这个前缀的右端点,同时维护这个前缀中的 g(0/1,0/1)

  因此对于右端点为 r 且选择 ab 分别作为出现奇数和偶数的数字的子串中,最大的答案是 sarsbr+g(¬(sarmod2),sbrmod2)

  AC 代码如下,时间复杂度为 O(42n)

class Solution {
public:
    int maxDifference(string s, int k) {
        int n = s.size();
        int ret = -0x3f3f3f3f;
        for (int a = 0; a <= 4; a++) {
            for (int b = 0; b <= 4; b++) {
                vector<int> s1(n + 1), s2(n + 1);
                for (int i = 1; i <= n; i++) {
                    s1[i] = s1[i - 1] + (s[i - 1] - '0' == a);
                    s2[i] = s2[i - 1] + (s[i - 1] - '0' == b);
                }
                vector<vector<int>> g(2, vector<int>(2, -0x3f3f3f3f));
                for (int i = k, j = 0; i <= n; i++) {
                    while (i - j >= k && s1[i] > s1[j] && s2[i] > s2[j]) {
                        g[s1[j] & 1][s2[j] & 1] = max(g[s1[j] & 1][s2[j] & 1], s2[j] - s1[j]);
                        j++;
                    }
                    ret = max(ret, s1[i] - s2[i] + g[~s1[i] & 1][s2[i] & 1]);
                }
            }
        }
        return ret;
    }
};

 

参考资料

  子集状压 DP【力扣周赛 435】:https://www.bilibili.com/video/BV1D5F6eRECp/

posted @   onlyblues  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2023-02-02 Minimum Cost to Make Array Equal
2023-02-02 Count Increasing Quadruplets
2023-02-02 方程的解
Web Analytics
点击右上角即可分享
微信分享提示