面试经典150题——文本左右对齐(困难)

​"It always seems impossible until it’s done."

- Nelson Mandela

面试经典150题——文本左右对齐(困难)_第1张图片

1. 题目描述:

面试经典150题——文本左右对齐(困难)_第2张图片

这个题目标为困难题目,但是如果我们静下心来把题目读懂了,其实无非就是不同情况下不同考虑而已,也没什么思维上的复杂,还比不上我们上一篇文章讲的KMP算法烧脑。

2. 题目分析与解析

解题思路:其实用下面一张流程图就可以很好的理解并做出该题。

面试经典150题——文本左右对齐(困难)_第3张图片

其实就是一系列的情况的分类而已,并没有太复杂。

3.代码实现

首先我们来实现主循环部分,我就直接把注释写在代码里了。

public List fullJustify(String[] words, int maxWidth) {
    // 记录总的结果
    ArrayList ret = new ArrayList<>();
    // 记录当前行的单词
    ArrayList 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 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. 运行结果

面试经典150题——文本左右对齐(困难)_第4张图片

当然还有很大的优化空间,但是思路是正确的,我看了下官方思路也是相同的,优化的话就是很多for循环是不必要的,可以用join函数实现。

你可能感兴趣的:(算法,数据结构,面试)