[punch] LeetCode68. Align text left and right

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, you can fill in the 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:
input:
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16
 output:
[
  "This    is    an",
  "example  of text",
  "justification.  "
]

Reading questions

  1. The maximum length of each line is limited to maxWidth, which requires the left and right ends of the text to be aligned.
  2. Every line, every non ending word, must be followed by a space.
  3. When each line is not enough maxWidth, you have to add spaces between words.
  4. If the total length of a line of words is not enough maxWidth, but can not be evenly divided into word intervals, the excess spaces will be distributed from left to right in this line first. Uniformity is required.
  5. The last line of text is aligned to the left, and the tail is filled if it is not enough maxWidth.

Problem solving ideas (3 cases of c + + greedy detailed problem solving)

In fact, after reading this question, you basically have a hazy idea. Roughly distinguish three cases

  1. If the current line is the last line, align it to the left. If it is less than maxWidth, fill in the space at the end.
  2. The current line has only one word, left aligned. If it is less than maxWidth, fill in the space at the end.
  3. The current line contains more than one word and is not the last line. Then you have to calculate whether you need to insert a space. If you want to, you have to insert it.

This idea is quite intuitive. Moreover, the first and second cases are relatively easy to handle, and the third case may be a little troublesome.

The trouble lies in what we know after reading the question: if the total length of a line of words is not enough maxWidth, but can not be evenly divided into word intervals, the excess spaces will be distributed from left to right in this line first. Uniformity is required.

According to this rule, we want to know that there are several words in a line, and each interval (PIT) needs to add multiple spaces. You have to calculate the number of words eWordsCount in each line. eWordsCount - 1 is the number of pits, and maxWidth - the total length of words in each line. eLineLen degree is equal to the total number of spaces to be supplemented, eBlankCount. Then we can calculate the minimum number of spaces eAvg to be filled in each pit, that is, eAvg = eBlankCount / (eWordsCount - 1);, However, it may not be evenly divided. Fill in from left to right according to the meaning of the question. The total amount of extrablank = eBlankCount% (eWordsCount - 1);.

Case 3, for example:

Code (with detailed comments)

class Solution {
public:
    vector<string> fullJustify(vector<string> &words, int maxWidth) {
        // result
        vector<string> res;
        int size = words.size();
        // Start and end of each line
        int eLeft = 0, eRight = 0;
        // Record the word length and length of each line
        int eLineLen = 0;
        // Number of words in the current line
        int eWordsCount = 0;
        // The length of the current line that needs to be filled
        int eBlankCount = 0;
        // The minimum number of spaces to be filled in the current line
        int eAvg = 0;
        // The number of extra spaces in the current line after completing the pit of two word Jane
        int extraBlank = 0;
        while(1) {
            eLeft = eRight;
            eLineLen = 0;
            
            // Judgment: the existing length of the current line + the length of the next word + the number of spaces to be added after each word < = 20
            while (eRight < size && eLineLen + words[eRight].length() + eRight - eLeft <= maxWidth) {
                eLineLen += words[eRight++].length();
            }
​
            // Case 1: the current line is the last line
            if (eRight == size) {
                // Words are left justified and there should be only one space between words
                string s = words[eLeft];
                for (int i = eLeft + 1; i < size; i++) {
                    s += ' ' + words[i];
                }
                //Fill in the remaining spaces at the end of the line
                res.push_back(s + string(maxWidth - s.length(), ' '));
                return res;
            }
​
            // Number of words in the current line
            eWordsCount = eRight - eLeft;
​
            // The length of the current line that needs to be filled
            eBlankCount = maxWidth - eLineLen;
​
            // Case 2: the current line has only one word
            if (eWordsCount == 1) {
                // Align words to the left and fill in the remaining spaces at the end of the line
                res.push_back(words[eLeft] + string(eBlankCount, ' '));
                continue;
            }
​
            /* Case 3: the current line has more than one word
             First, calculate the minimum number of missing spaces between two words in each line, because it may be redundant. For example, there are 8 spaces missing in a line, but if there are 3 word intervals, you can't get an average score. Try to be as uniform as possible according to the meaning of the question, and the left takes precedence.
             Here I deal with the spaces that should be after each word together with the missing spaces, without distinction.
             */
            eAvg = eBlankCount / (eWordsCount - 1); 
            extraBlank = eBlankCount % (eWordsCount - 1);
​
            string s1 = "";
            for (int i = eLeft; i < eRight; i++) {
                if (i == eRight - 1) {
                    s1 += words[i];
                }else {
                    if (i - eLeft < extraBlank) {
                        s1 += words[i] + string(eAvg + 1, ' ');
                    }else {
                        s1 += words[i] + string(eAvg, ' ');
                    }
                }
            }
            res.push_back(s1);
        }
        return res;
    }
};

other

If you feel this solution is helpful to you, please don't be stingy and praise it 👍🏻 Ah, go, go

Tags: Front-end Algorithm leetcode greedy algorithm

Posted on Sat, 20 Nov 2021 02:57:28 -0500 by Beauchy