Bootstrap

【Leetcode 热题 100】763. 划分字母区间

问题背景

给你一个字符串 s s s。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。
注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s s s
返回一个表示每个字符串片段的长度的列表。

数据约束

1 ≤ s . l e n g t h ≤ 500 1 \le s.length \le 500 1s.length500
s s s 仅由小写英文字母组成

解题过程

看到频率和子串,一开始想的是滑窗搭配哈希表,实际上并不是很好实现。
比较好的做法是,找到所有字母第一次和最后一次出现的位置,把这个问题看作 合并区间
每个字母第一次和最后一次出现的位置会框定一个范围,这些范围里还会包含其它字母,也就产生了重叠区间。为了使得同一字母最多出现在一个片段中,这些重叠区间是需要合并的。
而题目又要求划分为尽可能多的片段,就不应该进一步地尝试合并区间了,所以上述处理完的区间长度就是最终结果。

具体实现

class Solution {
    public List<Integer> partitionLabels(String s) {
        char[] chS = s.toCharArray();
        int n = chS.length;
        // 统计每一个字母最后一次出现的位置
        int[] lastIndex = new int[26];
        for (int i = 0; i < n; i++) {
            lastIndex[chS[i] - 'a'] = i;
        }
        List<Integer> res = new ArrayList<>();
        for (int i = 0, left = 0, right = 0; i < n; i++) {
            // 更新当前有边界的要求
            right = Math.max(right, lastIndex[chS[i] - 'a']);
            // 访问到当前的有边界时,说明已经完成了区间合并,添加结果并移动左边界指针
            if (i == right) {
                res.add(right - left + 1);
                left = i + 1;
            }
        }
        return res;
    }
}
;