对于每一行的单词,有三种可能:
- 一行只有一个单词,单词左对齐,然后后面多出来填充空格。
- 最后一行,左对齐,每个单词填充一个空格,然后后面多出来填充空格。
- 除了上面两种情况的常规行:一共共有maxWidth个位置,所有的单词共有wordLen,需要填充的空格数:maxWidth-wordLen。单词后填充的空格数:(maxWidth-wordLen)/(wordNums - 1)。剩余的空格为(maxWidth-wordLen)mod(wordNums - 1)依次填充到左边的空格中。
1. 按照上述思路自己想的:
java
class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
List<String> res = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int lineLen = 0;
int lineWordNum = 0;
for(int i = 0;i< words.length;i++){
// 判断是不是单行单词
int curLen = words[i].length();
if(lineWordNum == 0 && i < words.length - 1 && curLen + 1 + words[i+1].length() > maxWidth ){
sb.append(words[i]);
sb.append(repeatSpaces(maxWidth - curLen));
res.add(sb.toString());
sb = new StringBuilder();
}else {
// 常规行
if(lineLen + curLen + lineWordNum > maxWidth){
// 这一行放不下这个单词了
// 三个单词至少有两个空格 lineWordNum + 1 -1;
// 加上这个单词超出最大宽度了
int avgSpaceNum = (maxWidth - lineLen)/(lineWordNum -1);
int remainSpaceNum = (maxWidth - lineLen)%(lineWordNum -1);
for(int j = lineWordNum-1; j>=0 ;j--){
sb.append(words[i -1 -j]);
if(j != 0){
sb.append(repeatSpaces(avgSpaceNum));
if(remainSpaceNum-- > 0) sb.append(" ");
}
}
lineLen = 0;
lineWordNum = 0;
res.add(sb.toString());
sb = new StringBuilder();
i = i-1; // 返回去重新处理这个单词
}else{
// 这个单词可以放得下
lineLen += curLen;
lineWordNum++;
// 最后一行
if(i == words.length - 1){
for(int j = lineWordNum-1; j>=0 ;j--){
sb.append(words[i-j]);
if( j!= 0) sb.append(" ");
}
sb.append(repeatSpaces(maxWidth - sb.length()));
res.add(sb.toString());
}
}
}
}
return res;
}
public String repeatSpaces(int num){
StringBuilder sb = new StringBuilder();
while(num -- > 0) sb.append(" ");
return sb.toString();
}
}
使用贪心算法优化
- 应用贪心的思想,先看本行一共能装多少个单词
- 然后把情况分成两种:1.左对齐 2.常规行;简化操作。
java
class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
List<String> res = new ArrayList<>();
int n = words.length;
int i = 0;
while(i < n){
// 遍历到第i个元素
int curLen = words[i].length();
int curIndex = i + 1;
// 贪心算法,尽可能的往这一行多放单词(单词之间至少要一个空格)
while(curIndex < n){
if(curLen + 1 + words[curIndex].length() > maxWidth) break;
curLen += 1 + words[curIndex].length();
curIndex++;
}
StringBuilder sb = new StringBuilder();
int wordCount = curIndex - i;
int gaps = wordCount - 1 ;
// 情形1:左对齐的情况:最后一行或者单个单词行
if(curIndex == n || wordCount == 1){
for(int j = i;j<curIndex ;j++){
sb.append(words[j]);
if (j!=curIndex-1) sb.append(" ");
}
sb.append( repeatSpaces(maxWidth - sb.length()));
}else{
// 情形2:常规行
int spaceNum = maxWidth - curLen + gaps; // 多减的单词间的分隔空格要加回来
int avgSpaceNum = spaceNum / gaps;
int remainSpaceNum = spaceNum % gaps;
for(int j = i; j < curIndex ;j++){
sb.append(words[j]);
if(j != curIndex-1){
sb.append(repeatSpaces(avgSpaceNum));
if(remainSpaceNum-- > 0) sb.append(" ");
}
}
}
res.add(sb.toString());
i = curIndex; // 处理下一个单词
}
return res;
}
public String repeatSpaces(int num){
StringBuilder sb = new StringBuilder();
while(num -- > 0) sb.append(" ");
return sb.toString();
}
}