今日打卡宣言
Day 10,坚持第十天!连续10天没断,已经进入双位数打卡阶段了。今天做了这道经典的文本左右对齐(Hard难度),代码写得比较绕,但终于跑通了。项目再忙也要坚持,冲!
LeetCode 部分
- 题目链接:leetcode.cn/problems/te…
- 难度:困难
- 时间复杂度:O(n)(n为所有单词总字符数)
题目描述: 给定一个单词数组 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天坚持,真的有种“温水慢慢被煮开”的感觉,斗志在慢慢回来!