对分递归解以找到pow(x,n)

时间:2019-04-12 04:21:24

标签: python

我正在研究一个递归递归问题:

  

Pow(x, n) - LeetCode

     

实施pow(x, n),计算将 x 提升到幂 n (x ^ n)。

     

示例1:

Input: 2.00000, 10
Output: 1024.00000
     

示例2:

Input: 2.10000, 3
Output: 9.26100
     

示例3:

Input: 2.00000, -2
Output: 0.25000
Explanation: 2^-2 = 1/2^2 = 1/4 = 0.25
     

注意:

     
      
  • -100.0 < x <100.0
  •   
  • n 是一个32位带符号整数,范围为[−231,231 − 1]
  •   

我的二等分法

class Solution:
    def myPow(self, x: float, n: int) -> float:
        #base case
        if n == 0: return 1
        #recur case 
        else:
            half = self.myPow(x, n//2) #floor           
            if n % 2 == 0: #even                      
                return half**2
            if n % 2 != 0: #odd
                return x * (half**2)        

运行TestCase时


    def test_b(self):
        x = 2.0
        n = -2
        answer = 0.25
        check = self.solution.myPow(x, n)
        self.assertEqual(answer, check)

报告错误:

DEBUG x: 2.0, n: -1
DEBUG x: 2.0, n: -1
DEBUG x: 2.0, n: -1
.......
DEBUG x: 2.0, n: -1
DEBUG x: 2.0, n: -1
DEBUG x: 2.0, n: -1
Fatal Python error: Cannot recover from stack overflow.

它在n=-1停了下来,发现了尴尬的情况

In [10]: -1 // 2                                                                                                              
Out[10]: -1

In [11]: -2 // 2                                                                                                              
Out[11]: -1

修改后可以使用

class Solution:
    def myPow(self, x: float, n: int) -> float:
        """
        Runtime: 36 ms, faster than 99.70%
        Memory Usage: 13.2 MB, less than 5.53%
        """
        #base case
        if n == 0: return 1
        if n == -1: return 1/x
        #recur case 
        else:
            logging.debug(f"x: {x}, n: {n}")            
            half = self.myPow(x, n//2) #floor 

            if n % 2 == 0: #even
                logging.debug(f"even: x: {x}, n: {n}, half:{half}")                            
                return half**2
            if n % 2 != 0: #odd
                logging.debug(f"odd: x: {x}, n: {n}, half:{half}")                            
                return x * (half**2)        

但是,在阅读讨论和其他意见之后。我发现所有其他情况都更喜欢基本情况n < 0

一个清晰的例子:

class Solution(object):
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        if n == 0:
            return 1
        if n < 0:
            return 1 /self.myPow(x, -n)
        else:
            partial = self.myPow(x, n//2)
            result = partial * partial
            if n % 2 == 1: #odd
                result *= x
            return result

我认为没有必要将负数n更改为-n,因为2**10 == 2**5 * 2** 5 and 2**-10== 2**-5 * 2**-5

由于人们比n < 0更喜欢基本情况n == -1,所以有什么好处?

1 个答案:

答案 0 :(得分:2)

"not necessary to change negative n to-n"
我认为这是性能和精度的考虑。

  • 性能:整数乘法比浮点数快
  • 精度:当数量非常小时,可能会导致精度损失。

所以我们更喜欢先做战俘,然后分开。