Leetcode: 68. Align text left and right

Keywords: Python leetcode greedy algorithm

subject

Source: LeetCode
Link: https://leetcode-cn.com/problems/text-justification

Given an array of words and a length maxWidth, rearrange the words into text with exactly maxWidth characters per line and aligned left and right ends.
You should use "greedy algorithm" to place a given word; That is, put as many words in each line as possible. If necessary, it can be filled with space '' so that each line has exactly maxWidth characters.
It is required to distribute the number of spaces between words as evenly as possible. If the spaces between words in a line cannot be evenly distributed, the number of spaces placed on the left is more than the number of spaces on the right.
The last line of text should be left justified and no additional spaces should be inserted between words.

explain:
A word is a sequence of characters consisting of non whitespace characters.
The length of each word is greater than 0 and less than or equal to maxWidth.
The input word 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 format of the last line should be "shall be" instead of "shall be",
    Because the last row should be left aligned, not left and right aligned.
    The second line is also left justified because 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                            "
]

solution

Greedy algorithm plus double pointer

  • Greedy algorithm is to judge the maximum number of words in each line. After all, it is added in order
  • Double pointers are used to determine the number of words in each line

According to the greedy algorithm described by the stem, for each line, we first determine how many words can be placed at most, so as to get the number of spaces in the line, so as to determine the number of spaces between words in the line.

According to the details of filling in the blanks in the title, we discuss it in the following three cases:

The current line is the last line: the words are left aligned, and there should be only one space between the words. Fill in the remaining spaces at the end of the line;
The current line is not the last line, and there is only one word: align the word to the left, and fill in spaces at the end of the line;
The current line is not the last line, and there is more than one word: set the number of words in the current line as numWords and the number of spaces as numSpaces

def blank(n: int) -> str:
    return ' ' * n


class Solution:
    def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
        ans = []
        right = 0
        n = len(words)
        while True:
            left = right  # The position of the first word in the current line in words
            sumLen = 0
            while right < n and sumLen + len(words[right]) + right - left <= maxWidth:
                sumLen += len(words[right])
                right += 1
            
            # When words cannot be added to this line, start branch judgment. The last line is not the last line
            # 1. The current line is the last line: the words are left aligned, and there should be only one space between the words. Fill in the remaining spaces at the end of the line
            if right == n:
                s = ' '.join(words[left: right])
                ans.append(s+blank(maxWidth-len(s)))
                break
            
            numWords = right - left
            numSpaces = maxWidth - sumLen

            # 2. If the current line is not the last line and the line has only one word, fill in the remaining spaces at the end
            if numWords == 1:
                ans.append(words[left] + blank(numSpaces))
                continue
            
            # 3. When the current line is not the last line and there is more than one word in the line, the number of spaces placed in the words on the left is more than that on the right
            avgSpaces = numSpaces // (numWords - 1) # average number of spaces
            extraSpaces = numSpaces % (numWords - 1)  # It can also indicate the number of words that need to add an additional space
            s1 = blank(avgSpaces + 1).join(words[left: left + extraSpaces + 1])  # Splice the number of words to the left of the word with an additional space
            s2 = blank(avgSpaces).join(words[left + extraSpaces + 1: right])  # Splice the words to the right of the remaining words
            ans.append(s1 + blank(avgSpaces) + s2)
        return ans

Complexity analysis

  • Time complexity: O(m), where m is the sum of the lengths of all strings in the array words
  • Space complexity: O(m)

Posted by ozzythaman on Fri, 10 Sep 2021 01:02:00 -0700