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 时,说明区间已经完整,可以切分。

相关推荐
不会就选b1 小时前
算法日常・每日刷题--<动态规划>20
算法·leetcode·动态规划
青少儿编程课堂2 小时前
迪杰斯特拉(Dijkstra)算法:单源最短路与赛场路线规划
c++·python·算法·bfs·信息学竞赛
不会就选b2 小时前
算法日常・每日刷题--<动态规划>19
算法·leetcode·职场和发展
考研保研资料分享3 小时前
新闻传播保研经验:中传预推免面试、广告学代表作与实习准备(2025)
面试·职场和发展
没有钱的钱仔4 小时前
协方差矩阵含义
算法·机器学习·矩阵
垆边人似月.4 小时前
华为机试题 :和为 K 的子数组个数
算法·leetcode·华为
三*一4 小时前
优化修整算法
前端·javascript·算法
达子6664 小时前
RUST 图解 第 3 章:通用编程概念(Common Programming Concepts)
开发语言·算法·rust