给定一个单词数组和一个长度 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",
因为最后一行应为左对齐,而不是左右两端对齐。
第二行同样为左对齐,这是因为这行只包含一个单词。
上面的题目描述还是略显啰嗦,我整理了一下
- 尽可能多地往每行中放置单词
- 均匀分配单词间的空格数量,如果不能均匀,左侧放置的空格数要多于右侧的空格数
- 如果一行只能包含一个单词,左对齐
- 文本的最后一行应为左对齐,且单词之间不插入额外的空格。
我的解答
/**
* 68. 文本左右对齐(贪心,字符串,hard)<br>
* https://leetcode-cn.com/problems/text-justification/<br>
* 代码丑长,但ac87%,可以继续优化<br>
* 估计只有刚写完的自己看得懂<br>
* 踩了一些坑,还是要细心,考虑周全<br>
*
* @author wuwang
*
*/
class Solution {
public List<String> fullJustify(String[] words, final int maxWidth) {
int index = 0;
final char sp = ' ';
ArrayList<String> result = new ArrayList<>();
while (index < words.length) {
StringBuilder sb = new StringBuilder();
int len = 0, count = 0, scount = 0;
// 贪心greddy
while (index + count < words.length && (len + words[index + count].length()) <= maxWidth) {
len += words[index + count].length();
++count;
if (len < maxWidth) {
++len;
++scount;
} else if (index + count < words.length) {
if (len + words[index + count].length() == maxWidth) {
++count;
len += words[index + count].length();
}
break;
}
}
len -= scount;// 所有单词的长度
// 最后一行,左对齐,单词间不插入额外的空格
if ((index + count) == (words.length)) {
// System.out.printf("%s %s %s\n", index, count, words.length);
int l = 0, i = index;
for (; i < (words.length - 1); ++i) {
sb.append(words[i]);
sb.append(sp);
l += words[i].length() + 1;
}
sb.append(words[i]);// 最后一个单词无空格
l += words[i].length();
while (l < maxWidth) {// 补空格
sb.append(sp);
++l;
}
} else if (count > 1) {// 一行多个单词,且尽可能均匀空格,如不能,左边空格多余右边
int spaceHolderCount = count - 1;// 要填空格的空白处
int spaceCount = maxWidth - len;// 空格数量
// System.out.printf("%d %d\n", spaceHolderCount, spaceCount);
for (int i = 0; i < count; ++i) {
sb.append(words[index + i]);
int n = 0;
if (spaceHolderCount != 0)
n = spaceCount / spaceHolderCount + ((spaceCount % spaceHolderCount) == 0 ? 0 : 1);// 运算符优先级的一个坑
// n = spaceCount / spaceHolderCount +( (spaceCount % spaceHolderCount) == 0 ? 0
// n = spaceCount / spaceHolderCount + spaceCount % spaceHolderCount == 0 ? 0:1;
// 二目运算符优先级大于三目
for (int j = 0; j < n; ++j) {// 填空格
sb.append(sp);
}
spaceHolderCount -= 1;
spaceCount -= n;
}
} else {// 只有一个单词,左对齐补空格即可
sb.append(words[index]);
for (int i = words[index].length(); i < maxWidth; ++i)
sb.append(sp);
}
index += count;
result.add(sb.toString());
}
return result;
}
}