【Day 10】公开打卡第10天 | LeetCode 68. 文本左右对齐(贪心 + 空格分布)

1 阅读3分钟

今日打卡宣言

Day 10,坚持第十天!连续10天没断,已经进入双位数打卡阶段了。今天做了这道经典的文本左右对齐(Hard难度),代码写得比较绕,但终于跑通了。项目再忙也要坚持,冲!

LeetCode 部分

题目描述: 给定一个单词数组 words 和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。

要求:

  • 使用贪心算法:每行尽可能多放单词。
  • 行内单词之间空格要均匀分布,左侧空格不少于右侧。
  • 最后一行左对齐,右侧用空格补齐。

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

text

["This    is    an", "example  of text", "justification.  "]

核心思路

  • 贪心分组:当前行尽量多放单词,直到放不下下一个。

  • 空格分布:

    • 最后一行或单行单词 → 左对齐,右侧补空格。
    • 普通行 → 计算总空格数,平均分配到单词间隙,余数从左往右多加1个空格。

代码(你提供的C++版本,我稍作优化 + 添加详细注释):

C++

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Solution {
    string LRJustify(vector<string>& temp, int maxWidth, int curLen, bool isLast) {
        int numsRow = temp.size();
        int gapCount = numsRow - 1;  // 单词之间的间隙数
        string res;

        // 最后一行 或 只有1个单词 → 左对齐,右侧补空格
        if (isLast || numsRow == 1) {
            for (int i = 0; i < numsRow; ++i) {
                res += temp[i];
                if (i < gapCount) res += " ";
            }
            res += string(maxWidth - res.size(), ' ');
            return res;
        }

        // 左右对齐
        int allSpace = maxWidth - curLen;     // 需要填充的总空格数
        int avgSpace = allSpace / gapCount;   // 平均每个间隙的空格
        int extraSpace = allSpace % gapCount; // 余数,从左开始多加1

        for (int i = 0; i < numsRow; ++i) {
            res += temp[i];
            if (i < gapCount) {
                res += string(avgSpace, ' ');
                if (extraSpace > 0) {
                    res += " ";
                    extraSpace--;
                }
            }
        }
        return res;
    }

public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<string> res;
        vector<string> temp;   // 当前行临时存放的单词
        int curLen = 0;        // 当前行单词总字符长度(不含空格)

        for (auto& word : words) {
            // 当前行放不下这个单词了(需加上前面的空格数)
            if (curLen + temp.size() + word.size() > maxWidth) {
                res.push_back(LRJustify(temp, maxWidth, curLen, false));
                temp.clear();
                curLen = 0;
            }
            temp.push_back(word);
            curLen += word.size();
        }

        // 处理最后一行
        if (!temp.empty()) {
            res.push_back(LRJustify(temp, maxWidth, curLen, true));
        }

        return res;
    }
};

易错点 & 面试追问

  • 计算是否能放下单词时,要算上 temp.size()(已有单词间的空格数)。
  • 空格分配:余数 extraSpace 从左往右多给1个(左侧优先)。
  • 最后一行必须左对齐 + 右侧补空格。
  • 边界:只有一个单词、一行刚好满、所有单词都很短等。
  • 面试常问:如果要支持中文(双字节)怎么处理?(本题假设全是英文单词)

知识点部分

贪心 + 字符串模拟

  • 这题是典型的“贪心分组 + 均匀分配”问题,考察对边界条件的处理能力。
  • 学到的小技巧:用 temp 临时存放当前行单词,curLen 只记录单词本身长度,空格单独计算。
  • 类似题:68 这道是字符串排版里的经典,掌握后对文本处理类题目很有帮助。

今日感悟

今天刷文本左右对齐这道 Hard 题,代码逻辑比想象中绕,尤其是空格的均匀分配和最后一行处理,调试了好几次才跑通。以前看到这种模拟题就头大,今天手写完后发现只要把“分组”和“空格计算”分开想,就清晰多了。公开打卡第10天,连续10天坚持,真的有种“温水慢慢被煮开”的感觉,斗志在慢慢回来!