• [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.

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

  • 相关阅读:
    C# winform判断窗体是否已打开
    对象与json字符串转换类设计
    Redis 操作帮助类
    C# redis客户端帮助类
    RedisHelper Redis帮助类
    Vue.js实现tab切换效果
    Uni-app 使用总结
    C#中的委托和事件(续)
    12小时超级马拉松赛记
    2016年8月份
  • 原文地址:https://www.cnblogs.com/grandyang/p/5975426.html
Copyright © 2020-2023  润新知