LeetCode 2272.最大波动的子字符串:转为多次的最大子数组和 - 一步步思考 ...

打印 上一主题 下一主题

主题 1664|帖子 1664|积分 4992

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
【LetMeFly】2272.最大波动的子字符串:转为多次的最大子数组和 - 一步步思考推导

力扣题目链接:https://leetcode.cn/problems/substring-with-largest-variance/
字符串的 波动 定义为子字符串中出现次数 最多 的字符次数与出现次数 最少 的字符次数之差。
给你一个字符串 s ,它只包含小写英文字母。请你返回 s 里所有 子字符串的 最大波动 值。
子字符串 是一个字符串的一段一连字符序列。
 
示例 1:
  1. <b>输入:</b>s = "aababbb"
  2. <b>输出:</b>3
  3. <strong>解释:</strong>
  4. 所有可能的波动值和它们对应的子字符串如以下所示:
  5. - 波动值为 0 的子字符串:"a" ,"aa" ,"ab" ,"abab" ,"aababb" ,"ba" ,"b" ,"bb" 和 "bbb" 。
  6. - 波动值为 1 的子字符串:"aab" ,"aba" ,"abb" ,"aabab" ,"ababb" ,"aababbb" 和 "bab" 。
  7. - 波动值为 2 的子字符串:"aaba" ,"ababbb" ,"abbb" 和 "babb" 。
  8. - 波动值为 3 的子字符串 "babbb" 。
  9. 所以,最大可能波动值为 3 。
复制代码
示例 2:
  1. <b>输入:</b>s = "abcde"
  2. <b>输出:</b>0
  3. <strong>解释:</strong>
  4. s 中没有字母出现超过 1 次,所以 s 中每个子字符串的波动值都是 0 。
复制代码
 
提示:


  • 1 <= s.length <= 104
  • s  只包含小写英文字母。
解题方法:动态规划

