题目:
给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。
你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' '
填充,使得每行恰好有 maxWidth 个字符。
要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
文本的最后一行应为左对齐,且单词之间不插入额外的空格。
说明:
- 单词是指由非空格字符组成的字符序列。
- 每个单词的长度大于 0,小于等于 maxWidth。
- 输入单词数组
words
至少包含一个单词。
示例:
输入: words = ["This", "is", "an", "example", "of", "text", "justification."] maxWidth = 16 输出: [ "This is an", "example of text", "justification. " ]
示例 2:
输入: words = ["What","must","be","acknowledgment","shall","be"] maxWidth = 16 输出: [ "What must be", "acknowledgment ", "shall be " ] 解释: 注意最后一行的格式应为 "shall be " 而不是 "shall be", 因为最后一行应为左对齐,而不是左右两端对齐。 第二行同样为左对齐,这是因为这行只包含一个单词。
示例 3:
输入: words = ["Science","is","what","we","understand","well","enough","to","explain", "to","a","computer.","Art","is","everything","else","we","do"] maxWidth = 20 输出: [ "Science is what we", "understand well", "enough to explain to", "a computer. Art is", "everything else we", "do " ]
思路:
这道题需要考虑的方面相对多一点,需要仔细理清思路。
扫描二维码关注公众号,回复:
3600199 查看本文章
首先,看完题目我们可以了解有以下限制条件:
1. 每行首尾两单词是两端对齐的,中间的空格数是先均匀分布,然后再从左往右分布剩下的。
2. 中间存在一个单词的,直接靠左,剩余补全空格。
3. 最后一行无需两端对齐,每个单词间一个空格即可。
知道以上条件后,我们可以先求出所需要的行数,每个单词所在的行数标签。
然后再求出每个单词间的空格数,且存入string对象。
循环多次,即可得到vector<string>对象。
该思路所对应的程序是注释掉的,由于比较繁琐,所以参考了网上更优的方法。它的思路和本思路类似,但是它是一边处理一边存储,效率高很多。
程序:(注释掉的是自己写的,非注释是后来参考别人的)
class Solution {
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
vector<string> res;
int left = 0; // 行索引
int wordsNum = words.size();
while(left < wordsNum){
int right = left, len = 0;
while(right<wordsNum && len+words[right].size()+right-left<=maxWidth)
len += words[right++].size(); // right - left : 首尾两单词间空格数
string temp;
int space = maxWidth - len; // 行空格数
for(int i=left;i<right;i++){ // right:行单词数
temp += words[i];
if(space > 0){ // 单词后加空格
int snum; // 单词间空格数
if(right == wordsNum){ // 最后一行
if(right-i == 1) // 只有一个单词
snum = space;
else
snum = 1;
}
else{ // 前几行
if(right-i-1 > 0){ // right-1: 行单词数尾下标 [0,right-1]
if(space%(right-i-1) == 0)
snum = space/(right - i - 1);
else
snum = space/(right - i - 1) + 1;
}
else // 只有一个元素
snum = space;
}
temp.append(snum,' ');
space -= snum; // 更新剩余空格数
}
}
res.push_back(temp);
left = right; // 更新行索引
}
return res;
/* int rest = maxWidth;
int space = 0;
int wordsNum = words.size();
int row = 0;
cout << "num: " << wordsNum << endl;
int index[wordsNum] = {0};
int wordsLen = 0;
for (int i=0;i<wordsNum;i++){
int tmp_i = i;
wordsLen = words[i].size();
if (rest >= (wordsLen + space)){ // 4 >= 15 ?
rest = rest - wordsLen - space;
space = 1;
}
else{
++row; // 总行数
i = tmp_i - 1;
space = 0;
rest = maxWidth;
}
if (i == tmp_i){
index[i] = row; // 各个单词的所在行
cout << index[i] << endl;
}
}
int wordsOfRow[row+1] = {0}; // 每行的字符数
int rowArr[row+1] = {0}; // 每行的单词数
int spaceAdd = 0;
int tmp = 0;
vector<string> str;
int in = 0; // 行首索引
for (int j=0;j<row+1;j++){
for (int i=0;i<wordsNum;i++){ // 每行的单词数和字符个数
if (index[i] == j){
wordsOfRow[j] += words[i].size();
rowArr[j]++;
}
}
string tmpS;
tmp = rowArr[j] - 1; // 空格位数
if (tmp == 0){ // 当行只有一个单词时
tmpS = tmpS + words[in];
for (int sp=0;sp<maxWidth-words[in].size();sp++){
tmpS = tmpS + " ";
}
str.emplace_back(tmpS);
in++; // 行索引加1
cout << words[in-1] << endl;
}
else{ // 正常情况
int spaceArr[tmp+1] = {0}; // 空格组
int spaceSum = maxWidth - wordsOfRow[j];
int avrg = spaceSum/tmp;
spaceAdd = spaceSum % tmp;
for (int k=0;k<tmp;k++){
spaceArr[k] = avrg;
}
for (int k=0;k<spaceAdd;k++){
spaceArr[k] += 1;
}
if (j == row){ // 当最后一行时
tmpS = words[in];
int l=1;
for (;l<rowArr[j];l++){
tmpS = tmpS + " " + words[in+l];
}
tmpS.append((spaceSum-rowArr[j]+1),' ');
}
else{
for (int l=0;l<rowArr[j];l++){
tmpS = tmpS + words[in+l];
for (int sp=0;sp<spaceArr[l];sp++){
tmpS = tmpS + " ";
}
}
}
str.emplace_back(tmpS);
in += rowArr[j]; // 修正行首索引
}
}
return str;*/
}
};