LongDz 的数字文墨提案

763. 划分字母区间

3 min

题目

763. 划分字母区间 中等

解法:贪心

思路

核心思想是贪心策略:先统计每个字母的最后出现位置,再遍历字符串时维护当前片段的结束边界,当遍历到边界时立即切割。

正确性证明:对于任意片段,必须包含其中所有字母的最后出现位置,否则该字母会跨越片段。贪心策略选择当前已遍历字母的最后位置的最大值作为边界,确保边界内所有字母不会在后续出现,此时切割能得到最多片段数。若延迟切割只会减少片段数量,因此该策略是最优的。

  • Step 1: 创建大小为26的数组last,记录每个字母在字符串中最后出现的下标
  • Step 2: 第一次遍历字符串,填充last数组
  • Step 3: 初始化start=0end=0,用于标记当前片段的起止位置
  • Step 4: 第二次遍历字符串,更新end = max(end, last[s[i]-'a'])
  • Step 5: 当i == end时,说明当前片段结束,记录长度并更新start = end + 1

复杂度

  • 时间复杂度: O(n)O(n),其中n为字符串长度,需要两次线性遍历
  • 空间复杂度: O(1)O(1),使用了固定大小26的数组存储字母最后位置

代码

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int last[26] = {0};
        for(int i = 0; i < s.size(); i++){
            last[s[i]-'a'] = i;
        }
        vector<int> ans;
        int start = 0;
        int end = 0;
        for(int i = 0; i < s.size(); i++){
            end = max(end,last[s[i]-'a']);
            if(i == end){
                ans.push_back(end - start + 1);
                start = end + 1;
            }
        }
        return ans;
    }
};