「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」
题目
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例
输入:S = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
题解
贪心
- 题目要求字符串划分为尽可能多的片段
- 已知同一字母最多出现在一个片段中,所以要字符串划分为尽可能多的片段,需要知道字符最后一次出现的下标,字符串第一次出现与最后一次出现一定要在一个片段内;
- 有因为字符串是由小写字母组成,所以字符最多有26种。根据这个已知条件,可以使用一个长度为26的数组indexList保存字符串最后一次出现的下标;
- 枚举字符串
S,将字符串最后一次出现的下标存放到indexList; - 在indexList中,假设任意字符s在indexList数组中最后一次出现的下标为,
- 任意一个片段[,...,],片段中的字符最后一次出现的下标[,],在[,]一定存在,
- 从start= 0 开始,枚举整个字符串,当与枚举下标i相同时,可以认为这是一个最小的不可再分割的片段,将该片段长度放入结果数组中,i - start + 1
- 从start = i+1位置开始,继续枚举字符串S,当再次与枚举下标i相同时,找到另一个最小不可分割的片段,直到枚举结束
- 返回结果
根据上述思路编辑代码如下:
代码
var partitionLabels = function (s) {
// 记录字符最后一次出现的坐标
const indexList = Array(26).fill(0)
for (let i = 0; i < s.length; i++) {
const index = s[i].charCodeAt() - 'a'.charCodeAt()
indexList[index] = i
}
let start = 0
let end = 0
const result = []
for (let i = 0; i < s.length; i++) {
const index = s[i].charCodeAt() - 'a'.charCodeAt()
end = Math.max(end, indexList[index])
if (end === i) {
result.push(end - start + 1)
start = end + 1
}
}
return result
}