"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());}// 清0lineRet.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函数实现。