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

news2025/3/17 7:11:29

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

力扣题目链接:https://leetcode.cn/problems/substring-with-largest-variance/

字符串的 波动 定义为子字符串中出现次数 最多 的字符次数与出现次数 最少 的字符次数之差。

给你一个字符串 s ,它只包含小写英文字母。请你返回 s 里所有 子字符串的 最大波动 值。

子字符串 是一个字符串的一段连续字符序列。

 

示例 1:

输入:s = "aababbb"
输出:3
解释:
所有可能的波动值和它们对应的子字符串如以下所示:
- 波动值为 0 的子字符串:"a" ,"aa" ,"ab" ,"abab" ,"aababb" ,"ba" ,"b" ,"bb" 和 "bbb" 。
- 波动值为 1 的子字符串:"aab" ,"aba" ,"abb" ,"aabab" ,"ababb" ,"aababbb" 和 "bab" 。
- 波动值为 2 的子字符串:"aaba" ,"ababbb" ,"abbb" 和 "babb" 。
- 波动值为 3 的子字符串 "babbb" 。
所以,最大可能波动值为 3 。

示例 2:

输入:s = "abcde"
输出:0
解释:
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++
/*
 * @Author: LetMeFly
 * @Date: 2025-03-16 10:43:25
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-03-16 11:03:26
 */
#ifdef _WIN32
#include "_[1,2]toVector.h"
#endif

#ifdef FirstTry  // WA - 例如baa,一个变量会导致不选b,而只有aa虽然cnt比较大但不一定最优
class Solution {
public:
    int largestVariance(string s) {
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            char a = i + 'a';
            for (int j = 0; j < 26; j++) {
                char b = j + 'a';
                int cnt = 0;
                bool hasB = false;
                for (char c : s) {
                    if (c == a) {
                        cnt++;
                    } else if (c == b) {
                        // cnt = max(cnt - 1, 0);
                        if (cnt - 1 >= 0) {
                            cnt--;
                            hasB = true;
                        } else {
                            cnt = 0;
                            hasB = false;
                        }
                    }
                    if (hasB) {
                        ans = max(ans, cnt);
                    }
                }
                // printf("a = %c, b = %c, ans = %d\n", a, b, ans);
            }
        }
        return ans;
    }
};
#else  // FirstTry
// SecondTry
class Solution {
public:
    int largestVariance(string s) {
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            char a = i + 'a';
            for (int j = 0; j < 26; j++) {
                char b = j + 'a';
                int mayNoB = 0, hasB = -10000000;
                for (char c : s) {
                    if (c == a) {
                        mayNoB = max(mayNoB + 1, 1);
                        hasB++;
                    } else if (c == b) {
                        mayNoB = max(mayNoB - 1, -1);
                        hasB = mayNoB;
                    }
                    ans = max(ans, hasB);
                }
            }
        }
        return ans;
    }
};
#endif  // FirstTry
Python
'''
Author: LetMeFly
Date: 2025-03-16 11:06:25
LastEditors: LetMeFly.xyz
LastEditTime: 2025-03-16 11:09:05
'''
class Solution:
    def largestVariance(self, s: str) -> int:
        ans = 0
        for i in range(26):
            a = chr(i + ord('a'))
            for j in range(26):
                b = chr(j + ord('a'))
                mayNoB, hasB = 0, -100000
                for c in s:
                    if c == a:
                        mayNoB = max(mayNoB + 1, 1)
                        hasB += 1
                    elif c == b:
                        mayNoB = max(mayNoB - 1, -1)
                        hasB = mayNoB
                    ans = max(ans, hasB)
        return ans
Java
/*
 * @Author: LetMeFly
 * @Date: 2025-03-16 11:09:39
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-03-16 11:13:27
 */
class Solution {
    public int largestVariance(String s) {
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            char a = (char)(i + 'a');
            for (int j = 0; j < 26; j++) {
                char b = (char)(j + 'a');
                int mayNoB = 0, hasB = -10000000;
                for (char c : s.toCharArray()) {
                    if (c == a) {
                        mayNoB = Math.max(mayNoB + 1, 1);
                        hasB++;
                    } else if (c == b) {
                        mayNoB = Math.max(mayNoB - 1, -1);
                        hasB = mayNoB;
                    }
                    ans = Math.max(ans, hasB);
                }
            }
        }
        return ans;
    }
}
Go
/*
 * @Author: LetMeFly
 * @Date: 2025-03-16 11:14:38
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-03-16 11:18:01
 */