做本题之前推荐先做一下53. 最大子数组和:
   一个数组中元素有正有负,怎样求其非空子数组和的最大值呢?
  遍历数组并使用一个变量                                        c                            n                            t                                  cnt                     cnt统计即可。
  对于当前元素a,可以选择在前面子数组的底子上加上这个元素(                                        c                            n                            t                            +                            a                                  cnt + a                     cnt+a),也可以选择丢弃前面子数组而从这个元素重新开始(                                        a                                  a                     a)。
  因此有状态转移方程                                        c                            n                            t                            =                            max                            ⁡                            (                            c                            n                            t                            +                            a                            ,                            a                            )                                  cnt = \max(cnt + a, a)                     cnt=max(cnt+a,a)。
  本题怎样转为多次的“最大子数组”呢?本题的子数组只需要思量出现次数最多和出现次数最少的两个元素,因此我直接两层循环枚举所有的“最多元素a”和“最少元素b”不就行了吗?
   假设出现次数最多的元素是a,出现次数最少的元素是b。因为我们终极求的是                                        c                            o                            u                            n                            t                            (                            a                            )                            −                            c                            o                            u                            n                            t                            (                            b                            )                                  count(a) - count(b)                     count(a)−count(b),所以我们可以将a赋值为1,将b赋值为-1,其他元素直接无视(或赋值为0)。
  之后按照“最大子数组和”的方式求解,是不是就可以了?
  不可以,因为“最多次数的a减去最少次数的b”的条件是“子数组中出现了b”。若子数组中全是a,那么出现次数最少的元素并非0次,而是同样为a次。也就是说,我们还需要想办法包管子数组中出现了b。
   “最大子数组和”我们使用了一个变量cnt,本题我们可以使用两个变量                                        m                            a                            y                            N                            o                            B                                  mayNoB                     mayNoB和                                        h                            a                            s                            B                                  hasB                     hasB,分别表现子数组中可能不包含b和子数组中肯定包含b时的“最大波动”。
  因为mayNoB代表的子数组可以出现B也可以不出现B,所以mayNoB就和“最大子数组和”一样,无脑                                        m                            a                            y                            N                            o                            B                            =                            max                            ⁡                            (                            m                            a                            y                            N                            o                            B                            +                            t                            ,                            t                            )                                  mayNoB = \max(mayNoB + t, t)                     mayNoB=max(mayNoB+t,t)即可(                                        t                                  t                     t是字符的映射值                                        1                                  1                     1大概                                        −                            1                                  -1                     −1大概                                        0                                  0                     0)。
  但是hasB就比较有意思了,它要求子数组中必须有b,怎么办呢?也很好说,把hasB的初始值定义为“无穷小”就好了。
  

  • 若当前元素为b,则                                             h                               a                               s                               B                               =                               m                               a                               y                               N                               o                               B                                      hasB = mayNoB                        hasB=mayNoB,因为                                             m                               a                               y                               N                               o                               B                                      mayNoB                        mayNoB一旦包含当前元素b就肯定                                             h                               a                               s                               B                                      hasB                        hasB了(其实是                                             h                               a                               s                               B                               =                               m                               a                               x                               (                               h                               a                               s                               B                               ,                               m                               a                               y                               N                               o                               B                               )                                      hasB = max(hasB, mayNoB)                        hasB=max(hasB,mayNoB),但由于“可能不包含b”肯定不小于“必须包含b”,所以可以直接简写为                                             h                               a                               s                               B                               =                               m                               a                               y                               N                               o                               B                                      hasB=mayNoB                        hasB=mayNoB)
  • 若当前元素为a,则                                             h                               a                               s                               B                               +                               =                               1                                      hasB += 1                        hasB+=1(若从未出现过元素b,则hasB即使加一也还是无穷小,不影响后续答案的更新)
  更新答案                                        a                            n                            s                            =                            m                            a                            x                            (                            a                            n                            s                            ,                            h                            a                            s                            B                            )                                  ans = max(ans, hasB)                     ans=max(ans,hasB)
  

  • 时间复杂度                                        O                            (                            l                            e                            n                            (                            s                            )                            ×                                       C                               2                                      )                                  O(len(s)\times C^2)                     O(len(s)×C2),此中                                        C                            =                            26                                  C=26                     C=26
  • 空间复杂度                                        O                            (                            1                            )                                  O(1)                     O(1)
AC代码

C++

  1. /*
  2. * @Author: LetMeFly
  3. * @Date: 2025-03-16 10:43:25
  4. * @LastEditors: LetMeFly.xyz
  5. * @LastEditTime: 2025-03-16 11:03:26
  6. */
  7. #ifdef _WIN32
  8. #include "_[1,2]toVector.h"
  9. #endif
  10. #ifdef FirstTry  // WA - 例如baa,一个变量会导致不选b,而只有aa虽然cnt比较大但不一定最优
  11. class Solution {
  12. public:
  13.     int largestVariance(string s) {
  14.         int ans = 0;
  15.         for (int i = 0; i < 26; i++) {
  16.             char a = i + 'a';
  17.             for (int j = 0; j < 26; j++) {
  18.                 char b = j + 'a';
  19.                 int cnt = 0;
  20.                 bool hasB = false;
  21.                 for (char c : s) {
  22.                     if (c == a) {
  23.                         cnt++;
  24.                     } else if (c == b) {
  25.                         // cnt = max(cnt - 1, 0);
  26.                         if (cnt - 1 >= 0) {
  27.                             cnt--;
  28.                             hasB = true;
  29.                         } else {
  30.                             cnt = 0;
  31.                             hasB = false;
  32.                         }
  33.                     }
  34.                     if (hasB) {
  35.                         ans = max(ans, cnt);
  36.                     }
  37.                 }
  38.                 // printf("a = %c, b = %c, ans = %d\n", a, b, ans);
  39.             }
  40.         }
  41.         return ans;
  42.     }
  43. };
  44. #else  // FirstTry
  45. // SecondTry
  46. class Solution {
  47. public:
  48.     int largestVariance(string s) {
  49.         int ans = 0;
  50.         for (int i = 0; i < 26; i++) {
  51.             char a = i + 'a';
  52.             for (int j = 0; j < 26; j++) {
  53.                 char b = j + 'a';
  54.                 int mayNoB = 0, hasB = -10000000;
  55.                 for (char c : s) {
  56.                     if (c == a) {
  57.                         mayNoB = max(mayNoB + 1, 1);
  58.                         hasB++;
  59.                     } else if (c == b) {
  60.                         mayNoB = max(mayNoB - 1, -1);
  61.                         hasB = mayNoB;
  62.                     }
  63.                     ans = max(ans, hasB);
  64.                 }
  65.             }
  66.         }
  67.         return ans;
  68.     }
  69. };
  70. #endif  // FirstTry
