美文网首页算法提高之LeetCode刷题数据结构
【算法】Text Justification 文本对齐

【算法】Text Justification 文本对齐

作者: 无良剑染 | 来源:发表于2020-01-24 21:26 被阅读0次

    题目

    Given an array of words and a width maxWidth, format the text such that each line has exactly maxWidth characters and is fully (left and right) justified.

    You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly maxWidth characters.

    Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

    For the last line of text, it should be left justified and no extra space is inserted between words.

    Note:

    A word is defined as a character sequence consisting of non-space characters only.
    Each word's length is guaranteed to be greater than 0 and not exceed maxWidth.
    The input array words contains at least one word.
    Example 1:

    Input:
    words = ["This", "is", "an", "example", "of", "text", "justification."]
    maxWidth = 16
    Output:
    [
       "This    is    an",
       "example  of text",
       "justification.  "
    ]
    

    Example 2:

    Input:
    words = ["What","must","be","acknowledgment","shall","be"]
    maxWidth = 16
    Output:
    [
      "What   must   be",
      "acknowledgment  ",
      "shall be        "
    ]
    

    Explanation: Note that the last line is "shall be " instead of "shall be",
    because the last line must be left-justified instead of fully-justified.
    Note that the second line is also left-justified becase it contains only one word.

    Example 3:

    Input:
    words = ["Science","is","what","we","understand","well","enough","to","explain",
             "to","a","computer.","Art","is","everything","else","we","do"]
    maxWidth = 20
    Output:
    [
      "Science  is  what we",
      "understand      well",
      "enough to explain to",
      "a  computer.  Art is",
      "everything  else  we",
      "do                  "
    ]
    

    给出一组单词 words ,一个长度 maxWidth ,返回一个字符串数组满足如下条件:

    1. 所有字符长度均为 maxWidth
    2. 单词不可切割
    3. 每行字符串中,每个单词之间的空格大于等于 1 ,且均等分
    4. 如无法均等分,则左边的空格数比右边的多
    5. 最后一行单词之间只有一个空格,剩余空间用空格补齐

    解题思路

    主要就是计算每行字符串所需的单词 索引范围空格数量 ,最后一行的处理也有些不同:

    1. 动态字符串长度 strCount,头位置 from ,尾位置 to,单词个数 wordCount = to - from + 1
    2. 判断条件就是 strCount + (当前单词长度)word.count + wordCount - 1 > mixWidth 时,from ~ to-1 就是符合条件的单词索引范围
    3. from ~ to-1 单词数量判断空格区间有几个:
      • 单词数量<3时有一个,空格长度为 maxWidth - word.count,添加到单词后面
      • 单词数量>3时有 单词数量 - 1 个
      • 较大空格数量 larCount = (maxWidth - wordsLen) % (wordsCount - 1)
      • 空格长度 spaceLen = (maxWidth - wordsLen) / (wordsCount - 1)
      • 头 larCount 个空格区域有 spaceLen+1,之后都是 spaceLen 个空格
      • 最后一个单词后面注意不添加空格
    4. 最后一行单词和空格交叉添加,最后位数不足用空格补齐

    代码实现

    Runtime: 8 ~ 20 ms
    Memory: 21 MB

    func fullJustify(_ words: [String], _ maxWidth: Int) -> [String] {
            //添加字符串的数组
            var result = [String]()
            //动态字符串长度 strCount,头位置 from 尾位置to
            var strCount = 0, from = 0, to = 0
            //循环条件,to 在 words 范围内
            while to < words.count {
                // 空格数 spaceCount = to - from
                // 字符数 + spaceCount > maxWidth , 或者 to 不在 words 范围中时,跳出循环,
                while to < words.count && strCount + words[to].count + to - from <= maxWidth {
                    //循环条件内,添加动态字符串长度
                    strCount += words[to].count
                    //to 后移一位
                    to += 1;
                }
                // to 指向最后一个单词,应该跳出循环处理最后一行字符串
                if to == words.count {
                    break
                }
                // from ~ to-1 的单词加上空格数满足条件,进行处理
                let strEl = self.fillSpace(words, maxWidth: maxWidth, from: from, to: to - 1, wordsLen: strCount)
                //将处理后的字符串添加进 result 中
                result.append(strEl)
                // 将 from 指向 to
                from = to
                // 重置 strCount 为 0
                strCount = 0
            }
            //处理最后一行字符串
            let strEl = self.fillLastLine(words, maxWidth: maxWidth, from: from, to: to - 1, wordsLen: strCount)
            result.append(strEl)
            //返回结果
            return result
        }
    
        func fillSpace(_ words: [String], maxWidth: Int, from: Int, to: Int, wordsLen: Int) -> String{
            var resStr = ""
            let space = "*"
            //单词数量 wordsCount
            let wordsCount = to - from + 1
            //较大空格的数量 larCount
            var larCount = 0
            //空格的长度 spaceLen
            var spaceLen : Int = 1
            if wordsCount<3 {
                //单词数量小于3时,larCount=0,spaceLen=maxWidth - wordsLen
                spaceLen = maxWidth - wordsLen
            }else{
                //单词数量大于等于3时,计算 larCount ,spaceLen
                larCount = (maxWidth - wordsLen) % (wordsCount - 1)
                spaceLen = (maxWidth - wordsLen) / (wordsCount - 1)
            }
            //from ~ to 单词加空格赋值给 resStr
            for idx in from ... to {
                resStr += words[idx]
                var spaceLen1 = spaceLen
                if larCount>0 {
                    //若 larCount大于0,索命本次空格数量为 spaceLen + 1
                    spaceLen1 += 1
                    // larCount - 1
                    larCount -= 1
                }
                //若不是最后一个单词,且并非只有一个单词时,添加空额
                //若是最后一个单词,且只有一个单词时,添加空格
                if (idx != to && wordsCount != 1) || (idx == to && wordsCount == 1)  {
                    for _ in 0 ..< spaceLen1 {
                        resStr += space
                    }
                }
            }
            //返回结果
            return resStr
        }
        func fillLastLine(_ words: [String], maxWidth: Int, from: Int, to: Int, wordsLen: Int) -> String {
            var resStr = ""
            let space = "*"
            //如果 from 小于 to
            if from < to {
                // from ~ to-1 单词和空格 加值到 resStr
                for idx in from ..< to {
                    resStr += words[idx] + space
                }
            }
            // resStr 加最后一个单词
            resStr += words[to]
            //剩余空间用空格补齐
            let starNum = maxWidth - resStr.count
            for _ in 0 ..< starNum {
                resStr += space
            }
            //返回结果
            return resStr
        }
    

    代码地址:https://github.com/sinianshou/EGSwiftLearning

    相关文章

      网友评论

        本文标题:【算法】Text Justification 文本对齐

        本文链接:https://www.haomeiwen.com/subject/bvfhthtx.html