1. 问题背景与核心挑战
LeetCode 68题"文本左右对齐"是一个经典的字符串处理问题,要求将一组单词按照给定的最大宽度进行排版,同时满足特定的对齐规则。这个问题看似简单,但实际涉及多个技术难点:
- 单词分组策略:如何确定每行放置哪些单词
- 空格分配算法:如何在单词间合理分配空格数量
- 特殊行处理:最后一行与其他行的不同处理方式
- 性能优化:如何在O(n)时间复杂度内完成处理
我在实际解决这个问题时,发现很多初学者容易陷入以下误区:
- 试图一次性计算所有行的布局
- 忽略最后一行左对齐的特殊要求
- 空格分配算法不够优雅导致代码冗长
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 贪心算法设计思路
2.1 算法核心思想
贪心算法在这里的应用体现在:每次尽可能多地放置单词到当前行。这种局部最优的选择最终会导向全局最优解。具体步骤:
- 初始化当前行单词列表和字符计数
- 遍历单词列表,判断能否加入当前行:
- 当前行单词总长度 + 最少空格数 ≤ maxWidth
- 最少空格数 = 单词数 - 1
- 当无法加入时,处理当前行的对齐
- 最后单独处理末行
2.2 关键变量设计
python复制def fullJustify(words, maxWidth):
res, cur, num_of_letters = [], [], 0
for w in words:
# 判断当前单词能否加入当前行
if num_of_letters + len(w) + len(cur) > maxWidth:
# 处理当前行对齐
...
# 加入当前行
cur.append(w)
num_of_letters += len(w)
# 处理最后一行
...
return res
3. 空格分配算法详解
3.1 常规行空格分配
对于非最后一行,空格分配需要满足:
- 所有额外空格均匀分配
- 左边空格数多于右边
实现方案:
- 计算总空格数:maxWidth - 当前行字母总长度
- 计算基本空格数:total_spaces // (num_words - 1)
- 计算额外空格:total_spaces % (num_words - 1)
python复制def justify_line(words, maxWidth):
if len(words) == 1:
return words[0].ljust(maxWidth)
total_spaces = maxWidth - sum(len(w) for w in words)
space_between = total_spaces // (len(words) - 1)
extra_spaces = total_spaces % (len(words) - 1)
line = []
for i in range(len(words)-1):
line.append(words[i])
line.append(' ' * (space_between + (1 if i < extra_spaces else 0)))
line.append(words[-1])
return ''.join(line)
3.2 末行特殊处理
末行需要左对齐且单词间只加一个空格:
python复制def justify_last_line(words, maxWidth):
line = ' '.join(words)
return line.ljust(maxWidth)
4. 完整Python实现与优化
4.1 最终实现代码
python复制def fullJustify(words, maxWidth):
res, cur, num_of_letters = [], [], 0
for w in words:
if num_of_letters + len(w) + len(cur) > maxWidth:
for i in range(maxWidth - num_of_letters):
cur[i % (len(cur)-1 or 1)] += ' '
res.append(''.join(cur))
cur, num_of_letters = [], 0
cur += [w]
num_of_letters += len(w)
res.append(' '.join(cur).ljust(maxWidth))
return res
4.2 性能优化技巧
- 使用列表而非字符串拼接:在Python中,列表append操作比字符串拼接效率更高
- 原地修改空格:通过索引直接修改列表元素,减少中间变量
- 合并循环:将空格分配和字符串构建合并到一个循环中
5. 常见错误与调试技巧
5.1 典型错误案例
-
索引越界:处理单单词行时未做特殊判断
python复制# 错误示例 space_between = total_spaces // (len(words) - 1) # 当len(words)=1时除零错误 -
空格计算错误:未考虑单词间至少一个空格的基本要求
python复制# 错误示例 total_spaces = maxWidth - sum(len(w) for w in words) # 忘记减去(len(words)-1) -
末行处理不当:对所有行使用相同的对齐逻辑
5.2 调试建议
-
使用小规模测试用例:
python复制print(fullJustify(["This", "is", "an"], 16)) -
添加中间输出:
python复制print(f"Current line: {cur}, letters: {num_of_letters}") -
边界条件测试:
- 单个单词
- 单词长度等于maxWidth
- 空输入
6. 算法复杂度分析
-
时间复杂度:O(n),其中n是所有单词字符总数
- 每个单词只被处理一次
- 空格分配操作与单词数成正比
-
空间复杂度:O(m),其中m是输出行数
- 存储结果需要额外空间
- 临时变量空间恒定
7. 实际应用场景
这种文本对齐算法在以下场景有实际应用:
- 文档编辑器自动排版
- 终端输出格式化
- 报表生成系统
- 网页内容渲染
我在开发Markdown解析器时就遇到过类似需求,需要将纯文本按照指定宽度进行优雅换行和对齐。理解这个算法后,可以轻松应对各种文本排版需求。
