当前位置: 首页 > news >正文

LeetCode 68:文本左右对齐

LeetCode 68:文本左右对齐

在这里插入图片描述

问题定义与核心挑战

给定单词数组 words 和最大行宽 maxWidth,需将单词排版为每行恰好 maxWidth 个字符的文本,满足:

  1. 贪心排版:每行尽可能多放单词(优先填满)。
  2. 空格规则
    • 最后一行或单行单词:左对齐,单词间一个空格,剩余空格补在末尾。
    • 其他行:空格均匀分配,若无法均分,左侧间隔的空格数多于右侧

核心思路:分组 + 空格精细化分配

  1. 分组单词:逐行确定能容纳的单词(考虑单词间至少一个空格)。
  2. 空格计算
    • 对每组单词,计算总空格数,区分最后一行/单行普通行的分配逻辑。
  3. 构造行字符串:根据空格规则拼接单词和空格,确保长度严格为 maxWidth

算法步骤详解

步骤 1:分组单词(贪心排版)

遍历单词,逐步累加,确定每行能容纳的单词:

  • 初始状态currentLine 存储当前行单词,currentLen 记录当前行已用长度(初始为 0)。
  • 遍历逻辑
    • 若当前行空,直接加入单词,currentLen 设为单词长度。
    • 否则,计算加入下一个单词后的长度(需加 1 个空格),若不超过 maxWidth 则加入,否则当前行闭合,开始新行。
