68. Text Justification
问题描述:
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 " ]
解题思路:
看到题目,先理解一下题意:要我们把句子中的单词重新安排,放到长度有限的行中,每个单词用空格隔开。
除非最后一行,其他的空格要求尽可能均匀分布:左边大于右边。
重新排单词显然要遍历所有单词,在遍历所有单词的时候,将单词长度加入到现有的长度中,来判断能否加入这个单词。
有3种情况:
1.恰好等于最大长度
2.大于最大长度
3.小于最大长度
当当前长度满足或超出最大长度maxWidth时,我们可以用一个辅助方法packString来将单词均匀的分布在一行中。
在pachString中,我们用start来标识这一行开始的单词,end来标识结束的单词,rest表示剩下的空格。
首先我们现将剩下的空格均匀分布,有end-start的位置需要填充空格,初始化他们每一个都有一个空格,然后再将rest中的空格分配给他们(跟我们的更新方法有关)
求余来获取对应位置。
将单词加入新的字符串后,加入对应的空格。
我们要考虑end-start==0的情况:将唯一单词加入后,后面全部填充为空格。
再来讨论更新长度方法:
1. 先尝试加入该单词,若此时为情况3,则可以再加入一个空格。
2. 若此时为情况1: 直接调用packString并将最后的字符串压入返回数组中,此时end为i
3. 若此时为情况2: 当前长度减去该单词长度,还要减去尾部单词后的空格长度(即减1),计算剩余的空格长度,此时end为i-1。
空格个数为end-start。
注意当完成一行的时候,要更新start
最后我们要检查start是否比words.size()大,若不是,则说明最后一行结尾没有写入。
这时不需要空格均匀分布,所以我们每加入一个单词后检查长度是否查处最大宽度,若没有,则加入新的空格。
最后需用空格填充
代码:
class Solution { public: vector<string> fullJustify(vector<string>& words, int maxWidth) { vector<string> ret; int cnt = 0; int start = 0; int end = 0; for(int i = 0; i < words.size(); i++){ cnt += words[i].size(); if(cnt == maxWidth){ end = i; ret.push_back(packString(words, start, end, 0)); start = i+1; cnt = 0; }else if(cnt > maxWidth){ cnt -= words[i].size(); cnt--; string s; end = i-1; int rest = maxWidth-cnt; ret.push_back(packString(words, start, end, rest)); start = i; cnt = words[i].size() + 1; }else{ //add the space size cnt++; } } if(start < words.size()){ string s; cnt = 0; for(int i = start; i < words.size(); i++){ s += words[i]; cnt += words[i].size(); if(cnt < maxWidth){ s += " "; cnt++; } } while(cnt < maxWidth){ s.push_back(' '); cnt++; } ret.push_back(s); } return ret; } string packString(vector<string> &words, int start, int end, int rest){ cout<<start<<", "<<end<<", "<<rest<<endl; string ret; if(start == end){ ret = words[start]; while(rest > 0){ ret.push_back(' '); rest--; } return ret; } int numSpc = end-start; vector<string> spaces(numSpc ," "); for(int i = 0; i < rest; i++){ spaces[i % numSpc].push_back(' '); } for(int i = start; i < end; i++){ ret += words[i]; ret += spaces[i - start]; } ret += words[end]; return ret; } };