文章目录
- 写在前面
- Tag
- 题目来源
- 解题思路
- 方法一:模拟
- 写在最后
写在前面
本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……
专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:
- Tag:介绍本题牵涉到的知识点、数据结构;
- 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
- 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
- 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
- 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。
Tag
【数组】【字符串】【模拟】
题目来源
68. 文本左右对齐
解题思路
方法一:模拟
思路
根据题目中提示使用贪心算法,我们可以知道,对于每一行,我们首先需要确定最多可以放置多少个单词,这样根据 maxWidth
就可以确定该行的空格数,从而确定该行单词之间的空格数量。
根据题目中的填充空格的细节,我们可以分为以下三种情况进行讨论:
- 当前行是最后一行:单词需要左对齐,并且单词之间只需要一个空格,剩下的空格填充在行末;
- 当前行不是最后一行,且只有一个单词,在行末填充空格;
- 当前行不是最后一行,且有多个单词:设当前行可以放置的单词数为
numWords
,空格数为numSpaces
,我们需要将空格均匀分布在单词之间,则单词之间空格数至少有 a v g S p a c e s = ⌊ n u m S p a c e s n u m W o r d s − 1 ⌋ avgSpaces = \lfloor{\frac{numSpaces}{numWords - 1}}\rfloor avgSpaces=⌊numWords−1numSpaces⌋。对于多出的空格 e x t r a S p a c e s = n u m S p a c e s m o d ( n u m W o r d s − 1 ) extraSpaces = numSpaces mod (numWords - 1) extraSpaces=numSpacesmod(numWords−1),应填充在前 e x t r a S p a c e s extraSpaces extraSpaces 个单词之后。因此前 e x t r a S p a c e s extraSpaces extraSpaces 个单词之间填充 a v g S p a c e s + 1 avgSpaces + 1 avgSpaces+1 个空格,其余单词之间填充avgSpaces
个空格。
代码
class Solution {
private:
// 返回长度为 n 的由空格组成的字符串
string blank(int n) {
return string(n, ' ');
}
// 返回用 sep 拼接 [left, right) 范围内 words 组成的字符串
string join(vector<string>& words, int left, int right, string sep) {
string s = words[left];
for (int i = left + 1; i < right; ++i) {
s += sep + words[i];
}
return s;
}
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
vector<string> res;
int right = 0, n = words.size();
while (true) {
int left = right; // 当前行的第一个单词在 words 的位置
int sumLen = 0;
// 循环确定当前行可以放多少个单词,注意单词之间至少有一个空格
while (right < n && sumLen + words[right].length() + right - left <= maxWidth) {
sumLen += words[right++].length();
}
// 当前行是最后一行:单词左对齐,且单词之间只有一个空格,在行末填充剩余空格
if (right == n) {
string s = join(words, left, n, " ");
res.emplace_back(s + blank(maxWidth - s.length()));
return res;
}
int numWords = right - left;
int numSpaces = maxWidth - sumLen;
// 当前行只有一个单词:单词左对齐,空格都放在末尾
if (numWords == 1) {
res.emplace_back(words[left] + blank(numSpaces));
continue;
}
// 当前行不止一个单词
int avgSpaces= numSpaces / (numWords - 1);
int extraSpaces = numSpaces % (numWords - 1);
string s1 = join(words, left, left + extraSpaces + 1, blank(avgSpaces + 1));
string s2 = join(words, left + extraSpaces + 1, right, blank(avgSpaces));
res.emplace_back(s1 + blank(avgSpaces) + s2);
}
return res;
}
};
复杂度分析
时间复杂度:
O
(
m
)
O(m)
O(m),
m
m
m 是数组 words
中所有字符串的长度之和。
空间复杂度: O ( m ) O(m) O(m)。
写在最后
如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家有更优的时间、空间复杂度的方法,欢迎评论区交流。
最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。