题目

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。

示例

  1. 输入:S = "ababcbacadefegdehijhklij"
  2. 输出:[9,7,8]
  3. 解释:
  4. 划分结果为 "ababcbaca", "defegde", "hijhklij"
  5. 每个字母最多出现在一个片段中。
  6. "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。

提示

  • S的长度在[1, 500]之间。
  • S只包含小写字母 'a''z'

    解题思路

    读题时我就很懵逼,完全不知道要干嘛,只知道将字符串化分成片段,还有一个字母只能出现一个片段中,最不能理解就是返回一个字符串长度??? 我表示一脸懵逼这都是啥呀?
    观察示例才稍微明白过来,就是将字符串中的字符划分成局部最优的片段。每个片段只能有本片段的字母,其他片段是没该字段中的字母的。 虽然理解啦题意,但是我对这题无从下手,从参考资料的提示为image.png
    但是我却傻傻的想把频率 个数 第一次出现的位置,最后一次出现的位置 都记录下来,只能说我挺贪心的,想把它们用数组存起来,但是想啦想不太行,就想用一种存储的方式能把这些都存起来,之后我就钻进这个迷宫出不来啦。
    我忽视啦这道题的解题思路是在例题中,当看到一篇解题思路时我分析完他的代码,我发现我是真的笨。
    我将示例换种表达方式你看

    1. a b a b c b a c a d e f e g d e h i j h k l i j
    2. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 21 23 当前索引值
    3. 8 5 8 5 7 5 8 7 8 14 15 11 15 13 14 15 19 22 23 19 20 21 22 23 最后出现的索引值
    4. 第一段
    5. a b a b c b a c a
    6. 0 1 2 3 4 5 6 7 8 当前索引值
    7. 8 5 8 5 7 5 8 7 8 最后出现的索引值
    8. 这一段开始值是8最大值也是8
    9. 第二段
    10. d e f e g d e
    11. 9 10 11 12 13 14 15 当前索引值
    12. 14 15 11 15 13 14 15 最后出现的索引值
    13. 开始值为14 但是最大值为15
    14. 第三段
    15. h i j h k l i j
    16. 16 17 18 19 20 21 21 23 当前索引值
    17. 19 22 23 19 20 21 22 23 最后出现的索引值

    从例题中另种展示效果来看,它是怎吗将字符分割成片段,你看切口处,都有一个规律,切口处的字母的最后出现的索引值是这段中最大的,且还等于当前索引值,按照这个规律。就要将每个字母最后出现的索引值记录下来。
    我们在吧字母遍历一次,这次遍历主要是为啦找出切口的位置,切口位置的字母最后出现的索引值为本段最大的,当前索引值 == 本段字符中最后出现的索引值中最大的那个
    那我们在遍历前就先声明一个最大值,用这个最大值与每个字母最后出现的索引值比对,看那个大,大的就赋值给这个最大值,而且当前索引值 == 最大值就是切口的位置,我们吧这长度记录下来不就好啦。 ```javascript /**

    • @param {string} s
    • @return {number[]}
    • 获取字母出的的最后一位
    • a b a b c b a c a d e f e g d e h i j h k l i j
    • 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 21 23 当前索引值
    • 8 5 8 5 7 5 8 7 8 14 15 11 15 13 14 15 19 22 23 19 20 21 22 23 最后出现的索引值
    • 第一段
    • a b a b c b a c a
    • 0 1 2 3 4 5 6 7 8 当前索引值
    • 8 5 8 5 7 5 8 7 8 最后出现的索引值
    • 这一段开始值是8最大值也是8
    • 切口处:当前索引值 == 最后出现的索引值(且为本段字符中最后出现的索引值中最大的那个)
    • 第二段
    • d e f e g d e
    • 9 10 11 12 13 14 15 当前索引值
    • 14 15 11 15 13 14 15 最后出现的索引值
    • 开始值为14 但是最大值为15
    • 切口处:当前索引值 == 最后出现的索引值(且为本段字符中最后出现的索引值中最大的那个)
    • 第三段
    • h i j h k l i j
    • 16 17 18 19 20 21 21 23 当前索引值
    • 19 22 23 19 20 21 22 23 最后出现的索引值
    • 开始值为19 最大值为23
    • 切口处:当前索引值 == 最后出现的索引值(且为本段字符中最后出现的索引值中最大的那个)

    • 划分的字母区间内的字母不会出现在其他区间中

    • 观察上面你会发现切口的地方是
    • 索引值 == 最后出现的索引值(且为本段字符中最后出现的索引值中最大的) 那吗未知值就是当前字符中最后出现的索引值中最大的那个值
    • 怎嘛找到字符中最后出现的索引值中最大的呢,那只能按个比对啦 */ var partitionLabels = function (s) { const letterObj = {}; const len = s.length; // 获取每个字母最后出现的位置 for (let i = 0; i < len; i++) { letterObj[s[i]] = i; // 每个字母最后出现的索引值 } let prevLetterIndex = 0; // 上一个切口的位置 let maxLetterIndex = 0; // 本段最大值(且是最后出现的) const arr = []; for (let i = 0; i < len; i++) { const curLetterMaxIndex = letterObj[s[i]]; // 获取当前字母最后出现的索引值 maxLetterIndex = Math.max(curLetterMaxIndex, maxLetterIndex); // 比对出最大值 // 当前索引值 == 最大值 就是切口的位置 if (i == maxLetterIndex) { arr.push(maxLetterIndex - prevLetterIndex + 1); // 本段字符的长度 prevLetterIndex = i + 1; // 上次切口的位置 } } return arr; };

```