当前位置: 首页 > article >正文

第六天——贪心算法——字符串分隔

1. 题目

给定一个字符串 s,我们需要将其划分为尽可能多的部分,使得同一字母最多出现在一个部分中。

例如:字符串 "ababcc" 可以划分为 ["abab", "cc"],但要避免 ["aba", "bcc"] 或 ["ab", "ab", "cc"] 这样的划分方式(因为它们包含了同一个字母出现在多个部分的情况)。

注意:划分后的部分顺序必须与原字符串顺序一致,所有部分拼接起来仍然等于 s。
返回:这些部分的长度组成的列表。

2. 分析

这道题目是一个典型的贪心算法问题,解法类似于区间合并问题

关键思路

  1. 记录每个字母的最远出现位置
    • 用 last_occurrence 字典保存每个字符在字符串 s 中最后出现的位置(即最右边的索引),这样可以确定该字符所属的最小子串范围。
  2. 滑动窗口遍历,确定当前部分的结束点
    • 用 start 和 end 表示当前部分的起始和结束位置。
    • 遍历字符串时,不断更新 end,使其变为已遍历字符的最远出现位置。
    • 当 i == end 时,说明当前部分可以切分,记录长度,并更新 start 到 end + 1

3. 完整代码

def partition_labels(s):last_occurrence = {char: idx for idx, char in enumerate(s)}  # 记录每个字母的最后出现位置start = end = 0result = []for i, char in enumerate(s):end = max(end, last_occurrence[char])  # 更新当前部分的结束点if i == end:  # 找到一个符合条件的部分result.append(end - start + 1)start = end + 1  # 更新下一部分的起始点return result
print(partition_labels("ababcc"))

示例分析:s = "ababcc"

  1. last_occurrence = {'a': 2, 'b': 3, 'c': 5}
  2. 遍历过程:
    • i = 0char = 'a'end = max(0, 2) = 2
    • i = 1char = 'b'end = max(2, 3) = 3
    • i = 2char = 'a'(满足 i == end = 2),记录长度 2 - 0 + 1 = 3"aba")❌?
    • (这里需要更正!i = 2 时的 end = 3,不等于 i,不会触发 append。)
    • i = 3char = 'b'(满足 i == end = 3),记录长度 3 - 0 + 1 = 4"abab"
    • i = 4char = 'c'end = max(3, 5) = 5
    • i = 5char = 'c'(满足 i == end = 5),记录长度 5 - 4 + 1 = 2"cc"
  3. 最终结果[4, 2]["abab", "cc"])✅

partition_labels 算法中,end 表示当前部分的最远结束位置。为了保证同一字符仅出现在一个部分里,我们需要确保其所有出现的范围都能被当前部分完全覆盖max(end, last_occurrence[char]) 的作用是不断扩展当前部分的右边界,以确保:当前字符的所有出现都被覆盖,后续字符不会跨越当前部分。

s = "ababcc" 为例:

字符 charlast_occurrence[char]end(更新前)new_end = max(end, last)操作
'a' (i=0)20max(0, 2) = 2end=2
'b' (i=1)32max(2, 3) = 3end=3
'a' (i=2)23max(3, 2) = 3end=3
'b' (i=3)33max(3, 3) = 3触发分割
'c' (i=4)53max(3, 5) = 5end=5
'c' (i=5)55max(5, 5) = 5触发分割

i == end 时,触发分隔的原因:

说明:当前部分的所有字符已经处理完毕,

  • 已经遍历到 i = end,且在这个位置之前的所有字符的最远出现位置 last_occurrence[char] 都 ≤ end(因为 end 是由 max(last_occurrence[char]) 决定的)。
  • 换句话说,这个部分已经囊括了所有必须包含的字符(同一字母的所有出现都被包含在当前部分)。

http://www.lryc.cn/news/2379654.html

相关文章:

  • Python 条件语句详解
  • 前端获取用户的公网 IP 地址
  • 在Maven中替换文件内容的插件和方法
  • 符合Python风格的对象(再谈向量类)
  • 云电竞服务器 工作原理
  • 【数据结构】线性表--队列
  • [Vue3]语法变动
  • Ubuntu服务器开启SNMP服务 监控系统配置指南 -优雅草星云智控简易化操作
  • linux本地部署ollama+deepseek过程
  • 从零开始实现大语言模型(十五):并行计算与分布式机器学习
  • OpenCV进阶操作:指纹验证、识别
  • 网络安全-等级保护(等保) 2-5 GB/T 25070—2019《信息安全技术 网络安全等级保护安全设计技术要求》-2019-05-10发布【现行】
  • 3D生成新突破:阶跃星辰Step1X-3D开源,可控性大幅提升
  • MySQL数据类型之VARCHAR和CHAR使用详解
  • 数字人 LAM 部署笔记
  • 《Docker 入门与进阶:架构剖析、隔离原理及安装实操》
  • 基于Akamai云计算平台的OTT媒体点播转码解决方案
  • 【MySQL】02.数据库基础
  • 选错方向太致命,华为HCIE数通和云计算到底怎么选?
  • 经典启发算法【早期/启发式/HC爬山/SA模拟退火/TS禁忌搜/IA免疫 思想流程举例全】
  • IntraWeb 16.0.2 + Bootstrap 4 居中布局实战(附源码+效果图)
  • Spring 框架中适配器模式的五大典型应用场景
  • 【Java ee初阶】jvm(3)
  • C 语言多维数组:定义、初始化与访问的深度解析
  • 浅入ES5、ES6(ES2015)、ES2023(ES14)版本对比,及使用建议---ES6就够用(个人觉得)
  • 23种设计模式考试趋势分析之——适配器(Adapter)设计模式——求三连
  • Python 翻译词典小程序
  • 【Linux笔记】——线程互斥与互斥锁的封装
  • Android屏幕采集编码打包推送RTMP技术详解:从开发到优化与应用
  • 【深度学习】残差网络(ResNet)