package main

func largestVariance(s string) (ans int) {
    for i := byte(0); i < 26; i++ {
        a := i + 'a'
        for j := byte(0); j < 26; j++ {
            b := j + 'a'
            mayNoB, hasB := 0, -10000000
            for _, c := range s {
                if byte(c) == a {
                    mayNoB = max(mayNoB + 1, 1)
                    hasB++
                } else if byte(c) == b {
                    mayNoB = max(mayNoB - 1, -1)
                    hasB = mayNoB
                }
                ans = max(ans, hasB)
            }
        }
    }
    return
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2316478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

火语言RPA--列表项内容设置

【组件功能】&#xff1a;设置列表项内容 配置预览 配置说明 索引项位置支持T或# 列表对象待修改内容的索引位置。 内容值 支持T或# 默认FLOW输入项 修改的内容值。 示例 对象修改 描述 列表对象索引为0的数据修改为A字符串&#xff0c;并打印修改结果。 配置 输出结…

1.Qt SDK 的下载和安装

1Qt 下载官⽹&#xff1a; http://download.qt.io/archive/qt/ 2版本自行选择 3下载对应版本的.exe文件 4下载包下载完成 5双击.exe文件&#xff0c;默认下一步&#xff0c;要注册一个qt的账户 6记住程序安装的位置&#xff0c;后面要配置环境变量 7勾3个&#xff08;组件自行…

嵌入式系统中的Board Support Package (BSP)详解:以Xilinx Zynq为例

嵌入式系统中的Board Support Package (BSP)详解&#xff1a;以Xilinx Zynq为例 引言 在嵌入式系统开发中&#xff0c;硬件与软件的无缝集成至关重要。Board Support Package (BSP) 作为连接硬件和操作系统的桥梁&#xff0c;在这一过程中扮演着核心角色。本文将深入探讨BSP的…

Vue 生命周期详解:从创建到销毁的全过程

Vue.js 是一个流行的前端框架&#xff0c;它通过组件化的方式帮助开发者构建用户界面。在 Vue 中&#xff0c;每个组件实例都有其生命周期&#xff0c;从创建、挂载、更新到销毁&#xff0c;Vue 提供了一系列的生命周期钩子函数&#xff0c;允许我们在组件的不同阶段执行自定义…

计算机基础:二进制基础12,十进制数转换为十六进制

专栏导航 本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏&#xff0c;故划分为两个专栏导航。读者可以自行选择前往哪个专栏。 &#xff08;一&#xff09;WIn32 专栏导航 上一篇&#xff1a;计算机基础&#xff1a;二进制基础11&#xff0c;十六进制的位基…

SpringCloud系列教程(十四):Sentinel持久化

Sentinel之前已经搭建和应用成功了&#xff0c;但是它有一个很大的缺点就是官方没有提供持久化的方案&#xff0c;从项目源码上看感觉这款工具也没有完成的太好&#xff0c;所以需要我们去对它进行二次开发。要补充的功能大概如下&#xff1a; 1、将Sentinel接入nacos中&#…

Slider,InputField,Scroll View,Scrollbar及Layout组件

Slider组件 Fill Rect:填充滑动条选中区域的背景图部分 Handle Rect:滑动条的球 Direction:滑动条的滑动方向 Min Value:起始位置的数值&#xff08;浮点数&#xff09; Max Value:结束位置的数值&#xff08;浮点数&#xff09; Whole Numbers:必须为整数&#xff08;布尔…

ollama注册自定义模型(GGUF格式)

文章目录 ollama注册自定义模型&#xff08;GGUF格式&#xff09;下载模型注册模型(GGUF格式) ollama注册自定义模型&#xff08;GGUF格式&#xff09; 需要全程开启ollama nohup ollama serve > ollama.log 2>&1 &需要注意&#xff0c;尽管手动下载的GGUF格式模…

HarmonyOS NEXT 声明式UI语法学习笔记-创建自定义组件

基础语法概述 ArkTS的基本组成 装饰器&#xff1a;用于装饰类、结构、方法以及变量&#xff0c;并赋予其特殊含义。如上图都是装饰器&#xff0c;Component表示自定义组件&#xff0c;Entry表示表示自定义组件的入口组件&#xff0c;State表示组件中的状态变量&#xff0c;当状…

97.HarmonyOS NEXT跑马灯组件教程:基础概念与架构设计

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT跑马灯组件教程&#xff1a;基础概念与架构设计 1. 跑马灯组件概述 跑马灯&#xff08;Marquee&#xff09;是一种常见的UI组件&a…

81.HarmonyOS NEXT 状态管理与响应式编程:@Observed深度解析

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT 状态管理与响应式编程&#xff1a;Observed深度解析 文章目录 HarmonyOS NEXT 状态管理与响应式编程&#xff1a;Observed深度解析…

股指期货有卖不出去的时候吗?

在股指期货的交易世界里&#xff0c;很多人都有这样的疑问&#xff1a;股指期货会不会有卖不出去的时候呢&#xff1f;答案是会的&#xff0c;下面咱们就来详细唠唠为啥会出现这种情况。 市场极端行情下难以卖出 1.跌停限制&#xff1a;股指期货和股票一样&#xff0c;也有涨…

开发、科研、日常办公工具汇总(自用,持续更新)

主要记录汇总一下自己平常会用到的网站工具&#xff0c;方便查阅。 update&#xff1a;2025/2/11&#xff08;开发网站补一下&#xff09; update&#xff1a;2025/2/21&#xff08;补充一些AI工具&#xff0c;刚好在做AI视频相关工作&#xff09; update&#xff1a;2025/3/7&…

HTML5 drag API实现列表拖拽排序

拖拽API&#xff08;Drag and Drop API&#xff09;是HTML5提供的一组功能&#xff0c;使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能&#xff0c;用户可以通过鼠标将元素拖动并放置到指定的目标区域。 事件类型 dragstart&#xff1…

改变一生的思维模型【11】升维

升维思维模型&#xff1a;突破认知局限的破局法则 一、定义与核心逻辑 升维思维是通过增加分析维度&#xff0c;将问题投射到更高认知层次寻找解决方案的思考方式。其本质是跳出原有竞争维度&#xff0c;在更广阔的空间重构游戏规则。核心逻辑在于&#xff1a;当低维战场陷入…

【动手学深度学习】#2线性神经网络

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 2.1 线性回归2.1.1 线性回归的基本元素线性模型损失函数解析解随机梯度下降 2.1.3 最大似然估计 2.2 线性回归从零开始实现2.2.1 生成数据集2.2.2 读取数…

计算机网络——NAT

一、什么是NAT&#xff1f; NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09; 是一种将 私有IP地址 与 公有IP地址 相互映射的技术&#xff0c;主要用于解决IPv4地址不足的问题。它像一名“翻译官”&#xff0c;在数据包经过路由器或防火墙时…

同一子网通信

添加交换机后的通信流程 1. 同一子网内&#xff08;使用交换机&#xff09; 判断是否在同一子网&#xff1a; 主机A通过子网掩码判断主机B的IP地址是否属于同一子网。若在同一子网&#xff0c;主机A需要通过ARP获取主机B的MAC地址。 ARP请求&#xff08;广播&#xff09;&…

IntelliJ IDEA 快捷键系列:重命名快捷键详解

目录 引言一、默认重命名快捷键1. Windows 系统‌2. Mac 系统‌ 二、操作步骤与技巧1. 精准选择重命名范围‌2. 智能过滤无关内容‌ 三、总结 引言 在代码重构中&#xff0c;‌重命名变量、类、方法‌ 是最常用的操作之一。正确使用快捷键可以极大提升开发效率。本文针对 ‌Ma…

零基础掌握分布式ID生成:从理论到实战的完整指南 [特殊字符]

一、为什么需要分布式ID&#xff1f; &#x1f914; 在单机系统中&#xff0c;使用数据库自增ID就能满足需求。但在分布式系统中&#xff0c;多个服务节点同时生成ID时会出现以下问题&#xff1a; ID冲突&#xff1a;不同节点生成相同ID 扩展困难&#xff1a;数据库自增ID无法…