【贪心算法】——力扣763. 划分字母区间

news2024/11/14 14:21:40

763. 划分字母区间

一、题目难度

中等

二、相关标签与相关企业

[相关标签]
[相关企业]

三、题目描述

给你一个字符串 s。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s

返回一个表示每个字符串片段的长度的列表。

四、示例

示例1

输入s = "ababcbacadefegdehijhklij"
输出[9, 7, 8]
解释
划分结果为“ababcbaca”、“defegde”、“hijhklij”,每个字母最多出现在一个片段中。
像“ababcbacadefegde”,“hijhklij”这样的划分是错误的,因为划分的片段数较少。

示例2

输入s = "eccbbbbdec"
输出[10]

五、提示

  1. 1 <= s.length <= 500
  2. s 仅由小写英文字母组成

贪心算法

  • 思路:
    • 首先,我们先遍历一次字符串,用字典last_s = { }记录每个字母最后出现的位置。
    • 然后,我们再次从头遍历字符串,设定一个当前片段起startend位置,后续不断更新维护该片段。
      • startend都初始化为0
      • 遍历过程中,对于每个字符,更新end为当前字符最后出现位置的最大字符
      • 当遍历到i位置等于end时,说明当前片段已经包含了所有出现过的字母
      • 当前片段的长度end - start +1添加到结果列表中
      • 更新starti + 1,开始下一个片段的划分

——————————————————————————————————————————————
如何实现用字典enumerate()函数记录最后出现的位置??

1. enumerate函数**

  • 功能:
    • enumerate 是 Python 中的一个内置函数,它用于在遍历可迭代对象(如列表、字符串等)时,同时返回元素的索引和元素本身。它的基本语法是 enumerate(iterable, start=0),其中iterable是要遍历的可迭代对象,start 是可选参数,用于指定索引的起始值,默认是 0
  • 用法:
    • 当执行for i, char in enumerate(s): 时,对于字符串 s 中的每个字符chari,enumerate 会依次获取到该字符在字符串中的索引(从 0 开始,因为默认 start=0),而 char 则获取到对应的字符本身。例如,如果 s = "abc",那么第一次循环时,i 会是 0char 会是 a;第二次循环时,i 会是 1char 会是 b;第三次循环时,i 会是 2char 会是 c

以下是对这段代码中字典 last_index 以及 enumerate 函数相关操作的详细解释:

2. 字典 last_index

  • 注意字典写入方法

    • last_index={} # 创建字典
    • last_index[a] = 1 # 写入键值对
    • ——>
    • last_index = {'a' : 1}
  • 功能及初始化

    • 字典是Python中的一种数据结构,它以键值对的形式存储数据,其中键是唯一的,通过键可以快速访问到对应的 值。在这里,last_index 字典被初始化为一个空字典 {},它的作用是用于记录每个字母在字符串 s 中最后出现的位置。
  • 记录最后出现位置的原理

    • 在循环 for i, char in enumerate(s): 中,每次遍历到一个字符 char 时,我们就将这个字符作为键,将它当前的索引 i 作为值,存入 last_index 字典中。关键在于,由于我们是按照字符串的顺序依次遍历的,所以当遇到同一个字母多次出现时,后面出现的位置索引会覆盖前面的记录。这样,当整个字符串遍历完成后,字典 last_index 中每个字母对应的键值对中,值就是该字母在字符串中最后出现的位置。
  • 写入后字典的形式示例

    • 假设字符串 s = "ababcbacadefegdehijhklij",经过上述循环遍历后,last_index 字典的形式可能如下:
{
    'a': 8,
    'b': 5,
    'c': 7,
    'd': 14,
    'e': 15,
    'f': 11,
    'g': 13,
    'h': 19,
    'i': 22,
    'j': 23,
    'k': 20,
    'l': 21
}

可以看到,每个字母作为键,其最后出现的位置作为值被准确地记录在了字典中。这样,在后续处理划分字母区间的过程中,我们就可以方便地通过查询这个字典来获取每个字母的最后出现位置信息,以便确定每个片段的范围。

