Given a rows x cols
screen and a sentence represented by a list of words, find how many times the given sentence can be fitted on the screen.
Note:
- A word cannot be split into two lines.
- The order of words in the sentence must remain unchanged.
- Two consecutive words in a line must be separated by a single space.
- Total words in the sentence won't exceed 100.
- Length of each word won't exceed 10.
- 1 ≤ rows, cols ≤ 20,000.
Example 1:
Input: rows = 2, cols = 8, sentence = ["hello", "world"] Output: 1 Explanation: hello--- world--- The character '-' signifies an empty space on the screen.
Example 2:
Input: rows = 3, cols = 6, sentence = ["a", "bcd", "e"] Output: 2 Explanation: a-bcd- e-a--- bcd-e- The character '-' signifies an empty space on the screen.
Example 3:
Input: rows = 4, cols = 5, sentence = ["I", "had", "apple", "pie"] Output: 1 Explanation: I-had apple pie-I had-- The character '-' signifies an empty space on the screen.
這道題給我們了一個句子,由若干個單詞組成,然后給我們了一個空白屏幕區域,讓我們填充單詞,前提是單詞和單詞之間需要一個空格隔開,而且單詞不能斷開,如果當前行剩余位置放不下某個單詞,則必須將該單詞整個移動到下一行。我剛開始想的是便利句子,每個單詞分別處理,但是這種做法很不高效,因為有可能屏幕的寬度特別大,而單詞可能就一兩個,那么我們這樣遍歷的話就太浪費時間了,應該直接用寬度除以句子加上空格的長度之和,可以快速的得到能裝下的個數。這是對於只有一行的可以直接這么做,難點在於剩下的空格不足以放下一個單詞,就得另起一行。比如例子2中的第二行,a后面有三個空格,無法同時放下空格和bcd,所以bcd只能另起一行了。所以並不是每個位子都是可用的,我們需要記錄有效空位的個數。還是拿例子2來舉例,句子的總長度的求法時要在每個單詞后面加上一個空格(包括最后一個單詞),所以需要匹配的字符串是 a_bcd_e_,一共8個字符。每行有6個空位,我們用變量start來記錄有效位的個數,先加上第一行的空位數,那么start即為6,我們先算start%len=6%8=6,然后all[6] = 'e',不是空格,不會進入if循環。為啥要判斷這個呢,由於題目中說了如果某個單詞剛好填滿一行時,之后就不用加空格了,下一個單詞可以從下一行的首位置開始,就像例子3中的第二行一樣。那么什么時候會進入if從句呢,當 all[start%len]==' ' 的時候,此時start應該自增1,因為雖然剩余的位置剛好填滿了單詞,后面不用再加空格了,但是我們再算有效空位個數的時候還是要加上這個空格的。然后我們開始處理第二行,start再加上這行的長度,此時start為12,算start%len=12%8=4,然后all[4] = 'd',不是空格,不進入if從句。我們進入else從句,這里我們需要移除不合法的空位,此時我們需要算 (start-1)%len = 3,all[3] = 'c',不為空,所以start自減1,為11。然后再算(start-1)%len = 2,all[2] = 'b',不為空,所以start自減1,為10。然后再算(start-1)%len = 1,all[1] = ' ',為空,跳出循環。我們在第二行減去了2個不合法的空位,再來到第三行,start再加上這行的長度,此時start為16,算start%len=16%8=0,然后all[0] = 'a',不是空格,不進入if從句。我們進入else從句,這里我們需要移除不合法的空位,此時我們需要算 (start-1)%len = 7,all[7] = ' ',為空,跳出循環。最后用start/len=16/8=2,即為最終答案,參見代碼如下:
解法一:
class Solution { public: int wordsTyping(vector<string>& sentence, int rows, int cols) { string all = ""; for (string word : sentence) all += (word + " "); int start = 0, len = all.size(); for (int i = 0; i < rows; ++i) { start += cols; if (all[start % len] == ' ') { ++start; } else { while (start > 0 && all[(start - 1) % len] != ' ') { --start; } } } return start / len; } };
下面這種方法也是很棒,同樣也需要統計加空格的句子總長度,然后遍歷每一行,初始化colsRemaining為cols,然后還需要一個變量idx,來記錄當前單詞的位置,如果colsRemaining大於0,就進行while循環,如果當前單詞的長度小於等於colsRemaining,說明可以放下該單詞,那么就減去該單詞的長度就是剩余的空間,然后如果此時colsRemaining仍然大於0,則減去空格的長度1,然后idx自增1,如果idx此時超過單詞個數的范圍了,說明一整句可以放下,那么就有可能出現寬度遠大於句子長度的情況,所以我們加上之前放好的一句之外,還要加上colsRemaining/len的個數,然后colsRemaining%len是剩余的位置,此時idx重置為0,參見代碼如下:
解法二:
class Solution { public: int wordsTyping(vector<string>& sentence, int rows, int cols) { string all = ""; for (string word : sentence) all += (word + " "); int res = 0, idx = 0, n = sentence.size(), len = all.size(); for (int i = 0; i < rows; ++i) { int colsRemaining = cols; while (colsRemaining > 0) { if (sentence[idx].size() <= colsRemaining) { colsRemaining -= sentence[idx].size(); if (colsRemaining > 0) colsRemaining -= 1; if (++idx >= n) { res += (1 + colsRemaining / len); colsRemaining %= len; idx = 0; } } else { break; } } } return res; } };
參考資料:
https://leetcode.com/problems/sentence-screen-fitting/
https://leetcode.com/problems/sentence-screen-fitting/discuss/90849/accepted-java-solution
https://leetcode.com/problems/sentence-screen-fitting/discuss/90845/21ms-18-lines-java-solution