Solution 1
这道题整体来看其实就是模拟题,有两个判断逻辑:
- 合适的截断位置
- 正确的空格补充
第一种情况,只需要贪心地判定当前缓冲子串(单词+中间1个空格)的长度是否超出最大长度。
而第二种情况,则要基于当前缓冲的单词长度进行判定,首先均匀分布(商),再用余数逐个补齐。即已知最大宽度 maxWidth
,以及单词的总长度 buffer_len_words
,可以确定中间必然插入的空格有 buffer_num - 1
个,那么需要补足的额外空格有 maxWidth - buffer_len_words - buffer_num + 1
个,平均分到所有的间隙里面,每个间隙至少 space_num / (buffer_num - 1)
个额外空格,然后还有 space_num % (buffer_num - 1)
个间隙需要多补一个额外空格。
所以整道题其实难度就在于这两个逻辑判断上,写循环节比较容易出错,还是要注意一下的。
- 时间复杂度: O ( n ) O(n) O(n), n n n为输入的单词个数,遍历整个序列的长度(补足过程和最大长度实际相关,但是这里就不细致计算了,模拟题嘛)
- 空间复杂度: O ( n ) O(n) O(n), n n n为输入的单词个数,整理所有的序列所需
class Solution {
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
vector<string> ans;
int buffer_head = 0, buffer_len = 0; // 输入中的缓冲项(第几个),以及缓冲长度(算上分隔空格的字符长度)
for (int i = 0; i < words.size(); i++) {
buffer_len += words[i].size() + 1; // 加1是因为附带上最后一个空格
// cout << i << ": " << buffer_head << " - " << buffer_len << " ";
if(i == words.size() - 1) {
// 探到最后一个词
// cout << this->singleJustify(words, maxWidth, buffer_head, i, true) << endl;
ans.emplace_back(this->singleJustify(words, maxWidth, buffer_head, i, true));
}
else if (buffer_len + words[i + 1].size() > maxWidth) {
// 探到当前缓冲长度极限
// cout << this->singleJustify(words, maxWidth, buffer_head, i, false) << endl;
ans.emplace_back(this->singleJustify(words, maxWidth, buffer_head, i, false));
// 缓冲区清零
buffer_head = i + 1;
buffer_len = 0;
}
//cout << endl;
}
return ans;
}
private:
string singleJustify(vector<string>& words, int maxWidth, int buffer_head, int buffer_tail, bool final_line) {
string ans;
int buffer_num = buffer_tail - buffer_head + 1; // 当前缓冲区的单词个数
int buffer_len_words = 0;
for (int i = buffer_head; i <= buffer_tail; i++) { buffer_len_words += words[i].size(); }
int space_num = maxWidth - buffer_len_words - buffer_num + 1; // 减去单词长度,减去中间的空格个数,即为多余的空格个数
if (buffer_num == 1) {
// 只有一个词,直接补充到后面
ans += words[buffer_head];
for (int i = 0; i < space_num; ++i) {
ans += ' ';
}
}
else if (final_line) {
// 最后一行,所有的多余空格补充到后面
for (int i = 0; i < buffer_num - 1; i++) {
ans += words[buffer_head + i];
ans += ' ';
}
ans += words[buffer_tail];
for (int i = 0; i < space_num; ++i) {
ans += ' '; // 原本的空格
}
}
else {
int space_num_avg = space_num / (buffer_num - 1); // 均匀摆放
int space_num_rem = space_num % (buffer_num - 1); // 要多补一个的数量
for (int i = 0; i < buffer_num - 1; i++) {
ans += words[buffer_head + i];
int space_num_now = i < space_num_rem ? space_num_avg + 1 : space_num_avg;
for (int i = 0; i < space_num_now; ++i) {
ans += ' ';
}
ans += ' '; // 原本的空格
}
ans += words[buffer_tail];
}
return ans;
}
};
Solution 2
Soluton 1的Python实现
class Solution:
def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
ans = list()
buffer_head, buffer_len = 0, 0
for i in range(len(words)):
buffer_len += len(words[i]) + 1
if i == len(words) - 1:
ans.append(self._singleJustify(words, maxWidth, buffer_head, i, True))
elif buffer_len + len(words[i + 1]) > maxWidth:
ans.append(self._singleJustify(words, maxWidth, buffer_head, i, False))
buffer_head = i + 1
buffer_len = 0
return ans
def _singleJustify(self, words: List[str], maxWidth: int, buffer_head: int, buffer_tail: int, final_line: bool) -> str:
ans = ""
buffer_num = buffer_tail - buffer_head + 1
buffer_len_words = 0
for i in range(buffer_head, buffer_tail + 1): buffer_len_words += len(words[i])
space_num = maxWidth - buffer_len_words - buffer_num + 1
if buffer_num == 1:
ans += words[buffer_head]
for i in range(space_num):
ans += ' '
elif final_line:
for i in range(buffer_num - 1):
ans += words[buffer_head + i]
ans += ' '
ans += words[buffer_tail]
for i in range(space_num):
ans += ' '
else:
space_num_avg = space_num // (buffer_num - 1)
space_num_rem = space_num % (buffer_num - 1)
for i in range(buffer_num - 1):
ans += words[buffer_head + i]
space_num_now = space_num_avg + 1 if i < space_num_rem else space_num_avg
for i in range(space_num_now):
ans += ' '
ans += ' '
ans += words[buffer_tail]
return ans