Leetcode __806. 写字符串需要的行数

问题描述

我们要把给定的字符串 S 从左到右写到每一行上,每一行的最大宽度为100个单位,如果我们在写某个字母的时候会使这行超过了100 个单位,那么我们应该把这个字母写到下一行。我们给定了一个数组 widths ,这个数组 widths[0] 代表 ‘a’ 需要的单位, widths[1] 代表 ‘b’ 需要的单位,…, widths[25] 代表 ‘z’ 需要的单位。

现在回答两个问题:至少多少行能放下S,以及最后一行使用的宽度是多少个单位?将你的答案作为长度为2的整数列表返回。

示例 1:
输入:
widths = [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
S = “abcdefghijklmnopqrstuvwxyz”
输出: [3, 60]
解释:
所有的字符拥有相同的占用单位10。所以书写所有的26个字母,
我们需要2个整行和占用60个单位的一行。

示例 2:
输入:
widths = [4,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
S = “bbbcccdddaaa”
输出: [2, 4]
解释:
除去字母’a’所有的字符都是相同的单位10,并且字符串 “bbbcccdddaa” 将会覆盖 9 * 10 + 2 * 4 = 98 个单位.
最后一个字母 ‘a’ 将会被写到第二行,因为第一行只剩下2个单位了。
所以,这个答案是2行,第二行有4个单位宽度。

思路

  1. 26个小写字母对应数组,key-value放进map中;遍历字符串,每次判断是否都每行的边界,若当前的长度>100,则最后一个应该在下一行;若最后一个<100,则在同一行;若==100,则下次从下一行开始;每次记录行数,位置数。
  2. 优化:
    首先,分析字母与widths数组直接的对应关系,widths数组是按顺序排的,只要知道字符串中字符x出现的位置下标i,widths[i]就可以取到,即x跟’a’的之间的关系x - 'a’即为下标,widths[x - ‘a’]即为value的值;
    然后,三目运算符这时候会更快一些。

实现(思路1)

class Solution {
    public int[] numberOfLines(int[] widths, String S) {
        if (S == null || S.length() == 0) {
            return null;
        }
        Map<Character, Integer> map = new HashMap<>();
        int j = 0;
        for (char i = 'a'; i <= 'z'; i++) {
            map.put(i, widths[j++]);
        }
        int linenum = 1;
        int location = 0;
        int line = 100;
             for (int a = 0; a < S.length(); a++) {
            int v = map.get(S.charAt(a));
            if (line - v > 0) {
                line = line - v;
            } else if (line - v < 0) {
                linenum++;
                line = 100 - v;
            } else if (line - v == 0) {
                linenum++;
                line = 100;
            }
            location = 100 - line;
        }
        int[] res = new int[2];
        res[0] = linenum;
        res[1] = location;
        return res;
    }
}

耗时:4ms
时间复杂度:O(2n)

问题

  • line - v 与0的三种关系,对应着不同的操作,要具体分析每种情况。
  • 进来有字符串的时候,就是第一行,行数默认1.

实现(思路2)

class Solution {
    public int[] numberOfLines(int[] widths, String S) {
        int linenum=1;
        int curwidth=0;
        for(char x :S.toCharArray()){
            int value = widths[x-'a'];
            linenum= curwidth+value>100?linenum+1:linenum;
            curwidth= curwidth+value>100?value:curwidth+value;
        }
        return new int[]{linenum,curwidth};

    }
}

耗时:2ms
时间复杂度:O(n)

问题

三目运算符:(boolean表达式)?(表达式1):(表达式2)
结果是一个值,前面要用变量来接。

小结

看到问题不要急于开始做,要先想好,想想有没有比最基本方法好一点的方法,每个步骤,有没有优化可替代的方案,想好再开始做。

猜你喜欢

转载自blog.csdn.net/Growing_way/article/details/82771916