【问题标题】:Power of a number tail recursion数尾递归的幂
【发布时间】:2018-07-28 00:32:48
【问题描述】:

我正在尝试使用运行时间为 log(n) 的尾递归来计算 num 的幂。据我了解,使用 power // 2 而不是 power - 1 的区别在于减少运行时间。因此,当我计算值时,我需要将旧值乘以另外两个总和而不是一个。我的代码可以找到直到达到 power_of(2,6)

def power_of(num,power,value = 1):
    if power == 0:
        return 1

    elif power == 1:
        return value

    elif power % 2 != 0:
        return power_of(num, power // 2 , value * num * num * num)

    else:
        return power_of(num, power // 2 , value * num * num)

power_of(2,6)

【问题讨论】:

标签: python recursion data-structures tail-recursion


【解决方案1】:

如果递归是递归函数中要执行的最后一条语句,则递归函数称为尾递归。在计算x 提高到n (x^n) 的幂的情况下,正常的递归函数可能会将所有值存储在堆栈中,直到达到n == 1n == 0(根据您的基本条件)而我们没有不想使用所有这些状态/实例。所以我们能做的就是继续将最新状态保存在一个变量中,并在我们达到基本情况时立即返回该变量。

    int x = scanner.nextInt(); 
    int n = scanner.nextInt();
    int res = printPower(x, n);
    int resTail =  printPowerTail (x, n, x);   
    System.out.println(res);     
    System.out.println(resTail);

static int printPower (int x, int n) {
    if (n == 1) 
        return x;
    if (n == 0)
        return 1;
    return x * printPower(x, n - 1); // this call will store all the instances of n till n == 1
}
static int printPowerTail (int x, int n, int flag) {
    if (n == 1) 
        return flag;
    if (n == 0)
        return 1;
    return printPowerTail(x, n - 1, flag * x);
}

【讨论】:

  • 为什么你的递归函数命名为printX,而它实际上是纯的?
【解决方案2】:

看看它是如何工作的:

from hypothesis import given, strategies as st, settings, example

def power_of(num,power):
    if power == 0:
        return 1
    elif power == 1:
        return num
    elif power % 2 != 0:
        return num * power_of(num*num, power // 2)
    else:
        return power_of(num*num, power // 2)

@given(st.integers(min_value=0), st.integers(min_value=0))
@example(2, 6)
def test_power_of(i, j):
    assert power_of(i, j) == i**j

【讨论】:

  • 这不是尾递归
【解决方案3】:

https://repl.it/repls/WiltedOrnateMetadata

主要问题是您的尾值倍增不足。假设 power=9, power // 2 = 4, power - power // 2 = 5,你只会将 value * num ^ 3 相乘。如果这没有意义,请告诉我。

另外,您对 power == 1 有疑问,如果值为 1,则必须返回 num。

def power_of(num,power,value = 1):
    print ("power_of({},{},{})".format(num,power,value)) # this was how I debugged it
    if power == 0:
        return 1

    elif power == 1:
        return num if value == 1 else value

    elif power % 2 != 0:
        for a in range(1, power - power // 2):
          value *= num
        return power_of(num, power // 2 , value)

    else:
        for a in range(1, power - power // 2):
          value *= num
        return power_of(num, power // 2 , value * num * num)

输出:

print(power_of(2,9))
power_of(2,9,1)
power_of(2,4,16)
power_of(2,2,128)
power_of(2,1,512)
512

【讨论】:

    【解决方案4】:

    好的尾递归,对。我很抱歉另一个答案。您的方法应该有效,只需要进行一些修改。对于偶数,您希望将 num 替换为 num * num,并将 value 保留为 value。对于赔率,您想将 num 替换为 num * num,将 value * num 设为值,然后在除幂之前减去 1。

    def power_of(num,power, value = 1):
    
        if power == 0:
          return value
    
        if power == 1:
            return value * num
    
        elif power % 2 != 0:
            return power_of(num*num, (power - 1) // 2, value * num)
    
        else:
            return power_of(num*num, power // 2, value)
    
    print(power_of(2,6))
    

    我几乎从wikipedia复制了这个

    【讨论】:

    • 当然 wikipedia 有一个更有效的方法,我希望他能从我离开的地方弄清楚..
    • 额外的“power == 1”基本情况的目的是什么?
    猜你喜欢
    • 1970-01-01
    • 2013-10-05
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多