class Solution:
    def partitionLabels(self, s: str) -> List[int]:
        # 1. 统计每个字符最后出现的位置(用到enumerate迭代器,返回字符串的索引和字符)
          # 初始化字典last_index
        last_index = {}
          # 从头遍历每个字符char出现的位置,由于从头向后遍历,后面的位置会覆盖前面的,
        for i, char in enumerate(s):
            last_index[char] = i

        # 2. 从头遍历字符串s的字符char,
          # 初始化起末位置
          start = 0
          end = 0
          # 初始化结果列表
          res = []
          # 再次遍历,对于每个字符char,索引i
        for i, char in enumerate(s):
            # 更新end,为当前字符char最后出现的位置(字典中存着)
            end = last_index[char]
            if i == end:
                res.append(end- start + 1)
        return res
————————————————————————————————————————————
执行出错
0 / 118 个通过的测试用例
IndentationError: unindent does not match any outer indentation level
             ^
    start = 0
Line 12  (Solution.py)

以上代码错误,是我顺着之前的算法步骤写的!
问题出在哪?
太粗心了呀!!!

  • 首先,i碰到一次end,需要更新start位置为i+1
    if i == end:
        res.append(end- start + 1)
        start = i + 1

一个很关键的点,下面来详细解释一下为什么是 end = max(end, last_index[char]) 而不是直接 end = last_index[char]

理解需求

我们的目标是划分字符串 s 为尽可能多的片段,使得同一字母最多出现在一个片段中。在遍历字符串的过程中,要确定每个片段的结束位置 end,这个位置应该是当前片段内所有字母最后可能出现的最远位置。

