微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

下面这段代码会被认为是尾递归吗?

如何解决下面这段代码会被认为是尾递归吗?

下面这个函数是尾递归吗?以及如何更高效、更清晰地编写。

基于这个问题: 我们构建了一个包含 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 举报,一经查实,本站将立刻删除。