【问题标题】:recursively calculate if x is power of b递归计算 x 是否为 b 的幂
【发布时间】:2022-01-03 00:10:45
【问题描述】:

任务是编写一个递归函数,它接收两个整数非负数b, x,如果有自然整数n,则返回True,如果没有自然整数b**n=x,则返回False我不能使用任何数学运算符或循环,除了 % 来确定一个数字是偶数还是奇数。 但我确实有可以使用的外部功能。它可以添加 2 个数字,乘以 2 个数字,并将一个数字除以 2。我还可以编写可以在 main 函数中使用的辅助函数。

这是我目前得到的,但它仅在b 的形式为2^y(2、4、8、16 等)时才有效

def is_power(b, x):
    if b == x:
        return True
    if b > x:
        return False
    return is_power(add(b, b), x)  # the func 'add' just adds 2 numbers

此外,复杂度需要为O(logb * logx) 谢谢。

【问题讨论】:

  • 我想你想乘,而不是加。您还需要保留 b 的原始值(可能作为助手的参数),以确保每次只将 n 增加一。
  • @Samwise 我无法添加任何参数。我该怎么做?
  • 我认为在您所描述的限制下这是不可能的。 (我也不认为你准确地描述了作业的约束,但我不可能为你解决这个问题。)
  • @Samwise 也许我可以编写另一个函数来创建某种索引?我不知道这是否可能,我对递归很陌生
  • 写另一个函数,允许你添加另一个状态,同时仍然使解决方案递归是我的建议,但你说你不允许这样做,所以我不确定前进的道路是什么。只复制作业中的确切说明会更简单,因为听起来这个想法是为了发现一个聪明的漏洞,如果这些说明被模糊地解释,那是不可能的。

标签: python algorithm recursion math


【解决方案1】:

您基本上可以继续将b 乘以b,直到达到或超过n

使用辅助函数的递归实现可能如下所示:

def is_power(b, x):
    if b == 1:          # Check special case
        return x == 1
    return helper(1, b, x)

def helper(counter, b, x):
    if counter == x:
        return True
    elif counter > x:
        return False
    else:
        return helper(mul(counter, b), b, x) # mul is our special multiplication function

【讨论】:

  • 谢谢,成功了。辅助函数中的“acc”是什么?
  • @MadaBit 很高兴它有帮助:) 我使用acc 作为累加器,本质上我们通过乘法将一堆b 累加到acc 中。例如,您也可以将其称为counter
  • 这个解决方案的时间复杂度不符合问题的要求。
  • 如果我们假设乘法的时间复杂度是恒定的,那么就像你说的那样。但是对于动态大小的大整数的 Python 整数来说是这样吗?
  • @trincot 授予。我发现通常在允许访问黑盒函数的问题中(例如这里的 add、sub、mul),时间复杂度是用对这些函数的调用来表示的,而不是对其内部时间复杂度进行假设。我想在这种情况下这不是 100% 清楚的,但我想说他的措辞(“无数学运算符”、“外部函数”)确实暗示了这一点。
【解决方案2】:

使用您所说的可以用来将 2 个数字相乘的函数,例如:

power = False
result = b
while result < x:
    result = yourMultiplyFunction(b,b)
    if result == x:
        power = True
        break
print(power)

问题已编辑(无法使用循环):

def powerOf(x, b, b1=-1):
    if b1 == -1:
        b1 = b
    if (b == 1) and (x == 1):
        return True
    elif ( b==1 ) or (x == 1):
        return False
    if b*b1 < x:
        return powerOf(x, b*b1, b1)
    elif b*b1 > x:
        return False
    return True

print(powerOf(625, 25))

【讨论】:

  • 不能使用循环。
  • 是的,我刚刚看到更新,我正在编写解决方案
  • @AlexandruDuDu powerOf(1, 1) 是假的 :)
  • 对不起,这是我错过添加的案例。检查更新的
  • powerOf(27, 3) 是 False,但它应该是 True。 3**3 = 27
【解决方案3】:

O(logb * logx) 的解决方案比简单的顺序搜索要慢

你可以通过简单的操作得到 O(logx / logb):

def is_power(b,x,bn=1):
    if bn == x: return True
    if bn > x: return False
    return is_power(b,x,bn*b)

我怀疑目标是比 O(logx/logb) 更快,并且复杂性要求应该类似于 O(log(logx/logb)^2) ,相当于 O(log(n)*日志(n))。

要获得 O(log(n)*log(n)) 解决方案,您可以通过实现一个辅助函数将一个数字提高到 O(log(n)) 中的给定幂来将问题转换为二进制搜索时间并在 O(log(n)) 搜索逻辑中使用它。

def raise_power(b,n):                       # recursive b^n O(logN)
    if not n: return 1                      # b^0 = 1
    if n%2: return b*raise_power(b*b,n//2)  # binary decomposition
    return raise_power(b*b,n//2)            # of power over base

def find_power(b,x,minp,maxp):               # binary search
    if minp>maxp: return False               # no matching power 
    n = (minp+maxp)//2                       # middle of exponent range
    bp = raise_power(b,n)                    # compute power
    if bp == x: return True                  # match found
    if bp > x: return find_power(b,x,minp,n-1) # look in lower sub-range
    return find_power(b,x,n+1,maxp)            # look in upper sub-range

def max_power(b,x):
    return 2*max_power(b*b,x) if b<x else 1  # double n until b^n > x
    
def is_power(b,x):
    maxp = max_power(b,x)                    # determine upper bound
    return find_power(b,x,0,maxp)            # use binary search

    

请注意,您需要将 *、+ 和 //2 操作转换为等效的外部函数,以满足您的作业要求

【讨论】:

  • 我不允许在 is_power 函数中添加另一个参数
  • 然后您可以使用默认参数创建另一个辅助函数并从 is_power() 调用它。您可以利用这个机会在调用辅助函数之前设置 maxp 值,而不是检查 maxp 是否为 None。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
  • 2014-03-01
  • 1970-01-01
  • 2015-11-08
相关资源
最近更新 更多