779. 第K个语法符号(递归)

123 阅读2分钟

image.jpeg

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

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

    image.png

  • 题目示例

    image.png

  • 题目提示

    • 1 <= n <= 30
    • 1 <= k <= 2n - 1

二、思路分析:

我们今天拿到本题是 leetcode 难度为中等题 779. 第K个语法符号。题目要求在给定的n行中找到指定的K的字符符号。题目中介绍n行字符排序特点:

  • 从第一行开始,每一行字符索引从1开始计算
  • 首行0,第二行0替换成01,第三行1替换成10,0110,第四行01101001...依次类推
  • 每一行的符号都是0和1组成

根据题目描述,对于每一行都由上一行0和1替换组成,通过找规律递归遍历解答,思路如下:

  • 方法一:dfs模拟

    • 第n-1行的字符长度prelen是第n行的2的n-2的次方(2^(n-2))
    • 当k大于上一行的字符长度prelen时,则n行k的字符与n-1行k-prelen字符互为相反
    • 当k小于等于上一行的字符prelen时,则n行k的字符与n-1行k字符相同
    • 根据题目中示列,n=4,k=6;递归路径(dfs(4,6)->dfs(3,2)->dfs(2,2)->dfs(1,2)) image.png
      class Solution(object):
          def kthGrammar(self, n, k):
              """
              :type n: int
              :type k: int
              :rtype: int
              """
              def dfs(n,k):
                  if n==1:return 0
                  # prelen = pow(2,n-2)
                  prelen = 1<<(n-2)
                  if k > prelen:
                      return 0 if dfs(n-1,k-prelen) else 1
                  else:
                      return dfs(n-1,k)
      
              return dfs(n,k)
      
  • 方法二:找规律

    • 构建n行字符符号,我们可以转换成一个二叉树形式
    • 根节点为0,每一行按照0替换成10,1替换成10
    • 在二叉树中,左孩子与父节点相同,右孩子与父节点相反
    • 子节点(n,k),则其父节点位置为(n,(k+1)/2)
    • 判断节点是左/右孩子,可以根据k奇偶性,k为奇数则为左孩子,k为偶数则为右孩子 image.png
      class Solution(object):
          def kthGrammar(self, n, k):
              if n==1:return 0
              ret = self.kthGrammar(n-1,(k+1)/2)
              return ret if k % 2 ==1 else 1-ret 
      

三、总结:

本题是一道关于位运算概念,可以借用二叉树递归的思想来解答,只要发现左孩子与父节点一样,右孩子与父节点异或,同时借用k值来取求出父节点位置和左/右孩子特点就可以求出,AC提交记录如下:

image.png

  • 时间复杂度:O(n),n为题目给定的行数
  • 空间复杂度:O(n),n为递归遍历的深度

以上是本期内容,欢迎大佬们点赞评论,下期见~~~