题目
字符串 S
由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例
输入:S = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
提示
S
的长度在[1, 500]
之间。-
解题思路
读题时我就很懵逼,完全不知道要干嘛,只知道将字符串化分成片段,还有一个字母只能出现一个片段中,最不能理解就是返回一个字符串长度??? 我表示一脸懵逼这都是啥呀?
观察示例才稍微明白过来,就是将字符串中的字符划分成局部最优的片段。每个片段只能有本片段的字母,其他片段是没该字段中的字母的。 虽然理解啦题意,但是我对这题无从下手,从参考资料的提示为
但是我却傻傻的想把频率 个数 第一次出现的位置,最后一次出现的位置 都记录下来,只能说我挺贪心的,想把它们用数组存起来,但是想啦想不太行,就想用一种存储的方式能把这些都存起来,之后我就钻进这个迷宫出不来啦。
我忽视啦这道题的解题思路是在例题中,当看到一篇解题思路时我分析完他的代码,我发现我是真的笨。
我将示例换种表达方式你看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 最后出现的索引值
从例题中另种展示效果来看,它是怎吗将字符分割成片段,你看切口处,都有一个规律,切口处的字母的最后出现的索引值是这段中最大的,且还等于当前索引值,按照这个规律。就要将每个字母最后出现的索引值记录下来。
我们在吧字母遍历一次,这次遍历主要是为啦找出切口的位置,切口位置的字母最后出现的索引值为本段最大的,当前索引值 == 本段字符中最后出现的索引值中最大的那个
那我们在遍历前就先声明一个最大值,用这个最大值与每个字母最后出现的索引值比对,看那个大,大的就赋值给这个最大值,而且当前索引值 == 最大值就是切口的位置,我们吧这长度记录下来不就好啦。 ```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; };
```