携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第32天,点击查看活动详情
68. 文本左右对齐
给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。
你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。
要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
文本的最后一行应为左对齐,且单词之间不插入额外的空格。
注意:
单词是指由非空格字符组成的字符序列。 每个单词的长度大于 0,小于等于 maxWidth。 输入单词数组 words 至少包含一个单词。
「示例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 <= words.length <= 300
1 <= words[i].length <= 20
words[i] 由小写英文字母和符号组成
1 <= maxWidth <= 100
words[i].length <= maxWidth
解题思路
对齐规则:
最后一行
单词左对齐
单词间空格数为一
非最后一行
单词左右对齐
单词间空格均匀分布
无法均匀分布时, 左侧空格数多于右侧空格数.
递归的最小重复单元(形成输出数组 res 的一个字符串)
Recursion terminatior (递归终止)
递归遍历到数组 words 的末尾
Process logic in current level (当前层的过程逻辑)
非最后一行
确定 words 中能加入该行字符串的个数, 并将字符串保存到数组 rowArr .
对数组 rowArr 进行"处理", 形成符合非最后一行规则的字符串, 保存到数组 res .
最后一行
确定 words 中能加入该行字符串的个数, 并将字符串保存到数组 rowArr .
对数组 rowArr 进行"处理", 形成符合最后一行规则的字符串, 保存到数组 res .
Drill down (去下一层)
return appendLine(words, maxWidth, res, i)
i: 对应下一次递归, 加入数组 rowArr 的首个字符串, 在数组 words 中的下标.
res: 要输出的数组
Reverse the current level status if needed (进行下一层的操作之后, 会回到这里. 可以在这里做一些收尾的工作.)
res.pop()
删去数组数组 res 最后一个数组. 这样在递归结束时, 数组 res 可以清空.
代码实现
/**
* @param {string[]} words
* @param {number} maxWidth
* @return {string []}
*/
var fullJustify = function(words, maxWidth) {
const appendLine = (level, words, maxWidth, res, start) => {
// Recursion terminatior (递归终止)
if (start >= words.length) {
return res;
}
// Process logic in current level (当前层的过程逻辑)
let rowArr = [words[start]];
let count = words[start].length;
let i = start + 1;
while (i < words.length && count + words[i].length < maxWidth) {
count += words[i].length + 1;
rowArr.push(words[i]);
i ++;
}
let rowStr = '';
if (i < words.length) {
let space = maxWidth - count + rowArr.length - 1;
let eachSpace = parseInt(space / (rowArr.length - 1));
let extSpace = space % (rowArr.length - 1);
for (let j = 0; j < rowArr.length; j ++) {
rowStr += rowArr[j];
if (j !== rowArr.length - 1) {
let space = eachSpace;
if (extSpace > 0) {
space += 1;
extSpace --;;
}
while (space -- > 0) {
rowStr += ' ';
}
}
}
} else {
for (let j = 0; j < rowArr.length; j ++) {
if (j < rowArr.length - 1) {
rowStr += rowArr[j] + ' ';
} else {
rowStr += rowArr[j];
}
}
}
while (rowStr.length < maxWidth) {
rowStr += ' ';
}
res.push(rowStr);
// Drill down (去下一层)
return appendLine(level + 1, words, maxWidth, res, i);
// Reverse the current level status if needed (进行下一层的操作之后, 会回到这里. 可以在这里做一些收尾的工作.)
res.pop();
}
return appendLine(0, words, maxWidth, [], 0);
};
如果你对这道题目还有疑问的话,可以在评论区进行留言;
\