1. 程式人生 > >Leetcode 50:Pow(x, n)(超詳細的解法!!!)

Leetcode 50:Pow(x, n)(超詳細的解法!!!)

實現 pow(x, n) ,即計算 x 的 n 次冪函式。

示例 1:

輸入: 2.00000, 10
輸出: 1024.00000

示例 2:

輸入: 2.10000, 3
輸出: 9.26100

示例 3:

輸入: 2.00000, -2
輸出: 0.25000
解釋: 2^{-2} = 1/2^2 = 1/4 = 0.25

說明:

  • -100.0 < x < 100.0
  • n 是 32 位有符號整數,其數值範圍是 [ 2
    31 −2^{31}
    , 2 31 1
    2^{31} − 1
    ] 。

解題思路

我們首先想到的做法就是區分n是正數還是負數。如果是正數的話,我們就不斷的乘x。如果是負數的話,我們就不斷的除x。乘和除的次數都是n即可。

class Solution:
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        res = 1.0
        for _ in
range(abs(n)): if n > 0: res *= x else: res /= x return res

很顯然問題沒這麼簡單,我們提交結果超時了。當n非常大的時候我們乘積的次數太多了。這個問題我們很容易聯想到之前的一個問題Leetcode 29:兩數相除(超詳細的解法!!!)。我們可以使用相同的思路,通過增量式的思路來處理。對於輸入x=3n=1000來說,可以變為

  • 3 1000 = 3 2 9 3 2 8 3 2 7 3 2 6 3 2 5 3 2 3 3^{1000} = 3^{2^9}*3^{2^8}*3^{2^7}*3^{2^6}*3^{2^5}*3^{2^3}

現在我們的問題就變成了程式設計去實現這樣的拆解。我們首先想到的做法就是先找到小於10002的最大冪指數512,接著我們繼續找小於1000-512=4882的最大冪指數256,以此類推。所以可以想到的思路就是建立一個32維的陣列空間存放2的冪指數。

其實還有一種更好的辦法,如果你觀察到這樣的規律話

觀察每次數字是不是奇數,如果是奇數的話我們保留對應的2的冪次即可。

class Solution:
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        m = -n if n < 0 else n
        p, q = 1, x
        while m > 0:
            if (m & 1) == 1:
                p *= q
            m //= 2
            q *= q
            
        return 1/p if n < 0 else p

對於這個問題通過遞迴來處理思路會更加清晰,我們定義函式 f ( x , n ) f(x,n) 返回 x n x^n 值,那麼

  • f ( x , n ) = f ( x , n / 2 ) 2   ( n   i s   e v e n ) f(x,n)=f(x,n/2)^2\ (n\ is\ even)
  • f ( x , n ) = f ( x , n / 2 ) 2 x   ( n   i s   o d d ) f(x,n)=f(x,n/2)^2*x\ (n\ is\ odd)

我們定義的上述函式只能處理n為正數的情況。對於邊界問題,我們要分開考慮

  • n = 0 n=0
  • n = 1 n=1
  • n &lt; 0 n&lt;0
class Solution:
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        if n == 0:
            return 1.0
        
        if n == 1:
            return x
        
        m = n // 2
        if n < 0:
            m = -m
            x = 1/x
            
        res = self.myPow(x, m)
        
        if (n & 1) == 0:
            return res * res
        return res * res * x

我將該問題的其他語言版本新增到了我的GitHub Leetcode

如有問題,希望大家指出!!!