Introduction
LeetCode 50: Pow(x, n) challenges you to efficiently compute x raised to the power of n (i.e., xⁿ). While a naive solution might multiply x repeatedly, the optimal approach uses Fast Exponentiation, also known as Exponentiation by Squaring, which runs in logarithmic time.
This is a classic math problem often used in interviews to test your ability to implement optimized recursive or iterative algorithms.
Problem Statement
Implement the function:
go
func myPow(x float64, n int) float64
Calculate x raised to the power n (i.e., xⁿ). The function must handle both positive and negative exponents, and run efficiently for large n.
Examples
Example 1:
go
Input: x = 2.00000, n = 10
Output: 1024.00000
Example 2:
go
Input: x = 2.10000, n = 3
Output: 9.26100
Example 3:
go
Input: x = 2.00000, n = -2
Output: 0.25000
Explanation: 2⁻² = 1 / (2²) = 1/4 = 0.25
Approach: Fast Exponentiation (Binary Power)
To efficiently compute xⁿ, we use:
- Divide and Conquer strategy.
- For even
n: xⁿ = (x²)^(n/2)
- For odd
n: xⁿ = x * (x²)^((n−1)/2)
- For negative
n: x⁻ⁿ = 1 / xⁿ
This reduces the number of multiplications to O(log n).
Go Implementation
✅ Recursive Solution (Elegant and efficient):
go
func myPow(x float64, n int) float64 {
// Convert to int64 to handle edge cases like n = math.MinInt32
N := int64(n)
if N < 0 {
x = 1 / x
N = -N
}
return fastPow(x, N)
}
func fastPow(x float64, n int64) float64 {
if n == 0 {
return 1.0
}
half := fastPow(x, n / 2)
if n%2 == 0 {
return half * half
} else {
return half * half * x
}
}
Example Walkthrough
Input: x = 2.0, n = 10
Recursive stack will look like:
fastPow(2.0, 10)
fastPow(2.0, 5)
fastPow(2.0, 2)
fastPow(2.0, 1)
fastPow(2.0, 0) → returns 1
Then as the recursion unwinds:
fastPow(2.0, 1) → 1 * 1 * 2 = 2
fastPow(2.0, 2) → 2 * 2 = 4
fastPow(2.0, 5) → 4 * 4 * 2 = 32
fastPow(2.0, 10) → 32 * 32 = 1024
Time and Space Complexity
MetricComplexityTime ComplexityO(log n)Space ComplexityO(log n)
- Time: Each call halves the exponent.
- Space: Call stack for recursion is O(log n), or can be O(1) with an iterative version.
Edge Cases to Consider
x = 0.0, n > 0: Should return 0.0
n = 0: Always return 1.0 regardless of x
x = 0, n = 0: Return 1.0 (by mathematical convention)
- Very large or very negative
n (e.g. -2^31): Must handle safely using int64
Alternative: Iterative Version (for O(1) space)
go
func myPow(x float64, n int) float64 {
N := int64(n)
if N < 0 {
x = 1 / x
N = -N
}
result := 1.0
for N > 0 {
if N%2 == 1 {
result *= x
}
x *= x
N /= 2
}
return result
}
Key Takeaways
- Use fast exponentiation for logarithmic performance.
- Handle negative powers carefully, especially when
n == math.MinInt32.
- Know both recursive and iterative forms of this approach.
- Avoid brute-force multiplication for large exponents — it will timeout.