一、概述
輸入一個字符串數組和一個數字m,其中元素是一個個單詞,對單詞進行重新組合,將一定數量的單詞按原來的順序組合在一起,在其中插入若干空格,以保證:
不是最後一行的,保證字母數量加空格數量爲m,單詞間的空格數量儘可能相同,不相同的話,保證左邊的較多,保證本行最後一個字符不是空格;
是最後一行的,保證,單詞間的空格數量都爲1,字母數量加空格小於m時,剩餘空格全加到行尾。
有點複雜,總而言之就是對一句話進行排版,分爲兩端對齊的多行。
二、分析
首先要分成兩種情況:
到最後一行和不到最後一行。
不到最後一行是普遍情況,先討論這個。主要思路就是維護兩個指針i和left,一個變量len。left指向當前行的第一個單詞,i指向當前正在處理的單詞。
對於正在處理的單詞,有三種情況:
第一種,i指向的單詞長度加上len仍然小於m,那麼就在這個單詞後插入一個空格,len加一加上單詞長度,再判斷下一個單詞——爲什麼要再加一呢?我們知道,在一行中,單詞之間至少插入一個空格,這裏的加一就是把這個空格算上了。
第二種,i指向的單詞長度加上len大於m,那麼就到上一個單詞爲止,開始準備整理成行。這裏有一個問題:最後一個單詞後面不能有空格,別急,一會判斷這個。
第三種,i指向的單詞長度加上len等於m,那麼同樣到上一個單詞爲止。
現在後兩種情況都是到上一個單詞爲止,但是第二種情況下,我們需要把上一個單詞最後的空格刪去,第三種情況下,可以把當前單詞加上——注意後面沒有空格。這樣就確定了當前行中容納的所有單詞。然後就要插入空格了,插多少呢?個數是m-len。從第一個單詞往後加到倒數第二個單詞,要是還有空格,那就從頭再繼續。
當我們到了最後一行,需要做的就是直接在行末補空格直到長度爲m即可。
代碼如下:
class Solution {
public:
vector<string> fullJustify(vector<string>& words, int maxWidth) {
int len=0,left=0,right=0,i=0;
vector<string> res;
while(i<=words.size())
{
if(i<words.size()&&len+words[i].size()<maxWidth)
{
len+=(words[i].size()+1);
words[i]+=' ';
++i;
continue;
}
if(i==words.size()||len+words[i].size()>=maxWidth)
{
if(i<words.size()&&len+words[i].size()==maxWidth)
{
len+=words[i].size();
++i;
}
else
{
words[i-1].erase(words[i-1].size()-1);
--len;
}
int exs=maxWidth-len;
right=i-1;
string tmp;
int j=0;
if(i!=words.size())
{
for(j=left;exs>0;++j)
{
words[j]+=' ';
--exs;
if(j>=right-1||j>words.size()-1)
j=left-1;
}
}
else
{
while(exs>0)
{
words[words.size()-1]+=' ';
--exs;
}
}
for(int j=left;j<=right;++j)
tmp+=words[j];
res.push_back(tmp);
if(i==words.size())
break;
len=0;
left=i;
len=0;
}
}
return res;
}
};
總而言之抓住兩點:
其一是單詞之間必須至少有一個空格;其二是維護len來繼續插入空格。
三、總結
題目本身不難,主要是邊界條件。還有後面加空格的時機:是在挑選的時候加,還是在確定之後一起加?都可以。