递归与栈专题三

135 阅读2分钟

这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战 | 创作学习持续成长,夺宝闯关赢大奖 - 掘金 (juejin.cn)

题目链接

  1. 第K个语法符号 leetcode-cn.com/problems/k-…

题解及分析

第K个语法符号

在第一行我们写上一个0。接下来的每一行,将前一行中的0替换为01,1替换为10。
给定行数N和序数K,返回第N行中第K个字符。(K从1开始) 例子: 输入: N = 1, K = 1
输出: 0

输入: N = 2, K = 1
输出: 0

输入: N = 2, K = 2
输出: 1

输入: N = 4, K = 5
输出: 1

解释:
第一行: 0
第二行: 01
第三行: 0110
第四行: 01101001

思路:(这一类需要数学推导的题目是真的难)
借用下leetcode大神White Man的解析
把每一行对半分开:

1、0
2、0 | 1
3、01 | 10
4、0110 | 1001
5、01101001 | 10010110
6、0110100110010110 | 1001011001101001

不难看出,每一行实际上是把上一行的数字左右对半分开,然后0|1按照题意转换
例如:

3、01 | 10
4、0110 | 1001

第三行拆成01|10之后,按照题意,第四行的值的左边部分由第三行的值的左边部分01转换为0110,第四行的值的右边部分由第三行的值的右边部分10转换为1001
再把每一行的值分成四等分,再对比一次(举例4,5)

4、0110 | 1001
5、0110 1001 | 1001 0110

可以得出以下结论:

  • 如果K在前半段,所对应的值就是上一行的第K个值
  • 如果K在后半段,可以先算出K相对于后半段的位置,然后找出上一行这个位置的值,把值反过来 问题分析到这,就已经变成求某一行上一行的值,再进行推算
  • 怎么得到上一行的值?递归
var kthGrammar = function(n, k) {
    if(n === 1) return 0
    let length = 2 ** (n -1)
    if(k > length / 2) {
        let val = kthGrammar(n - 1, k - length / 2)
        return val === 0 ? 1 : 0
    } else {
        return kthGrammar(n - 1, k)
    }
}

上期文章:递归与栈专题二 - 掘金 (juejin.cn)