「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
题目描述
给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。
你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。
要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
文本的最后一行应为左对齐,且单词之间不插入额外的空格。
说明:
- 单词是指由非空格字符组成的字符序列。
- 每个单词的长度大于 0,小于等于 maxWidth。
- 输入单词数组
words至少包含一个单词。
示例1:
输入: words = ["This", "is", "an", "example", "of", "text", "justification."] maxWidth = 16 输出: [ "This is an", "example of text", "justification. " ]
解法:滑动窗口
分析:核心就是每组可以组成一行的 i - j 个窗口,然后在每个窗口内计算出空格space的数量,依次分配给各个字符串。
具体步骤:
设每一缓存行,一个数组来缓存单词的索引,一个长度变量来缓存当前已占用长度,一个长度变量缓存总单词长度。
不均衡空格的分配思路:
- 如总数10个空格分给4个位置,算出平均每个each = 10/4 =2
- 由于10%4!=0,第一个位置的空格数为each +1,然后剩下7个分3个位置
- 7%3!=0,第二个位置空格数为each+1,然后剩下4个分两个位置
- 最后得出空格块分别为3,3,2,2
class Solution {
//文本居中
private String textAlignCenter(String[] words,int start,int end,int lineLen,int maxWidth){
int space = maxWidth - lineLen,gap = end - start;
StringBuilder sb = new StringBuilder();
if(gap == 0){
sb.append(words[start]);
while(sb.length() < maxWidth) sb.append(' ');
return sb.toString();
}
int mod = space % gap,div = space / gap;
sb.append(words[start]);
for(int i = start + 1;i <= end;i++){
if(mod-- > 0)
sb.append(' ');
for(int j = 0;j < div;j++)
sb.append(' ');
sb.append(words[i]);
}
return sb.toString();
}
//文本左对齐
private String textLeftJustify(String[] words,int start,int end,int lineLen,int maxWidth){
StringBuilder sb = new StringBuilder();
sb.append(words[start]);
for(int i = start + 1;i <= end;i++){
sb.append(' ').append(words[i]);
}
while(sb.length() < maxWidth)
sb.append(' ');
return sb.toString();
}
public List<String> fullJustify(String[] words, int maxWidth) {
//lineHead表示每行第一个单词索引,lineTail表示每行最后一个单词索引,lineLen表示每行单词总长度(不计空格)
int lineHead = 0,lineTail = 0,lineLen = 0;
int n = words.length;
List<String> res = new ArrayList<>();
for(int i = 0;i < n;i++){
String word = words[i];
if(lineLen + word.length() + i - lineHead > maxWidth){
lineTail = i - 1;
res.add(textAlignCenter(words,lineHead,lineTail,lineLen,maxWidth));
lineHead = i--;
lineLen = -word.length();
}
lineLen += word.length();
}
res.add(textLeftJustify(words,lineHead,n - 1,lineLen,maxWidth));
return res;
}
}