1. 程式人生 > >[LeetCode] Sentence Screen Fitting 調整螢幕上的句子

[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:

  1. A word cannot be split into two lines.
  2. The order of words in the sentence must remain unchanged.
  3. Two consecutive words in a line must be separated by a single space.
  4. Total words in the sentence won't exceed 100.
  5. Length of each word won't exceed 10.
  6. 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;
    }
};

參考資料: