LeetCode429周赛T4
最小化二进制字符串中最长相同子字符串的长度
在处理二进制字符串问题时,优化字符串结构以满足特定条件是一项常见的挑战。本文将探讨一个具体的问题:给定一个长度为 n
的二进制字符串 s
和一个整数 numOps
,通过最多 numOps
次位翻转操作,最小化字符串 s
中最长相同子字符串的长度。
问题描述
输入
- 字符串
s
:长度为n
的二进制字符串,仅由字符'0'
和'1'
组成。 - 整数
numOps
:允许执行的最大位翻转次数。
操作
在每次操作中,你可以选择任意一个下标 i
(0 <= i < n
),并翻转 s[i]
的值:
- 如果
s[i] == '1'
,则将其改为'0'
。 - 如果
s[i] == '0'
,则将其改为'1'
。
目标
通过最多 numOps
次操作,最小化字符串 s
中最长相同子字符串的长度。相同子字符串指的是子字符串中的所有字符都相同。
示例
示例 1
- 输入:
s = "000001"
,numOps = 1
- 输出:
2
- 解释:
- 将
s[2]
改为'1'
,得到s = "001001"
。 - 此时,最长的相同子字符串为
s[0..1]
和s[3..4]
,长度均为2
。
- 将
示例 2
- 输入:
s = "0000"
,numOps = 2
- 输出:
1
- 解释:
- 将
s[0]
和s[2]
改为'1'
,得到s = "1010"
。 - 所有相同子字符串的长度均为
1
。
- 将
示例 3
- 输入:
s = "0101"
,numOps = 0
- 输出:
1
- 解释:
- 不进行任何操作,字符串中所有相同子字符串的长度均为
1
。
- 不进行任何操作,字符串中所有相同子字符串的长度均为
本题重要概念
段的分割
在优化字符串以最小化最长相同子字符串长度的过程中,段的分割是关键步骤。这里的“分割”不仅仅是简单地将字符串切开,而是通过翻转特定位置的字符,将一个连续的相同字符段划分为多个较小的段,从而减少最长段的长度。
具体来说,假设有一个长度为 k 的连续相同字符段。通过翻转其中的若干字符,可以将这个段分割成 seg + 1 个子段。每次翻转一个字符,相当于在该位置引入一个不同字符,从而将原来的段划分为两个部分。例如:
示例:考虑一个包含 10 个连续 ‘0’ 的字符串 “0000000000”。
如果我们翻转其中的 2 个 ‘0’ 为 ‘1’,例如将索引 3 和 7 位置的 ‘0’ 翻转为 ‘1’,字符串变为 “0001000100”。
这样,原本的 10 个 ‘0’ 被分割成了三个子段:“000”, “000”, 和 “00”。
经过这次分割,最长的 ‘0’ 子段长度由 10 减少到了 3。
通过这种方式,每次翻转操作都能有效地将一个较长的段分割成多个较短的段,从而逐步减少整个字符串中最长相同子字符串的长度。具体来说,一个长度为 k 的段,经过 seg 次分割后,每个子段的最大长度大约为 ceil(k / (seg + 1))。
解题思路
要最小化字符串中最长相同子字符串的长度,可以通过以下步骤进行优化:
-
检查是否可以分割为长度为1的子串:
- 首先判断是否可以通过最多
numOps
次翻转操作将字符串s
转换为一个交替字符串,如"1010"
或"0101"
。 - 如果可以实现,则返回
1
,因为此时最长的相同子字符串长度为1
。
- 首先判断是否可以通过最多
-
处理长度为2的字符串:
- 对于长度为2的字符串,如果无法转换为交替字符串(即已经是
"00"
或"11"
),则不需要进一步分割。 - 因为分割长度为2的字符串会影响前后部分,且前面已经判断了是否可以得到长度为1的结果。
- 如果当前最长的子串长度已经是2,则答案必定是2。
- 对于长度为2的字符串,如果无法转换为交替字符串(即已经是
-
分段统计:
- 将字符串
s
分割成连续的相同字符段。例如,"000001"
可以分为["00000", "1"]
。
- 将字符串
-
优先处理最长段:
- 通过优先将最长的相同字符段进行分割,可以有效减少最长段的长度。具体而言,使用优先队列(堆)来不断选择当前最长的段进行分割。
-
段的分割:
- 每次分割一个段,将其分成更多的小段,从而降低该段的最大长度。
- 假设一个段的长度为
k
,通过翻转特定位置的字符,将这个段分割seg次,成seg + 1
个子段,每段的最大长度约为ceil(k / (seg + 1))
。
-
迭代操作:
- 重复上述过程,直到用完所有的操作次数
numOps
或者无法进一步优化。
- 重复上述过程,直到用完所有的操作次数
-
最终结果:
- 操作完成后,堆顶元素即为当前最长相同子字符串的长度。
代码实现
from heapq import heapify, heapreplace
from itertools import groupbyclass Solution:def minLength(self, s: str, numOps: int) -> int:n = len(s)# 首先检查是否可以通过 numOps 次翻转将字符串转为交替字符串# 交替字符串有两种可能:"0101..." 或 "1010..."# 计算将 s 转换为这两种模式所需的翻转次数ops_to_alternate_0 = sum(1 for i, c in enumerate(s) if c != ('0' if i % 2 == 0 else '1'))ops_to_alternate_1 = sum(1 for i, c in enumerate(s) if c != ('1' if i % 2 == 0 else '0'))min_ops_to_alternate = min(ops_to_alternate_0, ops_to_alternate_1)# 如果可以通过翻转操作将字符串转为交替字符串,则最长相同子字符串长度为1if min_ops_to_alternate <= numOps:return 1# 特殊处理长度为2的字符串if n == 2:# 如果已经是交替字符串,返回1if s[0] != s[1]:return 1# 否则,需要至少1次操作将其分割为交替elif numOps >= 1:return 1else:return 2 # 无法分割,最长相同子字符串长度为2# 分组统计连续相同字符的段groups = [len(list(group)) for _, group in groupby(s)]# 如果分组中所有段的长度均为1,则已经是交替字符串if all(g == 1 for g in groups):return 1# 初始化堆,存储每个段的最大长度及分割次数# 堆中存储 (-最大长度, 原始长度, 分割次数)heap = [(-g, g, 1) for g in groups]heapify(heap)for _ in range(numOps):max_seg, k, seg = heap[0]# 如果当前最长段已经不能进一步分割if max_seg == -2:return 2# 将当前最长段进行一次分割# 新的最大长度为 ceil(k / (seg + 1)),这里用整除代替ceil# 因为 k // (seg + 1) 已经是向下取整,取负数用于最大堆new_max = -(k // (seg + 1))# 更新分割次数new_seg = seg + 1# 替换堆顶元素heapreplace(heap, (new_max, k, new_seg))# 返回操作后的最长相同子字符串长度return -heap[0][0]
相关文章:

LeetCode429周赛T4
最小化二进制字符串中最长相同子字符串的长度 在处理二进制字符串问题时,优化字符串结构以满足特定条件是一项常见的挑战。本文将探讨一个具体的问题:给定一个长度为 n 的二进制字符串 s 和一个整数 numOps,通过最多 numOps 次位翻转操作&am…...

详解MySQL在Windows上的安装
目录 查看电脑上是否安装了MySQL 下载安装MySQL 打开MySQL官网,找到DOWNLOADS 然后往下翻,找到MySQL Community(GPL) Downloads>> 然后找到MySQL Community Server 然后下载,选择No thanks,just start my download. 然后双击进行…...

【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
本教程的知识点为:操作系统 1. 常见的操作系统 4. 小结 ls命令选项 2. 小结 mkdir和rm命令选项 1. mkdir命令选项 压缩和解压缩命令 1. 压缩格式的介绍 2. tar命令及选项的使用 3. zip和unzip命令及选项的使用 4. 小结 编辑器 vim 1. vim 的介绍 2. vim 的工作模式 …...

软件测试面试题和简历模板(面试前准备篇)
一、问题预测 1、让简单介绍下自己(这个不用说了每次面试开场) 面试官,你好,我叫xxx,xx年本科毕业,从事软件测试将近3年的时间。在此期间做过一些项目也积累过一些经验,能够独立地完成软件测试…...

Linux 基本使用和程序部署
1. Linux 环境搭建 1.1 环境搭建方式 主要有 4 种: 直接安装在物理机上。但是Linux桌面使用起来非常不友好,所以不建议。[不推荐]。使用虚拟机软件,将Linux搭建在虚拟机上。但是由于当前的虚拟机软件(如VMWare之类的)存在一些bugÿ…...

uniapp微信小程序,使用fastadmin完成一个一键获取微信手机号的功能
前端部分 点击按钮,获取手机号 <button open-type"getPhoneNumber" getphonenumber"bindGetPhoneNumber" hover-class"none"class"btn-purity">一键获取</button> 传入openid和code bindGetPhoneNumber(e) …...

CSS系列(27)- 图形与滤镜详解
前端技术探索系列:CSS 图形与滤镜详解 🎨 致读者:探索CSS的艺术表现力 👋 前端开发者们, 今天我们将深入探讨 CSS 图形和滤镜效果,学习如何创建引人注目的视觉效果。 基础图形 🚀 几何形状…...

Docker 技术系列之安装多版本Mysql5.6和Mysql5.7
image 大家好,后面的就不是关于MAC专有的内容,基本是跟Java环境,基础技术方面有关。所以这个教程对于在linux系统还是macOS都是通用的,不用担心。 上一篇,我们安装好对应的Docker之后,感受到了它的便利。接…...

理解并使用Linux 内核中的 Tracepoint
理解并使用Linux 内核中的 Tracepoint 1. 引言 1.1 为什么需要 Tracepoint? 在内核调试与性能分析中,传统的 printk 方法虽然简单直接,但存在几个显著的局限性: 日志噪音:printk 会将所有输出无差别地记录到系统日…...

centos7中Gbase8s数据库安装,以及数据导入遇到的一系列问题
centos7中Gbase8s数据库安装,以及遇到的一系列问题 以下是我在centos7上安装gbase8s数据库遇到的一系列问题,包括数据库安装,数据导入,数据连接,不能完全作为标准,只可作为类似问题参考,有问题…...

AW36518芯片手册解读(3)
接前一篇文章:AW36518芯片手册解读(2) 二、详述 3. 功能描述 (1)上电复位 当电源电压VIN降至预定义电压VPOR(典型值为2.0V)以下时,该设备会产生复位信号以执行上电复位操作&#x…...

MySQL的REPEATABLE READ事务隔离级别
本文隔离级别: T1内读T2的update数据 首先开两个事务(左二) 事务1修改成李四,提交 事务2再读还是张三,也就是说,记录的数据从事务开始时一直到结束,读的都是同一个版本,读不到T2未提交的此条记录修改&…...

sqoop的参数有哪些?
Sqoop 是一款用于在 Hadoop 与关系型数据库之间进行数据传输的工具,它有很多参数,可分为通用参数、导入参数和导出参数等,以下是一些常见的参数介绍: 通用参数 --connect 说明:指定要连接的关系型数据库的 JDBC URL。…...

动态规划<四> 回文串问题(含对应LeetcodeOJ题)
目录 引例 其余经典OJ题 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 引例 OJ 传送门Leetcode<647>回文子串 画图分析: 使用动态规划解决 原理:能够将所有子串是否是回文的信息保存在dp表中 在使用暴力方法枚举出所有子串,是…...

跨模态知识迁移:基于预训练语言模型的时序数据建模
在NLP和CV领域,通常通过在统一的预训练模型上进行微调,能够在各自领域的下游任务中实现SOTA(最先进)的结果。然而,在时序预测领域,由于数据量相对较少,难以训练出一个统一的预训练模型来覆盖所有…...

重温设计模式--职责链模式
文章目录 职责链模式的详细介绍C 代码示例C示例代码2 职责链模式的详细介绍 定义与概念 职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它旨在将请求的发送者和多个接收者解耦,让多个对象都有机会处理请求&a…...

git冲突解决
git冲突解决 最近遇到了一次git冲突的问题 起因是因为最近公司数据推送部分重构,负责重构的同事就改动了我的一小部分推送的代码,然后等我开发完合并到远程master的时候,报了merge冲突。我对于git工具确实不是很熟练,只是学习了…...

Java学习笔记(14)--面向对象编程
面向对象基础 学习资料来自多态 - Java教程 - 廖雪峰的官方网站 目录 面向对象基础 Override 多态 举个例子 覆写Object方法 调用super final 练习 小结 Override 在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写&…...

《Swift 字面量》
《Swift 字面量》 介绍 在 Swift 编程语言中,字面量是一种表示源代码中固定值的表达方式。字面量可以直接表示数字、字符串、布尔值等基本数据类型,为编程提供了简洁和直观的方式。Swift 支持多种类型的字面量,包括整数字面量、浮点数字面量…...

数据库 SQL 常用语句全解析
数据库 SQL 常用语句全解析 在数据库领域,SQL(Structured Query Language)作为标准语言,掌控着数据的查询、插入、更新与删除等关键操作。无论是新手入门数据库,还是经验丰富的开发者日常工作,熟练掌握 SQ…...

SQLite 命令
关于《SQLite 命令》的文章,我可以为您概述一些关键点。SQLite是一个轻量级的数据库管理系统,它被广泛用于各种应用程序中。SQLite命令主要分为两类:一类是SQL命令,另一类是SQLite特定的点命令。 SQL命令:这些命令用于…...

本地如何启动casdoor
1、下载代码 GitHub - casdoor/casdoor at v1.777.0 下载对应tag的代码,我这里选择的时v1.777.0版本 通过网盘分享的文件:casdoor-1.777.0.zip 链接: https://pan.baidu.com/s/1fPNqyJYeyfZnem_LtEc0hw 提取码: avpd 2、启动后端 1、使用goland编译…...

目标检测-R-CNN
R-CNN在2014年被提出,算法流程可以概括如下: 候选区域生成:利用选择性搜索(selective search)方法找出图片中可能存在目标的候选区域(region proposal) CNN网络提取特征:对候选区域进行特征提取(可以使用AlexNet、VGG等网络) 目…...

【持续更新】Github实用命令
Intro 最近高强度使用github,遂小计于此作为备忘。 Basic github是一个代码管理软件,能够track文件变动并且管理版本,是当代coding必不可少的工具。当你安装好github在本地以后,你可以通过以下命令初始化当前文件夹(…...

docker 容器的基本使用
docker 容器 一、docker是什么? 软件的打包技术,就是将算乱的多个文件打包为一个整体,打包技术在没有docker容器之前,一直是有这种需求的,比如上节课我把我安装的虚拟机给你们打包了,前面的这种打包方式是…...

css让按钮放在最右侧
要将 el-button 按钮放在最右侧,可以使用多种方法,具体取决于使用的布局方式和样式库。以下是几种常见的解决方案: 方法 1:使用 CSS Flexbox Flexbox 是一种非常灵活的布局方式,可以轻松实现水平或垂直对齐。你可以将…...

8K+Red+Raw+ProRes422分享5个影视级视频素材网站
Hello,大家好,我是后期圈! 在视频创作中,电影级的视频素材能够为作品增添专业质感,让画面更具冲击力。无论是广告、电影短片,还是品牌宣传,高质量的视频素材都是不可或缺的资源。然而ÿ…...

Linux网络——UDP的运用
Linux网络——UDP的运用 文章目录 Linux网络——UDP的运用一、引入二、服务端实现2.1 创建socket套接字2.2 指定网络接口并bind2.3 接收数据并处理2.4 整体代码2.5 IP的绑定的细节 三、用户端实现3.1 创建套接字3.2 指定网络接口3.3 发生数据并接收3.4 绑定问题 四、代码五、UD…...

项目亮点案例
其实对我来说是日常操作,但是如果在面试的时候面试者能把日常的事情总结好发出来,其实足矣。 想让别人认同项目,选取的示例需要包含以下要素: 亮点项目四要素:明确的目标,问题点,解决方法和结果…...

Retrofit源码分析:动态代理获取Api接口实例,解析注解生成request,线程切换
目录 一,Retrofit的基本使用 1.定义api接口 2.创建Retrofit实例 3.获取api接口实例发起请求 二,静态代理和动态代理 1,静态代理 2,动态代理 三,动态代理获取Api接口实例 四,解析接口方法注解&…...