如何解决下面这段代码会被认为是尾递归吗?
下面这个函数是尾递归吗?以及如何更高效、更清晰地编写。
基于这个问题: 我们构建了一个包含 n 行(1 索引)的表。我们首先在第一行写 0。现在,在随后的每一行中,我们查看前一行,并将每次出现的 0 替换为 01,将每次出现的 1 替换为 10。
例如,对于n = 3,第一行是0,第二行是01,第三行是0110。 给定两个整数 n 和 k,返回 n 行表的第 n 行中的第 k 个(1 索引)符号。
def kthGrammar(self,n: int,k: int) -> int:
def getKvalue(k,predecessor):
digit_place = k%2
if predecessor == 0:
return 1 if digit_place == 0 else 0
elif predecessor == 1:
return 0 if digit_place == 0 else 1
def helper(n,k):
if n==1:
return 0
prevK = int((k+1)/2)
return getKvalue(k,helper(n-1,prevK))
return helper(n,k)
解决方法
您的函数当前是否是尾递归的?否。递归调用之后是对 getValue
的调用。
然而,您的函数可以被显着清理。我们将首先用 False 和 True 替换 0 和 1。
def kthGrammar(n: int,k: int) -> int:
def getKvalue(k : int,predecessor : bool) -> bool:
return (k % 2 == 0) != predecessor
def helper(n : int,k : int) -> bool
if n==1:
return False
prevK = (k+1) // 2
return getKvalue(k,helper(n-1,prevK))
return int(helper(n,k))
让我们进一步重写:
def kthGrammar(n: int,k: int) -> int:
def helper(n : int,k : int) -> bool
if n==1:
return False
prevK = (k+1) // 2
return (k % 2 == 0) != helper(n-1,k))
现在,我们尝试一些相当聪明的方法。我们定义 helper2(n : int,k : int,b : bool) = (b != helper(n,k))
。我们如何递归地实现 helper2
?
显然,如果 n = 1
,则 helper2(n,k,b) = (b != False) = b
。否则,我们有 helper2(n,b) = (b != helper(n,k)) = (b != ((k%2 == 0) != helper(n - 1,(k + 1) // 2)) = ((b != (k % 2 == 0)) != helper(n - 1,(k + 1) // 2)) = helper2(n - 1,(k + 1) // 2,b != (k % 2 == 0))
。
请注意,我使用的事实是,对于布尔值,a != (b != c)
与 (a != b) != c
相同。
最后,请注意 helper(n,k) = (False != helper(n,k) = helper2(n,False)
。
所以我们定义
def kthGrammar(n: int,k: int) -> int:
def helper2(n : int,b : bool) -> bool
if n==1:
return b
prevK = (k+1) // 2
return helper2(n - 1,prevK,b != (k % 2 == 0))
return int(helper2(n,False))
现在,我们有了一个尾递归函数。尾递归只是表达迭代的另一种方式,因此我们可以轻松地将其重写为使用 while
循环,如下所示:
def kthGrammar(n : int,k : int) -> int:
b = False
while n != 1:
n,b = n - 1,b != (k % 2 == 0)
return int(b)
可以再次替换为
def kthGrammar(n : int,k : int) -> int:
b = False
for _n in range(n,1,-1):
k,b = (k + 1) // 2,b != (k % 2 == 0)
return int(b)
当然,没有理由从 n
开始倒计时到 1
。所以最终的形式是
def kthGrammar(n : int,k : int) -> int:
b = False
for _n in range(1,n):
k,b != (k % 2 == 0)
return int(b)
请注意,我们实际上可以执行进一步的优化。一旦出现k = 1
,我们看到该行
k,b != (k % 2 == 0)
是空操作。所以最终的形式是
def kthGrammar(n : int,n):
if k == 1:
break
k,b != (k % 2 == 0)
return int(b)
在 k <= n
- 运行时为 O(min(n,log k))
而不是 O(n)
的情况下,这将更有效。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。