直接赋值的问题(end = last_index[char]

如果按照 end = last_index[char] 来更新 end,那么每次遇到一个字符 char,就会直接将 end 设置为该字符在字典中记录的最后出现位置。这样做会导致一个问题,就是可能会把 end 的值设置得过小,无法包含当前片段内其他字母后续可能出现的位置。

例如,对于字符串 s = "ababcbacadefegdehijhklij",假设我们已经开始划分第一个片段,初始时 end = 0。当我们遍历到字符 a 时,如果按照直接赋值的方式,end 就会被设置为 a 的最后出现位置,也就是 8。但此时,在后续的字符串中,还有其他字母(如 bc 等)在这个片段内也会出现,并且它们的最后出现位置可能比 8 更远。如果就这样把 end 固定为 8,那么就无法正确划分出满足条件的片段,可能会导致某些字母被错误地划分到了下一个片段中,违背了“同一字母最多出现在一个片段中”的要求

取最大值的好处(end = max(end, last_index[char])

而使用 end = max(end, last_index[char]) 来更新 end,就可以避免上述问题。每次遇到一个字符 char,我们会比较当前的 end 值和该字符 char 的最后出现位置(last_index[char])。

  • 如果 last_index[char] 大于当前 end 值,说明该字符的最后出现位置更远,那么就需要把 end 更新为这个更远的位置,以确保 end 能够包含该字符以及可能后续出现的其他字母的最远位置。
  • 如果 last_index[char] 小于等于当前 end 值,说明当前 end 的值已经能够涵盖该字符后续可能出现的位置了,不需要对 end 进行更新。

继续以上面的字符串为例,初始时 end = 0,当遍历到字符 a 时,假设 a 的最后出现位置是 8,此时 end = max(0, 8)end 就会被更新为 8。接着当遍历到字符 b 时,假设 b 的最后出现位置是 5,因为 5 小于当前的 end(也就是 8),所以 end 保持不变,还是 8。但当遍历到字符 c 时,假设 c 的最后出现位置是 7,此时 end = max(8, 7)end 依然保持为 8。这样,通过不断地取最大值来更新 end,就能保证 end 始终是当前片段内所有字母最后可能出现的最远位置,从而正确地划分出满足条件的片段。

所以,不能简单地为每一个 char 都直接赋予 end,而是要通过取最大值的方式来更新 end,以确保划分片段的正确性。

修改了代码:

class Solution:
    def partitionLabels(self, s: str) -> List[int]:
        # 1. 统计每个字符最后出现的位置(用到enumerate迭代器,返回字符串的索引和字符)
          # 初始化字典last_index
        last_index = {}
          # 从头遍历每个字符char出现的位置,由于从头向后遍历,后面的位置会覆盖前面的,
        for i, char in enumerate(s):
            last_index[char] = i

        # 2. 从头遍历字符串s的字符char,
          # 初始化起末位置
          start = 0
          end = 0
          # 初始化结果列表
          res = []
          # 再次遍历,对于每个字符char,索引i
        for i, char in enumerate(s):
            # 更新end,为当前字符char最后出现的位置(字典中存着)
            # 错:end = last_index[char]
            # 改:
            end = max(last_index[char], end)
            if i == end:
                res.append(end- start + 1)
                # 错,加:
                start = i + 1 
        return res
————————————————————————————————————————————————————————
IndentationError: unindent does not match any outer indentation level
             ^
    start = 0
Line 12  (Solution.py)

检查半天原来是缩进问题,缩进是python的特色。

class Solution:
    def partitionLabels(self, s: str) -> List[int]:
        # 1. 统计每个字符最后出现的位置(用到enumerate迭代器,返回字符串的索引和字符)
          # 初始化字典last_index
        last_index = {}
          # 从头遍历每个字符char出现的位置,由于从头向后遍历,后面的位置会覆盖前面的,
        for i, char in enumerate(s):
            last_index[char] = i

        # 2. 从头遍历字符串s的字符char,
          # 初始化起末位置
        start = 0
        end = 0
        # 初始化结果列表
        res = []
        # 再次遍历,对于每个字符char,索引i
        for i, char in enumerate(s):
            # 更新end,为当前字符char最后出现的位置(字典中存着)
            # 错:end = last_index[char]
            # 改:
            end = max(last_index[char], end)
            if i == end:
                res.append(end- start + 1)
                # 错,加:
                start = i + 1 
        return res
————————————————————————————
通过

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

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

相关文章

Python 获取PDF的各种页面信息(页数、页面尺寸、旋转角度、页面方向等)

目录 安装所需库 Python获取PDF页数 Python获取PDF页面尺寸 Python获取PDF页面旋转角度 Python获取PDF页面方向 Python获取PDF页面标签 Python获取PDF页面边框信息 了解PDF页面信息对于有效处理、编辑和管理PDF文件至关重要。PDF文件通常包含多个页面&#xff0c;每个页…

企业级RAG(检索增强生成)系统构建研究

— 摘要 检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;RAG&#xff09;技术已经成为企业在知识管理、信息检索和智能问答等应用中的重要手段。本文将从RAG系统的现状、方法论、实践案例、成本分析、实施挑战及应对策略等方面&#xff0c;探讨企业如何…

前端学习八股资料CSS(二)

更多详情&#xff1a;爱米的前端小笔记&#xff0c;更多前端内容&#xff0c;等你来看&#xff01;这些都是利用下班时间整理的&#xff0c;整理不易&#xff0c;大家多多&#x1f44d;&#x1f49b;➕&#x1f914;哦&#xff01;你们的支持才是我不断更新的动力&#xff01;找…

SAP 创建物料主数据报错:估价范围3010还没有生产式的物料帐簿

通过接口创建物料主数据&#xff08;模拟MM01&#xff09;&#xff0c;报错如图&#xff1a; 处理方案1&#xff1a;&#xff08;我的不行&#xff0c;提示已经是生产的&#xff09; 将评估范围的物料分类账设置为生产 事务码: CKMSTART - 物料分类帐的生产开始 处理方案2&a…

扫雷游戏代码分享(c基础)

hi , I am 36. 代码来之不易&#x1f44d;&#x1f44d;&#x1f44d; 创建两个.c 一个.h 1&#xff1a;test.c #include"game.h"void game() {//创建数组char mine[ROWS][COLS] { 0 };char show[ROWS][COLS] { 0 };char temp[ROWS][COLS] { 0 };//初始化数…

leetcode 148. 排序链表 中等

给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4] 示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,3,4,5]示例 3&#xff1a; …

Elasticsearch中什么是倒排索引?

倒排索引&#xff08;Inverted Index&#xff09;是一种索引数据结构&#xff0c;它在信息检索系统中被广泛使用&#xff0c;特别是在全文搜索引擎中。倒排索引允许系统快速检索包含给定单词的文档列表。它是文档内容&#xff08;如文本&#xff09;与其存储位置之间的映射&…

excel-VLOOKUP函数使用/XVLOOKUP使用

多个窗口同时编辑表格&#xff0c;方便对照操作 使用开始-视图-新建窗口 将战区信息表的三列数据匹配到成交数据表上 可以使用VLOOKUP函数 有4个参数&#xff08;必须要查找的值&#xff0c; 要查找的区域&#xff0c;要返回区域的第几列数据&#xff0c;一个可选参数查找匹…

