文本左右对齐
题目描述:
给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。文本的最后一行应为左对齐,且单词之间不插入 额外的空格。说明:
- 单词是指由非空格字符组成的字符序列。
- 每个单词的长度大于 0,小于等于 maxWidth。
- 输入单词数组 words 至少包含一个单词。
示例
输入: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 "]
class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
List<String> result = new ArrayList<String>();
for(int i=0 ; i<words.length ;){
// 选择合适的方法填入的单词
int sumLen = words[i].length();
if(i+1<words.length && words[i].length()+words[i+1].length()+1<=maxWidth){
// 当满足至少有两个单词时
int space = 0;
// 基本筛选
int j = i+1;
for(; j<words.length && sumLen<=maxWidth-space; j++,space++){
sumLen += words[j].length();
}
if(j == words.length && sumLen <= maxWidth-space){
//特殊处理: 当j已经达到words最后一个元素时,sumLen依然小于maxWidth-space
j--;
String temp = "";
for(; i<words.length ; i++){
// 这里改变了最外层循环的i
temp += words[i]; // 添加单词
if(temp.length() < maxWidth) temp += " "; // 添加空格
}
int spaceNum = maxWidth - temp.length();
String tempSpace = "";
for(int k = 0 ; k<spaceNum ; k++){
tempSpace += " ";
}
temp += tempSpace;
result.add(temp);
continue; // 跳过以下步骤
}else{
// 恢复
j--;
sumLen -= words[j].length();
}
int[] spaceSite = new int[space-1]; // 需要填充的空格的位置以及个数
int spaceNum = space-1;
space = maxWidth - sumLen; // 待填充的空格数
// 按照左多右少,并且尽量均匀的原则分布到spaceSite数组中
int k = 0; // 其实填充位置
while(space != 0){
spaceSite[k%spaceNum]++;
k++;
space--;
}
// 处理完结果,并将其放入result中
String temp = words[i++]; // 第一个绝对是单词 注:这里改变了最外层循环的i
for(int n = 0 ; n<spaceNum && i<words.length ; n++){
String tempSpace = ""; // 当前位置的空格数
for(int m = 0 ; m<spaceSite[n] ; m++){
tempSpace += " ";
}
temp += tempSpace; // 添加空格
temp += words[i++]; // 添加单词:这里改变了最外层的i
}
result.add(temp);
}else{
// 最多放置一个单词时
String temp = words[i++]; // 这里改变了最外层的i
int spaceNum = maxWidth - temp.length();
String tempSpace = "";
for(int j = 0 ; j<spaceNum ; j++){
tempSpace += " ";
}
temp += tempSpace;
result.add(temp);
}
}
return result;
}
}
该题一定要理清思路!最好在草稿纸上模拟一番逻辑。
这里笔者的思路是将其分为两种大情况:第一种就是至少两个单词组合成文本的一行,另一种就是只有一个元素组成的文本一行。对于第一种大情况,又分为两种小情况,一种就是输入文本元素还未使用完毕,但是再添加元素就已经达到文本长度限制;另一种就是输入文本元素已经使用完毕,但是其长度小于等于文本长度限制。对于一些其它的细节:比如均匀的空格布局,这里可以采用一个while和不断重复添加到数组中来达到预期效果。
详细请看代码,读者有疑问的地方,欢迎留言。