复制代码
Python

  1. '''
  2. Author: LetMeFly
  3. Date: 2025-03-16 11:06:25
  4. LastEditors: LetMeFly.xyz
  5. LastEditTime: 2025-03-16 11:09:05
  6. '''
  7. class Solution:
  8.     def largestVariance(self, s: str) -> int:
  9.         ans = 0
  10.         for i in range(26):
  11.             a = chr(i + ord('a'))
  12.             for j in range(26):
  13.                 b = chr(j + ord('a'))
  14.                 mayNoB, hasB = 0, -100000
  15.                 for c in s:
  16.                     if c == a:
  17.                         mayNoB = max(mayNoB + 1, 1)
  18.                         hasB += 1
  19.                     elif c == b:
  20.                         mayNoB = max(mayNoB - 1, -1)
  21.                         hasB = mayNoB
  22.                     ans = max(ans, hasB)
  23.         return ans
复制代码
Java

  1. /*
  2. * @Author: LetMeFly
  3. * @Date: 2025-03-16 11:09:39
  4. * @LastEditors: LetMeFly.xyz
  5. * @LastEditTime: 2025-03-16 11:13:27
  6. */
  7. class Solution {
  8.     public int largestVariance(String s) {
  9.         int ans = 0;
  10.         for (int i = 0; i < 26; i++) {
  11.             char a = (char)(i + 'a');
  12.             for (int j = 0; j < 26; j++) {
  13.                 char b = (char)(j + 'a');
  14.                 int mayNoB = 0, hasB = -10000000;
  15.                 for (char c : s.toCharArray()) {
  16.                     if (c == a) {
  17.                         mayNoB = Math.max(mayNoB + 1, 1);
  18.                         hasB++;
  19.                     } else if (c == b) {
  20.                         mayNoB = Math.max(mayNoB - 1, -1);
  21.                         hasB = mayNoB;
  22.                     }
  23.                     ans = Math.max(ans, hasB);
  24.                 }
  25.             }
  26.         }
  27.         return ans;
  28.     }
  29. }
复制代码
Go

  1. /*
  2. * @Author: LetMeFly
  3. * @Date: 2025-03-16 11:14:38
  4. * @LastEditors: LetMeFly.xyz
  5. * @LastEditTime: 2025-03-16 11:18:01
  6. */
  7. package main
  8. func largestVariance(s string) (ans int) {
  9.     for i := byte(0); i < 26; i++ {
  10.         a := i + 'a'
  11.         for j := byte(0); j < 26; j++ {
  12.             b := j + 'a'
  13.             mayNoB, hasB := 0, -10000000
  14.             for _, c := range s {
  15.                 if byte(c) == a {
  16.                     mayNoB = max(mayNoB + 1, 1)
  17.                     hasB++
  18.                 } else if byte(c) == b {
  19.                     mayNoB = max(mayNoB - 1, -1)
  20.                     hasB = mayNoB
  21.                 }
  22.                 ans = max(ans, hasB)
  23.             }
  24.         }
  25.     }
  26.     return
  27. }
复制代码
  同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
  千篇源码题解已开源

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表