netcore 静态文件目录浏览

环境&#xff1a;Net6 string dirPath "C:\\Users\\15298\\Pictures"; var fileProvider new PhysicalFileProvider(dirPath); app.UseStaticFiles(new StaticFileOptions {FileProvider fileProvider,RequestPath new PathString(("/files")) }); // …

1Panel修改PostgreSQL时区

需求 1Panel安装的PostgreSQL默认是UTC时区&#xff0c;需要将它修改为上海时间 步骤 进入PostgreSQL的安装目录 /opt/1panel/apps/postgresql/postgresql/data打开postgresql.conf文件 修改&#xff1a; log_timezone Asia/Shanghai timezone Asia/Shanghai保存后重启…

函数式接口和stream

函数式接口&#xff08;Functional Interface&#xff09;是Java 8引入的一个新特性&#xff0c;它只有一个抽象方法的接口。这意味着你可以将一个函数式接口作为参数传递给方法&#xff0c;或者将其实现为一个lambda表达式。函数式接口的主要目的是允许你以声明性方式处理操作…

Oracle 高水位线和低-高水位线(High Water Mark Low High Water Mark)

在Oracle的逻辑存储结构中&#xff08;表空间-段-区-块&#xff09;&#xff0c;数据是存在数据段中的&#xff0c;通常一个表就是一个数据段&#xff0c;而段最终又由许多数据块组成。当数据存入数据块时&#xff0c;需要对块进行格式化&#xff0c;高水位线&#xff08;High …

科技资讯|Matter 1.4 标准正式发布,低功耗蓝牙助力其发展

连接标准联盟&#xff08;CSA&#xff09;宣布推出最新的 Matter 1.4 版本&#xff0c;引入了一系列新的设备类型和功能增强&#xff0c;有望提高包括 HomeKit 在内的智能家居生态系统之间的互操作性。 设备供应商和平台能够依靠增强的多管理员功能改善多生态系统下的用户体验&…

python练习-Django web入门

python -m pip install --user requests使用API调用请求数据 处理API响应 import requestsclass Requests:def request(self):url "https://www.toutiao.com/stream/widget/local_weather/data/?city北京"headers {"Accept": "application/json;…

元器件封装

元器件封装类型 为什么越来越多用贴片元件&#xff0c;而不是插件元件 为什么越来越多用贴片元件&#xff0c;而不是插件元件 1.体积小、质量小、容易保存和运输&#xff1b; 2.容易焊接和拆卸。抗震效果好。 贴片元件不用过孔&#xff0c;用锡少。直插元件最麻烦的就是拆卸&a…

[SaaS] 数禾科技 AIGC生成营销素材

https://zhuanlan.zhihu.com/p/923637935https://zhuanlan.zhihu.com/p/923637935

自顶向下逐步求精解决LeetCode第3307题找出第K个字符II题

3307.找出第K个字符II 难度&#xff1a;困难 问题描述&#xff1a; Alice和Bob正在玩一个游戏。最初&#xff0c;Alice有一个字符串word"a"。 给定一个正整数k和一个整数数组operations&#xff0c;其中operations[i]表示第i次操作的类型。 现在Bob将要求Alice按…

v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条

效果 导入组件 import ElImageViewer from "element-ui/packages/image/src/image-viewer"; components:{ ElImageViewer },模板使用组件 <el-image-viewerv-if"isShowPics":on-close"closeViewer":url-list"srcList"/>定义两…

Redis - 哨兵(Sentinel)

Redis 的主从复制模式下&#xff0c;⼀旦主节点由于故障不能提供服务&#xff0c;需要⼈⼯进⾏主从切换&#xff0c;同时⼤量 的客⼾端需要被通知切换到新的主节点上&#xff0c;对于上了⼀定规模的应⽤来说&#xff0c;这种⽅案是⽆法接受的&#xff0c; 于是Redis从2.8开始提…

使用wordpress搭建简易的信息查询系统

背景 当前有这样的一个需求&#xff0c;要实现让客户能够自助登录系统查询一些个人的信息&#xff0c;市面上没有特别符合我的需求的产品&#xff0c;经过一段时间的研究&#xff0c;想出了一个用wordpress实现简易信息查询系统&#xff0c;有两种方式。 方式一&#xff1a;使…