"It always seems impossible until it’s done."
- Nelson Mandela
1. 题目描述:
这个题目标为困难题目,但是如果我们静下心来把题目读懂了,其实无非就是不同情况下不同考虑而已,也没什么思维上的复杂,还比不上我们上一篇文章讲的KMP算法烧脑。
2. 题目分析与解析
解题思路:其实用下面一张流程图就可以很好的理解并做出该题。
其实就是一系列的情况的分类而已,并没有太复杂。
3.代码实现
首先我们来实现主循环部分,我就直接把注释写在代码里了。
public List<String> fullJustify(String[] words, int maxWidth) {
// 记录总的结果
ArrayList<String> ret = new ArrayList<>();
// 记录当前行的单词
ArrayList<String> lineRet = new ArrayList<>();
// 记录当前行的字符串长度
int len = 0;
// 记录当前行有多少个单词
int wordCount = 0;
// 开始遍历每个单词
for (int i = 0; i < words.length; i++) {
String word = words[i];
// +1是因为要保证每一个单词后有至少要有一个空格
int strLen = word.length() + 1;
// 加入当前行的总长
len += strLen;
// 可以放入当前行(len-1是因为一行的最后一个单词后没有空格)
if (len - 1 <= maxWidth) {
//当是最后一行
if (i == words.length - 1) {
StringBuilder lastLine = new StringBuilder();
// 最后一行的单词之间只有一个空格,末尾要加空格
for (String item : lineRet) {
lastLine.append(item).append(" ");
}
// 加上当前单词
lastLine.append(word);
// 补充结尾空格
for (int j = lastLine.length(); j < maxWidth; j++) {
lastLine.append(" ");
}
ret.add(lastLine.toString());
// 不是最后一行
} else {
lineRet.add(word);
wordCount++;
}
// 放不下当前行
} else {
// 如果只有一个单词,左对齐
if (wordCount == 1) {
// 计算要补上的空格数
int spaceLen = maxWidth - lineRet.get(0).length();
StringBuilder sb = new StringBuilder();
// 补上空格
for (int j = 0; j < spaceLen; j++) {
sb.append(" ");
}
String spaces = sb.toString();
ret.add(lineRet.get(0) + spaces);
// 如果包含很多个单词,那就左右对齐,同时保证空格数尽量平均,且左边更多
} else {
// 改行总共应该有多少个空格
int spaceCount = maxWidth - len + strLen + wordCount;
// 包装函数获取左右对齐的字符串,sb即为当前行结果
StringBuilder sb = getSb(spaceCount, wordCount, lineRet);
ret.add(sb.toString());
}
// 清0
lineRet.clear();
len = 0;
wordCount = 0;
i--;
}
}
return ret;
}
现在我们来看一下对于包含很多个单词,左右对齐,同时保证空格数尽量平均,且左边更多的过程的函数getSb(spaceCount, wordCount, lineRet)。
/**
* 获取左右对齐的字符串
*
* @param spaceCount 总共的空格数
* @param wordCount 当前行单词数
* @param lineRet 当前行的单词
* @return 左右对齐的字符串
*/
private static StringBuilder getSb(int spaceCount, int wordCount, ArrayList<String> lineRet) {
// 计算每个间隔平均放几个空格
int space = spaceCount / (wordCount - 1);
// 多余的空格
int extraSpace = spaceCount % (wordCount - 1);
StringBuilder sb = new StringBuilder();
for (int j = 0; j < lineRet.size(); j++) {
sb.append(lineRet.get(j));
// 最后一个单词后不加空格
if (j != lineRet.size() - 1) {
for (int k = 0; k < space; k++) {
sb.append(" ");
}
// 每一次进来就相当于从左到右加一个多余的空格,那么我左边肯定比右边空格多
if (extraSpace > 0) {
sb.append(" ");
extraSpace--;
}
}
}
return sb;
}
好了代码到这就完成了,是不是很easy?遇到困难题不要慌,没准就是吓唬吓唬你!
4. 运行结果
当然还有很大的优化空间,但是思路是正确的,我看了下官方思路也是相同的,优化的话就是很多for循环是不必要的,可以用join函数实现。