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 <= 3001 <= words[i].length <= 20words[i]由小寫英文字母和符號組成1 <= maxWidth <= 100words[i].length <= maxWidth
class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
List<String> ans = new ArrayList<String>();
int right = 0, n = words.length;
while (true) {
int left = right; // 當前行的第一個單詞在 words 的位置
int sumLen = 0; // 統計這一行單詞長度之和
// 循環確定當前行可以放多少單詞,注意單詞之間應至少有一個空格
while (right < n && sumLen + words[right].length() + right - left <= maxWidth) {
sumLen += words[right++].length();
}
// 當前行是最後一行:單詞左對齊,且單詞之間應只有一個空格,在行末填充剩餘空格
if (right == n) {
StringBuffer sb = join(words, left, n, " ");
sb.append(blank(maxWidth - sb.length()));
ans.add(sb.toString());
return ans;
}
int numWords = right - left;
int numSpaces = maxWidth - sumLen;
// 當前行只有一個單詞:該單詞左對齊,在行末填充剩餘空格
if (numWords == 1) {
StringBuffer sb = new StringBuffer(words[left]);
sb.append(blank(numSpaces));
ans.add(sb.toString());
continue;
}
// 當前行不只一個單詞
int avgSpaces = numSpaces / (numWords - 1);
int extraSpaces = numSpaces % (numWords - 1);
StringBuffer sb = new StringBuffer();
sb.append(join(words, left, left + extraSpaces + 1, blank(avgSpaces + 1))); // 拼接額外加一個空格的單詞
sb.append(blank(avgSpaces));
sb.append(join(words, left + extraSpaces + 1, right, blank(avgSpaces))); // 拼接其餘單詞
ans.add(sb.toString());
}
}
// blank 返回長度為 n 的由空格組成的字符串
public String blank(int n) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < n; ++i) {
sb.append(' ');
}
return sb.toString();
}
// join 返回用 sep 拼接 [left, right) 範圍內的 words 組成的字符串
public StringBuffer join(String[] words, int left, int right, String sep) {
StringBuffer sb = new StringBuffer(words[left]);
for (int i = left + 1; i < right; ++i) {
sb.append(sep);
sb.append(words[i]);
}
return sb;
}
}