Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情
一、题目描述:
给定一个单词数组 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",
因为最后一行应为左对齐,而不是左右两端对齐。
第二行同样为左对齐,这是因为这行只包含一个单词。
二、思路与实现:
思路:
这题关键还是在于读懂题意,提取几个关键点
每行恰好需要有maxWidth字符,也就是说不满也得补足(包括最后一行)
每一行左右两端对齐,而最后一行左对齐,那么前面的空格都补在中间,最后一行补在后面
如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数,多出来的空格也是需要均分到前几个单词的,而不是全加到第一个单词后面(不理解的话跑下用例就知道了)
那么围绕着几个关键点就可以写代码了,主要思路就是用双指针遍历,判断单词总长度大于maxWidth时就要拼接出一行来(拼接过程就参照题目要求,具体看代码),然后慢指针指向快指针
最后快指针遍历完毕所有字符也就拼接完了
代码实现:
/**
* @param {string[]} words
* @param {number} maxWidth
* @return {string[]}
*/
var fullJustify = function (words, maxWidth) {
const res = [];
let str = "";
let tempLen = 0;
//双指针
let i = 0,
j = 0
//快指针遍历单词
while (j < words.length) {
const wordLen = words[j].length;
//如果当前行还能容纳单词,则把长度累加上占坑
if (tempLen + wordLen <= maxWidth - (j - i)) { //每个单词间至少要有一个空格,按照最极限来占位
tempLen += wordLen;
j++;
} else {
//如果当前行无法容纳单词了,则需要结算一下
//先计算需要补充的空格数
let spaceNum
const wordNum = j - i;
//用空余长度除以间隔数,如果只有一个单词moreSpace设为0
let moreSpace = (maxWidth - tempLen) % (wordNum - 1) || 0;
if (wordNum === 1) {
spaceNum = maxWidth - tempLen;
} else {
if (moreSpace === 0) {
//如果刚好除的开,则直接平分
spaceNum = (maxWidth - tempLen) / (wordNum - 1);
} else {
spaceNum = (maxWidth - tempLen - moreSpace) / (wordNum - 1);
}
}
//拼接字符串
for (let k = i; k < j; k++) {
str += words[k];
//如果空格无法均分则从左到右每个单词加一个空格,直到多余空格分配完毕
if (moreSpace-- > 0) {
str += " ";
}
//加上算好的空格数,最后一个单词不加空格(除非是唯一一个)
if (k !== j - 1 || wordNum === 1) {
for (let num = 0; num < spaceNum; num++) {
str += " ";
}
}
}
//拼接完字符串后添加到结果中去,并清空状态
res.push(str);
str = "";
tempLen = 0;
i = j; //慢指针指向快指针
}
}
//当遍历结束,判断一下最后一行还有没有单词
if (tempLen) {
//拼接字符串
for (let k = i; k < j; k++) {
str += words[k];
//最后一行除了末尾,一词一个空格,谁也不许多要!
if (k !== j - 1) {
str += " ";
}
}
//最后补空格让长度到maxWidth
while (str.length < maxWidth) {
str += " ";
}
res.push(str);
}
return res;
};
三、总结:
本题细节比较多,不好把握,分清楚情况会好解决些!