字符串 S
由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段。返回一个表示每个字符串片段的长度的列表。
示例 1:
输入: S = "ababcbacadefegdehijhklij"
输出: [9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
注意:
S
的长度在[1, 500]
之间。S
只包含小写字母'a'
到'z'
。
第一种思路:
只需要统计每个字母第一次出现的下标(find函数),和最后一次出现的下标的(rfind函数),就可以得到每个字母的区间范围,
比如示例1 的对应统计数组为: [[0, 8], [1, 5], [4, 7], [9, 14], [10, 15], [11, 11], [13, 13], [16, 19], [17, 22], [18, 23], [20, 20], [21, 21]]
然后题目就会转化为LeetCode-Python-56. 合并区间
class Solution(object):
def partitionLabels(self, S):
"""
:type S: str
:rtype: List[int]
"""
intervals = []
for i in range(0, 26):
if S.count(chr(ord("a") + i)):
intervals.append([S.find(chr(ord("a") + i)), S.rfind(chr(ord("a") + i))])
#print intervals
intervals = sorted(intervals, key = lambda x: x[0])
# print intervals
left = intervals[0][0]
right = intervals[0][1]
res = list()
for interval in intervals:
if interval[0] <= right:
right = max(right, interval[1])
else:
res.append([left, right])
left = interval[0]
right = interval[1]
res.append([left, right])
# print res
return [interval[1] - interval[0] + 1 for interval in res]
第二种思路:
学习自评论区,
先扫描一遍整个S,建立一个字典,字典的键是字母,值是这个字母最后一次出现的下标,
然后再线性扫描S,设置变量right 用于表示分隔开的子字符串的末尾在S里的下标,变量left表示子字符串的开头在S里的下标
如果当前扫描的元素的最后一次出现的下标比right大,就说明子字符串还需要延长,就刷新right,
如果当前扫描的元素的下标已经达到了right,就说明这个子字符串完全已经找到了,就可以把答案添加到res中。
class Solution(object):
def partitionLabels(self, S):
"""
:type S: str
:rtype: List[int]
"""
dic = {}
for index, char in enumerate(S):
dic[char] = index
right = dic[S[0]]
left = 0
res = []
for index, char in enumerate(S):
right = max(right, dic[char])
if index >= right:
res.append(right - left + 1)
left = right + 1
return res