1. 题目来源
链接:68. 文本左右对齐
2. 题目解析
这个字符串处理的模拟题,还挺常见的。题目抽象下来就三种情况,其中笔记上的第一行是问题分析。这个比 65 题有价值多了…
这种模拟题写写也能大程度的锻炼下自己的工程能力和设计能力。
- 时间复杂度: O ( n ) O(n) O(n)。
- 空间复杂度: O ( n ) O(n) O(n)
代码:
class Solution {
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
vector<string> res;
for (int i = 0; i < words.size(); i ++ ) {
int j = i + 1; // 顺序枚举所有单词。i 是当前行起始单词,j 是当前行末尾单词。构成单词区间
int len = words[i].size(); // 存储当前行的单词长度。包含了相邻单词必带的一个空格
// 当前行能放多少单词,当前枚举单词的长度+空格+下一个单词长度在限值内,则考虑下一个单词
while (j < words.size() && len + 1 + words[j].size() <= maxWidth)
len += 1 + words[j ++ ].size();
string line; // 组织处理这一行的单词
if (j == words.size() || j == i + 1) { // 如果 j 是最后一行或者这一行只放一个单词,则左对齐
line += words[i]; // 第 i 个单词的长度
for (int k = i + 1; k < j; k ++ ) line += ' ' + words[k]; // 先组织成一个空格的左对齐形式
while (line.size() < maxWidth) line += ' '; // 补充末尾的连续空格
} else { // 左右对齐
// cnt 是单词间的待分配空格的次数,为两单词之间的间隔数
// r 是剩余未填充进去的空格数
// len 是包含了本行相邻单词的 1 个空格的单词长度。故剩余的未填充的空格数量得再补充上 cnt 个
int cnt = j - i - 1, r = maxWidth - len + cnt;
line += words[i];
int k = 0;
// 先填充空格,再填充单词,左边比右边多 1 的情况总共需要分配 r % cnt 个
while (k < r % cnt) line += string(r / cnt + 1, ' ') + words[i + k + 1], k ++ ;
// k 最多这样分配 cnt 次这样的空格。左边的多 1 的情况分配完毕,处理右边少的情况即可
while (k < cnt) line += string(r / cnt, ' ') + words[i + k + 1], k ++ ;
}
res.push_back(line);
i = j - 1;
}
return res;
}
};