這題要把一個單字列表照給的最大寬度格式化,讓每行都正好符合最大寬度,且兩端要對齊,問題在怎麼分配空格,確保最後一行左對齊。
思路:
逐行打包單字,首先,要用貪心一點的方式,盡量把單字塞進一行,直到放下一個單字會超出 maxWidth ,空格分配,確定了一行裡要放的單字數量後,算那一行的剩餘空間,再把這些空格儘量均勻地分佈到單字間,如果沒辦法平均分配,那靠左的單字之間應該分更多空格,處理最後一行,最後一行的特別是,它不用兩端對齊,只要左對齊,右邊補齊空格。
步驟:
初始化變數,準備變數用來存儲當前行的單字跟其長度,迴圈處理單詞,對單字列表遍歷,逐一把單字加到當前行,再檢查有沒有超過最大寬度,當行滿時,把這行的單字兩端對齊,開始處理新的一行,空格分配邏輯,算每個單字間應該有多少空格,如果空格不能均勻分配,靠左的單字間應多分配一個空格,處理最後一行,最後一行向左對齊,然後在右邊補齊空格。
思考:
單字長度和空格的分配,每行裡剩下的空格怎麼平均分配是重點,特例,最後一行,或一行裡只有一個單字的情況,模擬填充,可以先把單字逐個放到行裡,超過 maxWidth 時,處理當前行的格式化問題,然後再開始新的一行。
程式碼:
class Solution(object):
def fullJustify(self, words, maxWidth):
"""
:type words: List[str]
:type maxWidth: int
:rtype: List[str]
"""
result = []
line = []
line_length = 0
for word in words:
# 如果加當前單字後超過maxWidth,就處理當前行
if line_length + len(word) + len(line) > maxWidth:
# 算剩餘空格數
spaces = maxWidth - line_length
#如果這一行只有一個單字,直接左對齊,後面補齊空格
if len(line) == 1:
result.append(line[0] + ' ' * spaces)
else:
# 空格平均分配到單字之間
space_between_words = spaces // (len(line) - 1)
extra_spaces = spaces % (len(line) - 1)
for i in range(extra_spaces):
line[i] += ' ' # 給前面的單字多加一個空格
result.append((' ' * space_between_words).join(line))
#清空行,開始新的一行
line = []
line_length = 0
#把單字加到當前行
line.append(word)
line_length += len(word)
#處理最後一行,左對齊
result.append(' '.join(line).ljust(maxWidth))
return result
逐行填充單字,用一個 line 列表來臨時存當前行的單字,再用一個變量 line_length 記錄那行單字的總長度(不包含空格),試看看加一個單字後發現行寬會超過 maxWidth ,就要對這行的單字分配空格,儲存結果,然後開始下一行,空格分配,如果一行有多個單字,算剩下的空格數把這些空格平均分配給行中的單字,如果空格不能完全平均分配,就從左開始依序多分配一個空格,如果那行只有一個單字,直接在後面填空格到達 maxWidth。
解釋:用 line 來存當前行的單字,用 line_length 跟蹤當前行的單字總長,當前行的單字加新單字會超過 maxWidth 時,對這行單字進行格式化,如果行內只有一個單字,那行直接左對齊,右邊用空格填滿,如果有多個單字,平均分配空格,再把多的空格分配到左邊的單字間,最後一行直接左對齊。
時間複雜度:
這個算法的時間複雜度是 O(n),n 是單字總數,因為每個單字只處理一次,這樣的方法能確保每行的單字合理分配,符合題目對齊要求。