779. 第K个语法符号:简单模拟

179 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情

题目描述

这是 力扣上的 779. 第K个语法符号,难度为 中等

题目分析

题目汇总给出一个表格,这个表格比较特殊,行索引11开始,每一行的字符也是从索引11开始,且表格的每一行中的数据是按照特殊方式分裂开来的,例如上一行中的00会分裂成下一行的0101,上一行中的11会分裂成下一行中的 1010

题目要我们迅速的找到第 nn 行的 第 kk 个字符是0 0还是1 1

思考:

那么我们来稍微简单的写几行数据来模拟一下,看看有没有什么规律可循

0
01
0110
01101001

仔细看例子,我们可以看到第 ii 行的字符个数是 2i12^{i-1},并且仔细的我们还可以发现,第ii行的字符数,总是i+1i+1行的一半,且字符还有很有趣的关系

那就是第 i 行的全部字符是第i+1i+1行的前半部分,i+1i+1 行的后半部分也很有意思,后半部分是前半部分的翻转

此处的翻转意思是:

前半部分的 0 对应着后半部分的 1,前半部分的 1 ,对应这后半部分的 0

那么,看到这里,对于解决这道题是不是有了一些思路呢?

我们就可以将题目中要求我们找到n行的第k个字符第 n 行的第 k 个字符,转换成了 n1行的第k个字符第 n-1 行的第 k 个字符(如果这个k 是大于当前行字符的一半,那么就要转换成前半段的字符),一直递归到n==1n == 1的情况我们就可以找到答案了,那么我们就有这样的逻辑:

如果 n是等于1n 是等于 1 的,咱们就可以直接返回 0 0

如果 n是大于1n 是大于 1 的,且满足条件 k>1<<(n2) k > 1<<(n-2) ,满足这个条件,说明找当前行的第 k 个字符,已经是在当前行的后半段了,因此,我们就继续往上找,找上一行的 k1<<(n2)k - 1<<(n-2) 个字符的翻转

如果 n是大于1n 是大于 1 的,且不满足条件 k>1<<(n2)k > 1<<(n-2) ,说明当前行要找的第 k 个字符在前半段,那么直接就找上一行的第 kk 个字符即可,一直找到n等于1n 等于 1的时候

对于以上逻辑,已经非常清晰了

接下来,咱们就可以来实现编码了,咱们这次使用 golang 的方式来进行实现

Golang 的实现方式:

  • 递归处理即可,每一次都判断当前行的第 k 个字符是否大于当前行的一半,若是,则找上一行对应位置的翻转

    • 若不是则找上一行的 第 k 个位置的字符
func kthGrammar(n, k int) int {
    if n == 1 {
        return 0
    }
    // 判断 当前行的第 k 个字符,是否大于上一行的总个数
    // 表示 k 的位置是当前行的后半部分了,那么就需要找到 当前行的第 k 个字符的位置在前半部分的对应翻转位置
    if k > 1<<(n-2) {
        return 1 ^ kthGrammar(n-1, k- 1<<(n-2))
    }
    // 若 k 是当前行的前半部分,那么不需要翻转
    return kthGrammar(n-1, k)
}

这种实现方式,咱们的时间复杂度为 O(n),此处的 n 是表示表格的 n 行,空间复杂度也是 O(n),我们使用的是递归的方式,需要递归 n 行,占用栈空间

今天就到这里,若有偏差,还请斧正

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~