68、文本左右对齐
# 给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。
# 你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单词。
# 必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。
# 要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
# 文本的最后一行应为左对齐,且单词之间不插入额外的空格。
# 注意:
# 单词是指由非空格字符组成的字符序列。
# 每个单词的长度大于 0,小于等于 maxWidth。
# 输入单词数组 words 至少包含一个单词
# 输入: words = ["This", "is", "an", "example", "of", "text", "justification."], maxWidth = 16
# 输出:
# [
# "This is an",
# "example of text",
# "justification. "
# ]
class Solution(object):
def fullJustify(self, words, maxWidth):
"""
:type words: List[str]
:type maxWidth: int
:rtype: List[str]
"""
def fullJustify(self, words, maxWidth):
"""
对给定的单词列表进行全文对齐。
:type words: List[str] - 单词列表
:type maxWidth: int - 最大行宽度
:rtype: List[str] - 对齐后的文本列表
"""
# 初始化结果列表
res = []
# 初始化单词列表索引
i = 0
# 遍历单词列表,直到所有单词都被处理
while i < len(words):
# 初始化当前行的单词列表和长度计数器
line = []
line_len = 0
# 确定当前行可以容纳的单词
while i < len(words) and line_len + len(words[i]) + len(line) <= maxWidth:
line.append(words[i])
line_len += len(words[i])
i += 1
# 计算当前行的空格数
if i < len(words) and len(line) > 1:
# 如果不是最后一行且当前行有多个单词,则均匀分配空格
spaces = maxWidth - line_len
avg_spaces = spaces // (len(line) - 1)
extra_spaces = spaces % (len(line) - 1)
# 将额外的空格分配给前面的单词间隔
line_str = (' ' * (avg_spaces + 1)).join(line[:extra_spaces + 1]) + ' ' * avg_spaces + (' ' *avg_spaces).join(line[extra_spaces + 1:])
else:
# 如果是最后一行或当前行只有一个单词,则左对齐并填充剩余空间
line_str = ' '.join(line) + ' ' * (maxWidth - line_len - len(line) + 1)
# 将格式化后的行添加到结果列表中
res.append(line_str)
# 返回全文对齐的结果
return res
#说明:
# 将额外的空格分配给前面的单词间隔
line_str = (' ' * (avg_spaces + 1)).join(line[:extra_spaces + 1]) + ' ' * avg_spaces + ('avg_spaces).join(line[extra_spaces + 1:])#三部分:额外分配空格+中间空格+正常分配空格
-
计算额外空格:
extra_spaces
表示需要额外分配的空格数量,这些空格会优先分配给前面的单词间隔。 -
构建前部分字符串:
(' ' * (avg_spaces + 1)).join(line[:extra_spaces + 1])
将line
列表中前extra_spaces + 1
个单词用avg_spaces + 1
个空格连接起来,确保这些单词之间的空格数比其他单词间隔多一个。 -
添加中间部分空格:
' ' * avg_spaces
添加avg_spaces
个空格,作为中间部分的分隔符。 -
构建后部分字符串:
(' ' * avg_spaces).join(line[extra_spaces + 1:])
将line
列表中剩余的单词用avg_spaces
个空格连接起来。时间复杂度
-
外层
while
循环:- 该循环遍历整个
words
列表,每个单词最多被处理一次。因此,外层循环的时间复杂度为 O(n),其中 n 是words
的长度。
- 该循环遍历整个
-
内层
while
循环:- 内层循环用于确定当前行可以容纳的单词。由于每个单词最多只会被加入一行并处理一次,因此内层循环的时间复杂度也是 O(n)。
-
空格分配和字符串拼接:
- 对于每一行,计算空格数量和拼接字符串的操作是线性的,与当前行中单词的数量成正比。假设平均每行有 m 个单词,则这部分操作的时间复杂度为 O(m)。由于总共有 n 个单词,最坏情况下所有单词都分布在不同的行中,因此这部分操作的总时间复杂度为 O(n)。
综合以上分析,整体时间复杂度为 O(n),因为每个单词只被处理一次,并且每行的处理也是线性的。
空间复杂度
-
结果列表
res
:- 存储最终的对齐文本,其大小取决于输入单词的数量和最大宽度
maxWidth
。最坏情况下,结果列表的大小为 O(n * maxWidth),但通常情况下会小于这个值。
- 存储最终的对齐文本,其大小取决于输入单词的数量和最大宽度
-
当前行的临时列表
line
和计数器line_len
:- 这些变量用于存储当前行的单词和长度计数,空间复杂度为 O(m),其中 m 是当前行中的单词数量。由于这些变量在每次迭代后会被重置,因此不会累积占用额外空间。
-
其他辅助变量:
- 如
spaces
,avg_spaces
,extra_spaces
等,这些变量的空间复杂度为 O(1)。
综合以上分析,整体空间复杂度为 O(n * maxWidth),但在实际应用中通常会更小,因为结果列表中的每一行不会达到最大宽度。
- 如
-