[LeetCode] Sentence Screen Fitting 調整螢幕上的句子
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.
這道題給我們了一個句子,由若干個單片語成,然後給我們了一個空白螢幕區域,讓我們填充單詞,前提是單詞和單詞之間需要一個空格隔開,而且單詞不能斷開,如果當前行剩餘位置放下不下某個單詞,則必須將該單詞整個移動到下一行。我剛開始想的是便利句子,每個單詞分別處理,但是這種做法很不高效,因為有可能螢幕的寬度特別大,而單詞可能就一兩個,那麼我們這樣遍歷的話就太浪費時間了,應該直接用寬度除以句子加上空格的長度之和,可以快速的得到能裝下的個數。下面這種方法設計的很巧妙,思路是用start變數來記錄下能裝下的句子的總長度,最後除以一個句子的長度,就可以得到個數。而句子的總長度的求法時要在每個單詞後面加上一個空格(包括最後一個單詞),我們遍歷螢幕的每一行,然後每次start都加上寬度,然後看all[start%len]是否為空格,是的話就start加1,這樣做的好處是可以處理末尾是沒有空格的情況,比如寬度為1,只有一個單詞a,那麼我們都知道是這樣放的 a ,start變為1,len是2,all[start%len]是空格,所以start自增1,變成2,這樣我們用start/len就知道能放下幾個了。對於all[start%len]不為空格的情況,如果all[(start-1)%len]也不為空格,那麼start就自減1,進行while迴圈,直至其為空格為止。大家可以自己帶例子嘗試,個人覺得想出此方法的人真是太聰明瞭:
解法一:
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; } };
參考資料: