力扣hot100:划分字母区间

题目描述:

题目解析:

题目要求对字符串进行分割,使得每个字母最多只出现在一个分割片段中

在满足这个条件的前提下,需要返回每个分割片段的长度。

换句话说:

  1. 同一个字符不能跨越多个片段

  2. 一旦某个字符出现在当前片段中,那么这个片段必须包含该字符在字符串中的所有出现位置

  3. 分割后的片段要尽可能靠前、数量尽可能多

因此,本题的本质并不是"随意切字符串",而是要找到一种合理的切分方式,使字符的出现范围不会被打断。

思路分析:

解决这道题的关键,在于提前知道每个字符最远会出现到哪里。

1. 预处理字符的最后位置

由于字符串只包含小写字母,可以先遍历字符串,记录每个字符在字符串中最后一次出现的下标。

这样一来,当我们在某个位置看到一个字符时,就能立刻知道:当前分割区间至少要延伸到这个字符的最后出现位置。

2. 用区间合并的思路遍历字符串

接下来,从左到右遍历字符串,并维护一个"当前分割区间":区间的左端点是当前片段的起始位置。区间的右端点表示:当前片段必须覆盖到的最远位置。在遍历过程中,每遇到一个字符,就用它的最后出现位置来更新当前区间的右端点,保证这个字符不会出现在区间之外。

3. 何时可以完成一次分割

当遍历位置刚好走到当前区间的右端点时,说明:当前片段中出现的所有字符都已经完整地包含在这个区间内不会再延伸到后面的位置此时就可以安全地切分出一个片段,记录它的长度,并从下一个位置开始新的片段。

4. 思路本质

从整体来看,这道题的核心思想可以概括为:先确定每个字符的"活动范围",再把这些范围不断合并成若干不重叠的区间,每一个最终合并完成的区间,就是一个合法的分割片段

代码:

java 复制代码
class Solution {
    public List<Integer> partitionLabels(String s) {
        char[] a=s.toCharArray();
        int n=a.length;
        int[] last=new int[26];
        for(int i=0;i<n;i++){
            last[a[i]-'a']=i;
        }
        List<Integer> res=new ArrayList<>();
        int start=0,end=0;
        for(int i=0;i<n;i++){
            end=Math.max(last[a[i]-'a'],end);
            if(i==end){
                res.add(end-start+1);
                start=end+1;
            }
        }
        return res;
    }
}
相关推荐
tankeven4 分钟前
HJ138 在树上游玩
c++·算法
lihihi37 分钟前
P1209 [USACO1.3] 修理牛棚 Barn Repair
算法
weixin_387534221 小时前
Ownership - Rust Hardcore Head to Toe
开发语言·后端·算法·rust
xsyaaaan1 小时前
leetcode-hot100-链表
leetcode·链表
庞轩px1 小时前
MinorGC的完整流程与复制算法深度解析
java·jvm·算法·性能优化
Queenie_Charlie1 小时前
Manacher算法
c++·算法·manacher
闻缺陷则喜何志丹1 小时前
【树的直径 离散化】 P7807 魔力滋生|普及+
c++·算法·洛谷·离散化·树的直径
AI_Ming1 小时前
Seq2Seq-大模型知识点(程序员转行AI大模型学习)
算法·ai编程
若水不如远方1 小时前
分布式一致性(六):拥抱可用性 —— 最终一致性与 Gossip 协议
分布式·后端·算法
计算机安禾1 小时前
【C语言程序设计】第35篇:文件的打开、关闭与读写操作
c语言·开发语言·c++·vscode·算法·visual studio code·visual studio