List<List<String>> lines = new ArrayList<>();
List<String> currentLine = new ArrayList<>();
int currentLen = 0;for (String word : words) {if (currentLine.isEmpty()) {currentLine.add(word);currentLen = word.length();} else {int nextLen = currentLen + 1 + word.length(); // 加1是单词间的空格if (nextLen <= maxWidth) {currentLine.add(word);currentLen = nextLen;} else {lines.add(currentLine); // 闭合当前行currentLine = new ArrayList<>();currentLine.add(word);currentLen = word.length();}}
}
if (!currentLine.isEmpty()) { // 处理最后一行lines.add(currentLine);
}
步骤 2:处理每行的空格分配

对每组单词,分两种情况处理:

情况 1:最后一行 或 单行单词(左对齐)
  • 单词间用 1 个空格 连接,剩余空格补在行尾
情况 2:普通行(空格均匀分配)
  • 计算总空格数:totalSpaces = maxWidth - 单词总长度
  • 间隔数:gaps = 单词数 - 1(如 3 个单词有 2 个间隔)。
  • 基础空格:base = totalSpaces / gaps(每个间隔的基本空格数)。
  • 多余空格:extra = totalSpaces % gaps(前 extra 个间隔需多 1 个空格)。
步骤 3:构造行字符串

根据上述规则,拼接单词和空格:

List<String> result = new ArrayList<>();
for (int i = 0; i < lines.size(); i++) {List<String> line = lines.get(i);int numWords = line.size();int totalSpaces = maxWidth;for (String word : line) { // 计算单词总长度,得到需分配的空格数totalSpaces -= word.length();}StringBuilder sb = new StringBuilder();if (numWords == 1 || i == lines.size() - 1) { // 最后一行或单行sb.append(String.join(" ", line)); // 单词间1个空格int remaining = maxWidth - sb.length(); // 补全行尾空格for (int j = 0; j < remaining; j++) {sb.append(" ");}} else { // 普通行,均匀分配空格int gaps = numWords - 1;int base = totalSpaces / gaps;int extra = totalSpaces % gaps;for (int j = 0; j < numWords; j++) {sb.append(line.get(j));if (j < gaps) { // 非最后一个单词,加空格int spaceCount = base + (j < extra ? 1 : 0); // 前extra个间隔多1个空格for (int k = 0; k < spaceCount; k++) {sb.append(" ");}}}}result.add(sb.toString());
}

完整代码(Java)

import java.util.ArrayList;
import java.util.List;class Solution {public List<String> fullJustify(String[] words, int maxWidth) {// 步骤1:分组单词,确定每行的单词List<List<String>> lines = new ArrayList<>();List<String> currentLine = new ArrayList<>();int currentLen = 0;for (String word : words) {if (currentLine.isEmpty()) {currentLine.add(word);currentLen = word.length();} else {int nextLen = currentLen + 1 + word.length();if (nextLen <= maxWidth) {currentLine.add(word);currentLen = nextLen;} else {lines.add(currentLine);currentLine = new ArrayList<>();currentLine.add(word);currentLen = word.length();}}}if (!currentLine.isEmpty()) {lines.add(currentLine);}// 步骤2:处理每行的空格,构造结果List<String> result = new ArrayList<>();for (int i = 0; i < lines.size(); i++) {List<String> line = lines.get(i);int numWords = line.size();int totalSpaces = maxWidth;for (String word : line) {totalSpaces -= word.length();}StringBuilder sb = new StringBuilder();if (numWords == 1 || i == lines.size() - 1) {// 最后一行或单行:左对齐,补空格到末尾sb.append(String.join(" ", line));int remaining = maxWidth - sb.length();for (int j = 0; j < remaining; j++) {sb.append(" ");}} else {// 普通行:均匀分配空格,左侧间隔多int gaps = numWords - 1;int base = totalSpaces / gaps;int extra = totalSpaces % gaps;for (int j = 0; j < numWords; j++) {sb.append(line.get(j));if (j < gaps) {int spaceCount = base + (j < extra ? 1 : 0);for (int k = 0; k < spaceCount; k++) {sb.append(" ");}}}}result.add(sb.toString());}return result;}
}

关键逻辑解析

1. 分组的贪心策略
  • 优先填满行:每次尝试加入下一个单词,仅当超过 maxWidth 时才闭合当前行,保证每行单词数最多。
2. 空格分配的细节
  • 最后一行:单词间仅 1 个空格,剩余空格补在末尾(如示例 1 中最后一行 "justification. ")。
  • 普通行:通过 baseextra 确保空格均匀,左侧间隔多(如示例 1 中第一行 "This is an",两个间隔各 4 个空格)。
3. 边界处理
  • 单行单词(如 ["a"]maxWidth=5):直接左对齐,补 4 个空格到行尾("a ")。

示例验证(以示例 1 为例)

输入words = ["This","is","an","example","of","text","justification."], maxWidth=16

行索引单词列表处理逻辑输出字符串
0["This","is","an"]普通行,空格数 8,间隔 2 → 每个间隔 4 个空格"This is an"
1["example","of","text"]普通行,空格数 5,间隔 2 → 前 1 个间隔 3 个空格,后 1 个间隔 2 个空格 → "example of text"(实际计算:example(7)+3+of(2)+2+text(4)=7+3+2+2+4=18?不对,哦,重新计算:单词总长度7+2+4=13,maxWidth=16,空格数3。间隔数2,base=1,extra=1。所以前1个间隔2个空格,后1个间隔1个空格 → 7+2+2+1+4=16 → "example of text"
2["justification."]最后一行,左对齐,补 1 个空格 → "justification. "

该方法通过贪心分组精细化空格分配,严格满足题目规则,高效处理所有边界情况,是文本排版问题的经典实现。

http://www.dtcms.com/a/302262.html

相关文章:

  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘papermill’问题
  • Docker搭建Hadoop集群
  • 进程管理(systemd)
  • 企业微信服务商创建第三方应用配置数据回调url和指令回调url的java代码实现
  • Python系统交互库全解析
  • Entity Framework Core (EF Core) 中Database
  • 归雁思维:解锁自然规律与人类智慧的桥梁
  • Online Proofing System(OPS)在线校样系统使用说明
  • Linux进程概念(五)进程地址空间
  • Leaflet 综合案例 - 路径规划
  • 医疗领域非结构化数据处理技术突破与未来演进
  • svn与git Merge重要区别讲解
  • C# 提取字符串 指定开始和结尾字符
  • 人机交互打字游戏
  • C#高级:通过修改注册表实现系统代理服务器的启用、编辑和禁用
  • 【计算机网络】计算机网络中光猫、交换机、路由器、网关、MAC地址是什么?两台电脑是如何联通的?
  • 承装修试二级承包范围
  • 3DGRUT: 革命性的3D高斯粒子光线追踪与混合光栅化技术深度解析
  • mac电脑如何关闭防火墙
  • 反欺诈系统:Oracle 到 ES 迁移实战
  • keepalive
  • 8.异常处理--Exceptions
  • 代码随想录Day32:动态规划(斐波那契数、爬楼梯、使用最小花费爬楼梯)
  • 字节跳动开源Coze,开启AI Agent开发新时代?
  • 我从 Web2 转型到 Web3 的 9 条经验总结
  • linux命令grep的实际应用
  • Leetcode——11. 盛最多水的容器
  • kubectl中的yaml配置详解
  • 前段面试题新版
  • 从fork到exit:剖析Linux进程的诞生、消亡机制