文本两端对齐算法详解:从LeetCode到实际应用
今天我们来聊一个非常经典的算法问题------文本两端对齐(Text Justification)。这个问题不仅出现在各大公司的面试中,也是文字处理软件(如Word、Pages)的核心功能之一。
问题描述
给定一个字符串数组 arr[] 和一个宽度 W,你需要格式化文本,使得每一行恰好有 W 个字符,并且左右两端对齐。具体要求如下:
- 每行尽可能多地放置单词
- 单词之间的空格需要均匀分布,无法均匀分配时,左边的空格比右边的多
- 最后一行需要左对齐,单词之间只保留一个空格,剩余空格全部放在行末
示例
输入:
arr = ["GfG", "is", "the", "best", "computer", "science", "portal", "for", "geeks."]
W = 16
输出:
GfG is the best
computer science
portal for
geeks.
核心思路
这个问题的解决思路可以分为三步:
- 贪心选词 :从当前行开始,尽可能多地选择单词,使得总长度(单词长度之和 + 单词间至少一个空格)不超过
W - 计算空格:根据选中的单词数量和总字符数,计算需要添加的空格数
- 均匀分配:将空格均匀分配到单词之间,注意最后一行特殊处理
代码实现
我整理了Python的实现版本,清晰易懂:
python
def count_characters(start, end, arr):
cnt = 0
for i in range(start, end + 1):
cnt += len(arr[i])
return cnt
def pad_line(s, W):
return s + ' ' * (W - len(s))
def justify(start, end, arr, W):
justified_line = ""
words_cnt = end - start + 1
if words_cnt == 1:
return pad_line(arr[start], W)
space_cnt = W - count_characters(start, end, arr)
space = " "
extra_spaces = 0
if end != len(arr) - 1:
space = ' ' * (space_cnt // (words_cnt - 1))
extra_spaces = space_cnt % (words_cnt - 1)
for i in range(start, end + 1):
justified_line += arr[i]
if i < end:
justified_line += space
if extra_spaces > 0:
justified_line += ' '
extra_spaces -= 1
justified_line = justified_line[:W]
return pad_line(justified_line, W)
def get_end(start, arr, W):
end = start + 1
len_words = len(arr[start])
while end < len(arr) and (len_words + 1 + len(arr[end])) <= W:
len_words += len(arr[end]) + 1
end += 1
return end - 1
def justify_text(arr, W):
start = 0
justified_text = []
while start < len(arr):
end = get_end(start, arr, W)
justified_line = justify(start, end, arr, W)
justified_text.append(justified_line)
start = end + 1
return justified_text
if __name__ == "__main__":
arr = ["GfG", "is", "the", "best", ,直接把60多种数据结构和算法做成交互式动画,连LeetCode的模拟题都能输入自定义数据跑一遍动画。更绝的是,它支持上传C/C++/Java/Python代码自动生成可视化,对着动画看指针移动,比光看文字清晰十倍。如果你是备战**408考研**或**数据结构期末考试**,这网站简直是为复习量身定制------全书级知识点配可运行代码,还能7×24小时选中代码问AI。强烈建议去"computer",
"science", "portal", "for", "geeks."]
W = 16
ans = justify_text(arr, W)
for line in ans:
print(line)
学算法最怕的就是纸上谈兵,尤其是"文本两端对齐"这种需要精细模拟排版过程的题。最近发现一个宝藏工具图码试试,把抽象算法变成看得见的动画。
图码-数据结构与算法交互式可视化平台
访问网站:https://totuma.cn
算法详解
1. 如何确定每行包含哪些单词?
使用贪心策略:从当前起始位置开始,不断尝试加入下一个单词,直到加入后总长度(单词长度之和 + 单词间至少一个空格)超过宽度 W。
2. 如何均匀分配空格?
假设这一行有 k 个单词,总字符长度为 L,那么需要添加的空格总数 spaceCnt = W - L。
- 每个单词之间的基础空格数:
spaceCnt // (k-1) - 额外需要分配的空格数:
spaceCnt % (k-1) - 这些额外空格从左边开始依次分配,每个间隙加一个空格
3. 最后一行如何处理?
最后一行特殊处理:单词之间只保留一个空格,剩余所有空格全部放在行末(左对齐)。
复杂度分析
- 时间复杂度:O(N),其中 N 是所有单词的总字符数。每个单词只会被处理一次。
- 空间复杂度:O(W),W 是每行的最大宽度,用于存储当前行的字符串。
总结
文本两端对齐是一个看似简单但实现起来有很多细节的问题。关键点在于:
- 贪心选词保证每行尽可能多的单词
- 均匀分配空格时注意左多右少的原则
- 最后一行左对齐的特殊处理
掌握了这个算法,你就掌握了文字排版的核心技术!面试中遇到这类问题,一定要先理清思路,再动手写代码。
你学会了吗? 欢迎在评论区分享你的理解或提问!
#数据结构 #算法 #面试题 #LeetCode #文本处理