最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • [ 力扣38 ] 外观数列|刷题打卡

    正文概述 掘金(Orime小猪)   2021-03-09   738

    [ 力扣38 ] 外观数列|刷题打卡

    题目名称:外观数列

    给定一个正整数 n ,输出外观数列的第 n 项。

    「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。

    你可以将其视作是由递归公式定义的数字字符串序列:

    countAndSay(1) = "1"

    countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。 前五项如下:

    1.     1
    2.     11
    3.     21
    4.     1211
    5.     111221
    

    第一项是数字 1

    描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"

    描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"

    描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"

    描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"

    要描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。

    要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。

    例如,数字字符串 "3322251" 的描述如下图:

    示例 1:
    
    输入:n = 1
    输出:"1"
    解释:这是一个基本样例。
    
    示例 2:
    
    输入:n = 4
    输出:"1211"
    解释:
    countAndSay(1) = "1"
    countAndSay(2) = 读 "1" = 一 个 1 = "11"
    countAndSay(3) = 读 "11" = 二 个 1 = "21"
    countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"
    

    解法

    一、递归

    • 条件表达式为 countAndSay(n) = countAndSay(n-1);
    • 递归终止条件为 n === 1返回1
    /**
     * @param {number} n
     * @return {string}
     */
    var countAndSay = function (n) {
      if (n === 1) {
        return "1"
      }
      // * table 存储
      // const dp = [null, '1', '11']
      // for(let i = 3; i <= n; i++){
      //   dp[i] = getStr(dp[i-1])
      // }
      // return dp[n]
      // * 变量替换
      let dp = "11"
      for (let i = 3; i <= n; i++) {
        dp = getStr(dp)
      }
      return dp
    }
    
    /**
     * * 如果'21',从前向后比较,如果str[i] === str[i+1],则 count++;否则 现在的count进行结算 res += String(count) + String(val)
     * * 重置
     * @param {*} str
     */
    function getStr(str) {
      // '21' ---> '1211'
      let count = 1,
        res = ""
      for (let i = 0; i < str.length; i++) {
        const val = str[i]
        if (val === str[i + 1]) {
          count++
          if (i === str.length - 1) {
            res += String(count) + String(val)
            break
          }
        } else {
          res += String(count) + String(val)
          count = 1
        }
      }
      return res
    }
    

    二、正则表达式

    /**
     * * 解法二:正则表达式操作字符串 
     * @param {number} n
     * @return {string}
     */
    var countAndSay1 = 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
    }
    
    
    • 原理说明:

    [ 力扣38 ] 外观数列|刷题打卡

    测试用例

    // 测试用例
    let test = 1
    let test1 = 4
    let test2 = 5
    
    console.time("执行用时")
    console.log(countAndSay(test))
    console.timeEnd("执行用时")
    console.time("执行用时")
    console.log(countAndSay(test1))
    console.timeEnd("执行用时")
    console.time("执行用时")
    console.log(countAndSay(test2))
    console.timeEnd("执行用时")
    
    1
    执行用时: 4.221ms
    1211
    执行用时: 0.099ms
    111221
    执行用时: 0.021ms
    

    总结

    • 第一种思路标准递归解法,先列出递归表达式和终止条件,再将问题简化为描述一组连续数字
    • 第二种解法利用了字符串分组匹配特性,和\1复用分组的规则

    说明

    1. 本题解已同步GitHub地址,可以复制代码进行调试。
    2. 总结出了一套亲测有效的前端无痛刷题项目,有助于算法小白平稳入门,详见leetcode-js-roadmap,希望对从零开始刷题的前端小伙伴们带来帮助~

    本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情


    起源地下载网 » [ 力扣38 ] 外观数列|刷题打卡

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元