leetcode 763划分字母区间

复制代码
class Solution {
public:
    vector<int> partitionLabels(string s) {
        int last[26];

        // 记录每个字母最后一次出现的位置
        for(int i = 0; i < s.length(); i++){
            last[s[i] - 'a'] = i;
        }

        int start = 0, end = 0;
        vector<int> res;

        for(int i = start; i < s.length(); i++){

            // 当前字母最后出现的位置决定区间至少要延伸到哪里
            end = max(end, last[s[i] - 'a']);

            // i走到了当前区间的最远位置,可以进行切分
            if(i == end){
                // 计算当前区间的长度
                res.push_back(end - start + 1);

                // 下一个区间从end的下一个位置开始
                start = end + 1;
            }
        }

        return res;
    }
};

总结

这道题的核心就是 "记录最后位置 + 贪心划分区间"。

1. last 数组

复制代码
last[s[i] - 'a'] = i;

记录每个字母最后一次出现的位置。

例如:

复制代码
s = "ababcbaca"

那么:

复制代码
a 最后出现位置 = 8
b 最后出现位置 = 5
c 最后出现位置 = 7

2. end 表示当前区间最远必须到哪里

遍历当前区间时:

复制代码
end = max(end, last[s[i] - 'a']);

看到一个字母,就找到它最后一次出现的位置。

如果这个位置比当前 end 更远,就把 end 向后扩展。

所以 end 可以理解成:

当前区间为了保证同一个字母不出现在其他区间,最少需要到达的位置。


3. 为什么 i == end 就能切?

当:

复制代码
i == end

说明当前已经走到了区间要求的最远位置。

也就是说:

当前区间里面出现的所有字母,在后面都不会再出现了。

所以此时可以安全切分:

复制代码
res.push_back(end - start + 1);

然后:

复制代码
start = end + 1;

开始下一个区间。


4. 最核心的代码

实际上整道题最重要的就三步:

复制代码
end = max(end, last[s[i] - 'a']);

不断扩大区间。

复制代码
if(i == end)

发现可以切分。

复制代码
start = end + 1;

进入下一个区间。

一句话记忆

先找每个字母最后出现的位置,然后遍历字符串,用 end 不断扩大当前区间;当 i 走到 end 时,说明区间已经完整,可以切分。

相关推荐
圣保罗的大教堂4 分钟前
leetcode 453. 最小操作次数使数组元素相等 中等
leetcode
aichitang202417 分钟前
代数拓扑学与现代前沿视角
考研·算法·数学建模·ai·拓扑学·高考
二本咕咕-机械转码31 分钟前
FreeRTOS深入解析(一)_链表与并发保护——哨兵循环链表、排序键游标、临界区与关调度
单片机·算法·链表
-银雾鸢尾-43 分钟前
两数之和-C++实现
c++·算法
j7~1 小时前
【动态规划算法专题】动态规划五部曲实战:泰波那契数、三步问题、最小花费爬楼梯
c++·算法·动态规划·数据结构与算法
倍利福猎头公司官方账号1 小时前
大企业HR如何向猎头公司清晰传达AI岗位的技术需求?
人工智能·算法·机器人·求职招聘·业界资讯
揽星河..2 小时前
【C++】类和对象
c++·算法
D e re k ZH2 小时前
C++ 并发、未定义行为与工程化难点(No 3)
数据结构·c++·算法·面试
释厄6233 小时前
同性线套娃律——圆面积必然=1+2+...+n 的求和·圆心不与 π 相关
java·人工智能·算法·1024程序员节
暴力求解3 小时前
C++ ---继承(二)
开发语言·c++·算法