算法题-文本左右对齐

一、题意核心理解

给定单词数组、每行最大长度 maxWidth贪心尽可能多塞单词到一行,然后补齐空格:

  1. 非最后一行、且多个单词 :两端对齐,空格左边多、右边少、均匀分配
  2. 只有一个单词 / 最后一行左对齐,单词之间只有单个空格,末尾补空格

二、核心规则

  1. 贪心:尽可能往当前行塞单词(每次能塞就塞,塞不下就换行)
  2. 非末行、多单词:
    • 空格尽可能均匀
    • 余数空格优先分给左边间隔
  3. 单行只有一个单词:单词左对齐,后面全部补空格
  4. 最后一行:全部左对齐,单词间只有 1 个空格,末尾补满空格

三、数学公式

设:

  • wordCnt:当前行单词数
  • charLen:所有单词纯字符长度总和(不含空格)
  • totalSpace = maxWidth - charLen:本行需要填充的总空格数
  • spaceCnt = wordCnt - 1:单词之间的间隔总数
  1. 每个间隔基础空格base = totalSpace / spaceCnt
  2. 多出的余数空格extra = totalSpace % spaceCnt
  • extra 个间隔:base + 1 个空格
  • 后面所有间隔:base 个空格

四、整体算法流程

  1. 遍历单词,不断收集单词,贪心凑满一行
  2. 凑不下时,处理当前行
    • 如果是最后一行 → 左对齐
    • 如果只有一个单词 → 左对齐
    • 否则 → 两端均匀对齐(左多右少)
  3. 循环直到所有行处理完毕

五、完整可直接提交 Java 代码

java

复制代码
import java.util.ArrayList;
import java.util.List;

public class Solution {
    public List<String> fullJustify(String[] words, int maxWidth) {
        List<String> res = new ArrayList<>();
        int n = words.length;

        int index = 0;
        while (index < n) {
            // 1. 贪心:选出当前行最多能装的单词 [start, index-1]
            int start = index;
            int len = 0; // 纯单词字符总长度

            while (index < n && len + words[index].length() + (index - start) <= maxWidth) {
                // (index-start) 是至少每个间隔1个空格的长度
                len += words[index].length();
                index++;
            }

            // 当前行单词数量
            int wordCnt = index - start;
            // 本行总空格数
            int totalSpace = maxWidth - len;

            StringBuilder sb = new StringBuilder();

            // 2. 判断是否为最后一行 || 只有一个单词
            if (index == n || wordCnt == 1) {
                // 左对齐:单词之间只隔1个空格
                for (int i = start; i < index; i++) {
                    sb.append(words[i]);
                    if (i != index - 1) {
                        sb.append(" ");
                    }
                }
                // 末尾补满空格
                while (sb.length() < maxWidth) {
                    sb.append(" ");
                }
            } 
            // 3. 正常行:两端对齐、均匀空格
            else {
                int spaceGap = wordCnt - 1; // 间隔数
                int base = totalSpace / spaceGap; // 基础空格
                int extra = totalSpace % spaceGap; // 左边多出来的空格

                for (int i = start; i < index; i++) {
                    sb.append(words[i]);
                    // 最后一个单词不加空格
                    if (i == index - 1) break;

                    // 前extra个间隔 多1个空格
                    int nowSpace = base;
                    if (extra > 0) {
                        nowSpace += 1;
                        extra--;
                    }
                    // 填充空格
                    for (int s = 0; s < nowSpace; s++) {
                        sb.append(" ");
                    }
                }
            }
            res.add(sb.toString());
        }
        return res;
    }
}

六、逐场景拆解

场景 1:普通多行两端对齐

空格均匀分配,余数优先左边

场景 2:单行单个单词

直接单词后面全部补空格

场景 3:最后一行

强制左对齐,间隔只有单个空格 ,末尾补空格,不平均分配

七、高频易错点

  1. ❌ 忘记最后一行特殊处理(必须左对齐)
  2. ❌ 单行只有一个单词时,错误平分空格
  3. ❌ 多余空格分给右边(正确:左边优先多空格)
  4. ❌ 贪心判断条件写错(必须包含「原有间隔 1 个空格」)
  5. ❌ 计算空格时把单词长度 + 空格长度算混

八、极简背诵总结

  1. 先贪心选一行所有单词
  2. 最后一行 / 单个单词:左对齐
  3. 普通多行:均分空格,余数左加
  4. 末尾统一补满 maxWidth