From 458f94b8b94b6e9252dc23dc11f6627a4272e2b8 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 02:26:34 -0500 Subject: [PATCH] =?UTF-8?q?Update=200763.=E5=88=92=E5=88=86=E5=AD=97?= =?UTF-8?q?=E6=AF=8D=E5=8C=BA=E9=97=B4.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0763.划分字母区间.md | 111 +++++++++++----------------- 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md index fbcafdc8..158f76d6 100644 --- a/problems/0763.划分字母区间.md +++ b/problems/0763.划分字母区间.md @@ -231,83 +231,56 @@ class Solution{ ``` ### Python +贪心(版本一) ```python class Solution: def partitionLabels(self, s: str) -> List[int]: - hash = [0] * 26 - for i in range(len(s)): - hash[ord(s[i]) - ord('a')] = i + last_occurrence = {} # 存储每个字符最后出现的位置 + for i, ch in enumerate(s): + last_occurrence[ch] = i + result = [] - left = 0 - right = 0 - for i in range(len(s)): - right = max(right, hash[ord(s[i]) - ord('a')]) - if i == right: - result.append(right - left + 1) - left = i + 1 + start = 0 + end = 0 + for i, ch in enumerate(s): + end = max(end, last_occurrence[ch]) # 找到当前字符出现的最远位置 + if i == end: # 如果当前位置是最远位置,表示可以分割出一个区间 + result.append(end - start + 1) + start = i + 1 + return result - -# 解法二(不相交区间法) + +``` +贪心(版本二)与452.用最少数量的箭引爆气球 (opens new window)、435.无重叠区间 (opens new window)相同的思路。 +```python class Solution: - def partitionLabels(self, s: str) -> List[int]: - # 记录每个字母出现的区间 - def getBord(s): - hash = [[-float('inf')] * 2 for _ in range(26)] - for i in range(len(s)): - if hash[ord(s[i]) - ord('a')][0] == -float('inf'): - hash[ord(s[i]) - ord('a')][0] = i - hash[ord(s[i]) - ord('a')][1] = i - # 去除字符串中未出现的字母所占用区间 - hash_filter = [] - for item in hash: - if item[0] != -float('inf'): hash_filter.append(item) - return hash_filter - - # 得到无重叠区间题意中的输入样例格式:区间列表 - hash = getBord(s) - # 按照左边界从小到大排序 - hash.sort(key= lambda x: x[0]) - res = [] - left = 0 - # 记录最大右边界 - right = hash[0][1] + def countLabels(self, s): + # 初始化一个长度为26的区间列表,初始值为负无穷 + hash = [[float('-inf'), float('-inf')] for _ in range(26)] + hash_filter = [] + for i in range(len(s)): + if hash[ord(s[i]) - ord('a')][0] == float('-inf'): + hash[ord(s[i]) - ord('a')][0] = i + hash[ord(s[i]) - ord('a')][1] = i for i in range(len(hash)): - # 一旦下一区间左边界大于当前右边界,即可认为出现分割点 - if hash[i][0] > right: - res.append(right - left + 1) - left = hash[i][0] - # 实时更新最大右边界 - right = max(right, hash[i][1]) - # 最右侧区间(字符串长度为1时的特殊情况也包含于其中) - res.append(right - left + 1) + if hash[i][0] != float('-inf'): + hash_filter.append(hash[i]) + return hash_filter + + def partitionLabels(self, s): + res = [] + hash = self.countLabels(s) + hash.sort(key=lambda x: x[0]) # 按左边界从小到大排序 + rightBoard = hash[0][1] # 记录最大右边界 + leftBoard = 0 + for i in range(1, len(hash)): + if hash[i][0] > rightBoard: # 出现分割点 + res.append(rightBoard - leftBoard + 1) + leftBoard = hash[i][0] + rightBoard = max(rightBoard, hash[i][1]) + res.append(rightBoard - leftBoard + 1) # 最右端 return res - -# 解法三:区间合并法 (结合下一题 56. Merge Intervals 的写法) -class Solution: # - def partitionLabels(self, s: str) -> List[int]: - aaa = list(set(s)) - #aaa.sort() - bbb = list(s) - ccc = [] - for i in reversed(bbb): - ccc.append(i) - intervals = [] - for i in range(len(aaa)): - intervals.append([bbb.index(aaa[i]),len(bbb)-ccc.index(aaa[i])-1]) - # 先求出各个字母的存在区间,之后利用区间合并方法得出所有不相邻的最大区间。 - intervals.sort(key = lambda x:x[0]) - newinterval = [] - left, right = intervals[0][0], intervals[0][1] - for i in range(1,len(intervals)): - if intervals[i][0] in range(left, right+1): - right = max(intervals[i][1],intervals[i-1][1],right) - left = min(intervals[i-1][0],left) - else: - newinterval.append(right-left+1) - left = intervals[i][0] - right = intervals[i][1] - newinterval.append(right-left+1) - return newinterval + ``` ### Go