【每日算法】LeetCode 68 —— 文本左右对齐(一百六十)

题目内容

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

你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ‘ ‘ 填充,使得每行恰好有 maxWidth 个字符。

要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。

文本的最后一行应为左对齐,且单词之间不插入额外的空格。

示例

示例 1:

输入:
words = [“This”, “is”, “an”, “example”, “of”, “text”, “justification.”]
maxWidth = 16
输出:
[
“This is an”,
“example of text”,
“justification. “
]

示例 2:

输入:
words = [“What”,”must”,”be”,”acknowledgment”,”shall”,”be”]
maxWidth = 16
输出:
[
“What must be”,
“acknowledgment “,
“shall be “
]
解释: 注意最后一行的格式应为 “shall be “ 而不是 “shall be”,因为最后一行应为左对齐,而不是左右两端对齐。第二行同样为左对齐,这是因为这行只包含一个单词。

示例 3:

输入:
words = [“Science”,”is”,”what”,”we”,”understand”,”well”,”enough”,”to”,”explain”,
“to”,”a”,”computer.”,”Art”,”is”,”everything”,”else”,”we”,”do”]
maxWidth = 20
输出:
[
“Science is what we”,
“understand well”,
“enough to explain to”,
“a computer. Art is”,
“everything else we”,
“do “
]

提示

1、单词是指由非空格字符组成的字符序列。
2、每个单词的长度大于 0,小于等于 maxWidth。
3、输入单词数组 words 至少包含一个单词。

题解

本题与lc65题考查的思想类似,都是把规则制定好,然后进行底代码实现即可。

根据题意,有如下思考:

1、要尽量保证除最后一行外单词的左右均匀,具体是说,除最后一行外,每行单词之间的空格可均分则直接均分,不可均分则余出来的空格从左往右加到单词空格中。

2、如果是最后一行,实现左对齐即可,且在单词行尾插入若干空格,使其达到maxWidth。

具体,请看代码实现。

代码

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;//j从下一个单词开始看
int len = words[i].size();//记录当前这一行的长度
//j指针在单词数组内且当前行数的长度+下一个单词的长度小于允许的最大长度,j指针向前移动,直到条件不成立跳出while循环
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遍历到了数组末尾,说明该行是最后一行,需要左对齐
//或者 j == i + 1 即该行仅存一个单词,也需要左对齐
line += words[i];
for(int k = i + 1; k < j; k++) line += ' ' + words[k];//将之前的空格和单词插入本行
while(line.size() < maxWidth) line += ' ';//如果插入完毕后,不足最大长度,需要在后方插入空格
}else{
//一般情况,即左右对齐且空格尽量平均分布
line += words[i];//这一行先将当前的单词加上去

int cnt = j - i - 1;//求一下一共多少个空隙
int rest_space = maxWidth - len + cnt;//求一下还有多少剩余的空间可用

int k = 0;//从第0个空隙开始
while(k < rest_space % cnt)
//rest_space % cnt 代表平均每个间隔应该有多少个空隙
//从左边数,rest_space % cnt个位置的空隙应该均为rest_space / cnt + 1,然后加上单词
line += string(rest_space / cnt + 1, ' ') + words[i + k + 1], k++;
while(k < cnt)
//剩余的空隙都是rest_space / cnt + 1个空格,然后加上单词
line += string(rest_space / cnt, ' ') + words[i + k + 1], k++;
}
res.push_back(line);//最后将本行插入答案中
i = j - 1;//更新i
}
return res;
}
};
Author: Frederic Niu
Link: https://www.fredericniu.cn/2021/06/03/【每日算法】LeetCode-68-——-文本左右对齐(一百六十)/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
我的公众号