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 "
]
方法1:
喜刷刷:http://bangbingsyb.blogspot.com/2014/11/leetcode-text-justification.html
思路:
class Solution {
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
int start = 0, end = -1, totLen = 0;
bool isLast = false;
vector<string> result;
int i = 0;
while (i < words.size()) {
if (words[i].size() > maxWidth) return result;
int newLen = totLen + (end - start + 1) + words[i].size();
if (newLen <= maxWidth) {
end = i;
totLen += words[i].size();
i++;
}
else {
string line = createLine(words, maxWidth, start, end, totLen, false);
result.push_back(line);
start = i;
end = i - 1;
totLen = 0;
}
}
string lastLine = createLine(words, maxWidth, start, end, totLen, true);
result.push_back(lastLine);
return result;
}
string createLine(vector<string> & words, int L, int start, int end, int totLen, bool isLast) {
string ret;
if (start < 0 || end >= words.size() || start > end) return ret;
ret.append(words[start]);
int n = end - start + 1;
if (n == 1 || isLast) {
for (int i = start + 1; i<= end; i++) {
ret += " " + words[i];
}
int j = L -totLen - (n - 1);
ret += string(j, ' ');
return ret;
}
int k = (L - totLen) / (n - 1), m = (L - totLen) % (n - 1);
for (int i = start + 1; i <= end; i++) {
int nspace = i - start <= m ? k + 1 : k;
ret += string(nspace, ' ');
ret += words[i];
}
return ret;
}
};
submission:
num:向前累计本行能放下的单词,len:本行累加的总单词长度。words[i + num].size() + len <= L - num, 这里是 左边是之前总长+新单词长 ,右边是maxWidth - num,去掉中间至少一个的空格条件下所允许的最长字符限制。如果成立,可以再多放一个单词,并且将长度累计,index前进。
出循环后已经收集了应该本行的单词范围,在 i 到 i + num这个区间内,首先tmp放入第一个单词words[i],接下来需要计算单词间应该有多少个空格。(L - len) / (num - 1) 是每个单词间应该至少插入的空格数,除此之外,前 m = (L - len) % (num - 1) 个间隔应该
class Solution {
public:
vector<string> fullJustify(vector<string> &words, int L) {
vector<string> ans;
const int n = words.size();
for (int i = 0; i < n;) {
int num = 0, len = 0;
while (i + num < n && words[i + num].size() + len <= L - num) {
len += words[i + num].size();
++num;
}
string tmp = words[i];
for (int j = 1; j < num; ++j) {
if (i + num >= n) tmp += " ";
else tmp += string((L - len) / (num - 1) + (j <= (L - len) % (num - 1)), ' ');
tmp += words[i + j];
}
tmp += string(L - tmp.size(), ' ');
ans.push_back(tmp);
i += num;
}
return ans;
}
};
https://www.tianmaying.com/tutorial/LC68
class Solution {
string getALine(vector<string>& words, int maxWidth, int start, int end) {
// 处理words.size() = 0的情况
if (start > end) return string(maxWidth, ' ');
// 只有1个单词的情况
if (start == end) return words[ start ] + string(maxWidth - words[ start ].size(), ' ');
string ret = "";
int totLen = 0;
// 统计单词长度
for (int i = start; i <= end; ++i)
totLen += words[i].size();
// 计算间隔
int space = (maxWidth - totLen) / (end - start);
int rest = (maxWidth - totLen) % (end - start);
// 如果是最后一行特殊处理
if (end == words.size() - 1) space = 1, rest = 0;
// 处理出该行字符串
ret += words[ start ];
for (int i = start + 1; i <= end; ++i) {
ret += string(space, ' ');
if (i - start <= rest) ret += ' ';
ret += words[i];
}
// 最后一行的特殊处理
ret += string(maxWidth - ret.size(), ' ');
return ret;
}
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
int prev = 0; // 表示该行起点的位置
int len = -1; // 方便处理第一次计算
for (int i = 0; i < words.size(); ++i) {
if (len + 1 + words[i].size() <= maxWidth)
len += 1 + words[i].size(); // 在紧凑放置的情况下仍然不超过 L
else {
ret.push_back( getALine(words, maxWidth, prev, i - 1) ); // 处理prev到i-1这一行
// 新的一行
len = words[i].size();
prev = i;
}
}
ret.push_back( getALine(words, maxWidth, prev, words.size() - 1) );
return ret;
}
};