【算法36天:Day36】第八章贪心算法 划分字母区间(763)

78 阅读2分钟

题目二:

image.png

思路

一想到分割字符串就想到了回溯,但本题其实不用回溯去暴力搜索。

题目要求同一字母最多出现在一个片段中,那么如何把同一个字母的都圈在同一个区间里呢?

如果没有接触过这种题目的话,还挺有难度的。

在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

可以分为如下两步:

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

如图:

763.划分字母区间

明白原理之后,代码并不复杂,如下:

var partitionLabels = function(s) {
    let hash = {} 
    for (let i = 0; i < s.length; i++) {
        hash[s[i]] = i // 统计每一个字符最后出现的位置
    }
    let result = []
    let left = 0
    let right = 0
    for (let i = 0; i < s.length; i++) {
        right = Math.max(right, hash[s[i]])
        if (right === i) {
            result.push(right - left + 1)
            left = right + 1
        }
    }
    return result
};

总结

这道题目leetcode标记为贪心算法,说实话,我没有感受到贪心,找不出局部最优推出全局最优的过程。就是用最远出现距离模拟了圈字符的行为。

但这道题目的思路是很巧妙的,所以有必要介绍给大家做一做,感受一下。

#补充

这里提供一种与452.用最少数量的箭引爆气球 (opens new window)435.无重叠区间 (opens new window)相同的思路。

统计字符串中所有字符的起始和结束位置,记录这些区间(实际上也就是435.无重叠区间 (opens new window)题目里的输入),将区间按左边界从小到大排序,找到边界将区间划分成组,互不重叠。找到的边界就是答案。