779.第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
注意:
N 的范围 [1, 30].
K 的范围 [1, 2^(N-1)].
原题链接:https://leetcode-cn.com/problems/k-th-symbol-in-grammar
分析解题思路
昨天刚发现leetcode可以用python,一直看到官方解题里有python,我一直以为只能选c++和Java,真是可以偷大懒了。把C++留给大神们去用吧。
拿到这道题,审题就审了半天,然后明白了,就是按规律排列的若干行,用01替换上一行的0,用10替换上一行的1。拿到手就是算,那我把这一行求出来不就知道这行第K个数字是什么了么,官方称之为暴力破解法。
如图:
解题思路
- 第一行为0
- 下一行与上一行对应,每一个0对应一个01,每一个1对应一个10
- 循环N行,输出第K个值
暴力破解代码如下
class Solution(object):
def kthGrammar(self, N, K):
lastrow = '0'
rows = 1
while rows < N:
lastrow = "".join('01' if x == '0' else '10' for x in lastrow)
rows += 1
return int(lastrow[K-1])
根据上图所示,该算法的时间复杂度: O(2^N),时间复杂度呈指数级增加。当N的值稍微一大,程序运行会超时。
算法优化
经过观察,我们发现,不需要去计算第N行的所有数字,因为N行的第K个元素是受N-1行第K+1/2的元素所影响,当该值为0时,所求K值为1-K%2,当该值为1时,所求K值为K%2。因此,可以用递归优化求解。步骤如下:
- 设置递归出口N = 0时,返回值为0
- 返回N-1行第K+1/2个元素的值进行判断
- if 该值为0 返回1-K%2 ,else返回K%2
优化递归代码
class Solution(object):
def kthGrammar(self, N, K):
"""
:type N: int
:type K: int
:rtype: int
"""
if N == 1 :
return 0
elif self.kthGrammar(N-1,(K + 1)/2) == 0 :
return 1 - K % 2
else:
return K % 2
运行结果
该算法的时间复杂度减小到O(log(2^N))即O(N),提高了运算速度。
小结
希望不虚度每一天。依旧每日一句,共勉。
若新雪初霁,满月当空,下面平铺着皓影,上面流转着亮银,而你向我走来,月色与雪色之间,你是第三种绝色。
————余光中《绝色》