优美编程

Leetcode-报数

2019-12-30  本文已影响0人  小遁哥

0.题目

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。

输入 输出 报数 写作
1 1 一个一 11
2 11 两个一 21
3 21 一个二, 一个一 1211
4 1211 一个一,一个二, 两个一 111221
5 111221 三个一,两个二, 一个一 312211
6 312211 一个三,一个一, 两个二,两个一
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。

核心就是按顺序从左到右统计每个数字出现的个数,遇到不同的,则用${count}${number}表示上一次的统计。

1.递归解

 var countAndSay = function(n) {
      if (n == 1) {
        return "1";
      }

      let last = countAndSay(n - 1);

      let list = [...last];

      let count = 1;
      let str = "";
      for (let i = 0; i < list.length - 1; i++) {
        if (list[i] == list[i + 1]) {
          count++;
        } else {
          str += count + "" + list[i];
          count = 1;
        }
      }
      str += `${count}${list[list.length - 1]}`;
      return str;
    };

因为使用 list[i] == list[i + 1]作判定,所以在for循环结束后需要 str += `${count}${list[list.length - 1]}`; 处理最后一次的统计,实际开发容易忽略,改进如下:

   var countAndSay = function(n) {
      if (n == 1) {
        return "1";
      }

      let last = countAndSay(n - 1);

      let list = [...last];

      let str = "";
      for (let i = 0, count = 1; i < list.length; i++) {
        if (list[i] == list[i + 1]) {
          count++;
        } else {
          str += `${count}${list[i]}`;
          count = 1;
        }
      }

      return str;
    };

尽管遍历到最后一个元素 list[i] == list[i + 1] 中的 list[i + 1] 必定是undefined,但不会引发错误,反而执行了最后一次统计的逻辑。

2.双重for循环解法

这种正向推理的案例用递归处理,在逻辑有些绕,毕竟要先一层一层深入到n 等于1,在一层一层回到n等于5

var countAndSay = function(n) {
    let s = '1'
    for (let i = 1; i < n; i++) {
        let result = ''
        for (let i = 1, currentChar = s[0], currentCount = 1; i <= s.length; i++) {
            if (s[i] === currentChar) {
                currentCount++
            } else {
                result += `${currentCount}${currentChar}`
                currentChar = s[i]
                currentCount = 1
            }
        }
        s = result
    }
    return s
};

3.正则解

上述对数字的统计正则也可以做到。

   var countAndSay = function(n) {
      let prev = "1";
      for (let i = 1; i < n; i++) {
        prev = prev.replace(/(\d)\1*/g, (item) => `${item.length}${item[0]}`);
      }
      return prev;
    };

4. 做成数组

对于结果固定的答案,下面的解法也值得参考,或是用一些记忆函数,比如lodash的memoize

image.png

视频地址

上一篇 下一篇

猜你喜欢

热点阅读