題目要求:
給定一個字符串,要求把它切割成最小子字符串的集合,使得每一個字母只可能出現(xiàn)在一個子字符串中。舉例如下:若給定字符串s = ‘a(chǎn)aabbccabnnmmng’,期待的輸出結果為[[0, 8], [9, 13], [14, 14]]。因為切分后的字符串為:res = ['aaabbccab','nnmmn','g'].
解題思路:
我自己花了幾個小時都沒有做出來,是一位大佬告訴我他的思路,這里總結如下:
需要找到每個字母出現(xiàn)的第一個位置和最后一個位置,然后再取區(qū)間的最大并集即可。
解題步驟:
首先是用一個函數(shù) get_position來找出每個字母出現(xiàn)的第一個位置和最后一個位置。代碼如下:
def get_position(s):
position_start = dict()
position_end = dict()
for i in range(len(s)):
position_end.update({s[i]:i})
for i in range(len(s)):
if position_start.get(s[i],'') == '':
print(i)
position_start.update({s[i]:i})
position = []
for key in position_start:
position.append([position_start[key],position_end[key]])
return position
如果輸入目標字符串‘'aaabbccabnnmmng',這個函數(shù)的輸出為:
[[0, 7], [3, 8], [5, 6], [9, 13], [11, 12], [14, 14]]
也就是每一個字母出現(xiàn)的起始位置。
下一步需要給這些區(qū)間取并集,其實畫在數(shù)軸上是一個比較容易理解的辦法,但是如果想要讓程序也能識別,可以使用條件:
- 如果一個區(qū)間的右邊界小于另一個區(qū)間的左邊界,則兩個區(qū)間沒有交集。
- 如果一個區(qū)間的左邊界小于另一區(qū)間左邊界,右邊界大于另一個區(qū)間的右邊界,則第一個區(qū)間一定包含第二個區(qū)間。
從上面兩個規(guī)則就可以得到區(qū)間合并的函數(shù):
from typing import List
def string_cut(string:str)->List[List[int, int]]:
position = get_position(string) # 調用上面得到每個字母的首尾的函數(shù)
i = 0
result = []
for i in position:
if not result or result[-1][1] <i[0]:
result.append(i)
continue
if result[-1][1] <i[1]:
result[-1][1] = i[1]
return result