Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 418. Sentence Screen Fitting #418

Open
grandyang opened this issue May 30, 2019 · 0 comments
Open

[LeetCode] 418. Sentence Screen Fitting #418

grandyang opened this issue May 30, 2019 · 0 comments

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

 

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.

 

这道题给我们了一个句子,由若干个单词组成,然后给我们了一个空白屏幕区域,让我们填充单词,前提是单词和单词之间需要一个空格隔开,而且单词不能断开,如果当前行剩余位置放不下某个单词,则必须将该单词整个移动到下一行。我刚开始想的是便利句子,每个单词分别处理,但是这种做法很不高效,因为有可能屏幕的宽度特别大,而单词可能就一两个,那么我们这样遍历的话就太浪费时间了,应该直接用宽度除以句子加上空格的长度之和,可以快速的得到能装下的个数。这是对于只有一行的可以直接这么做,难点在于剩下的空格不足以放下一个单词,就得另起一行。比如例子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

LeetCode All in One 题目讲解汇总(持续更新中...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant