|
| 1 | +# solutions/0050_powx_n.py |
| 2 | +""" |
| 3 | +Problem: Pow(x, n) |
| 4 | +https://leetcode.com/problems/powx-n/ |
| 5 | +
|
| 6 | +Implement pow(x, n), which calculates x raised to the power n. |
| 7 | +
|
| 8 | +Constraints: |
| 9 | +- -100.0 < x < 100.0 |
| 10 | +- -2^31 <= n <= 2^31 - 1 |
| 11 | +- n is an integer |
| 12 | +- Either x is not zero or n > 0 |
| 13 | +- -10^4 <= x^n <= 10^4 |
| 14 | +""" |
| 15 | +from _runner import get_solver |
| 16 | + |
| 17 | +SOLUTIONS = { |
| 18 | + "default": { |
| 19 | + "class": "SolutionIterative", |
| 20 | + "method": "myPow", |
| 21 | + "complexity": "O(log n) time, O(1) space", |
| 22 | + "description": "Iterative binary exponentiation", |
| 23 | + }, |
| 24 | + "recursive": { |
| 25 | + "class": "SolutionRecursive", |
| 26 | + "method": "myPow", |
| 27 | + "complexity": "O(log n) time, O(log n) space", |
| 28 | + "description": "Recursive binary exponentiation", |
| 29 | + }, |
| 30 | +} |
| 31 | + |
| 32 | + |
| 33 | +class SolutionIterative: |
| 34 | + """ |
| 35 | + Iterative binary exponentiation (exponentiation by squaring). |
| 36 | +
|
| 37 | + Key insight: x^n can be computed in O(log n) multiplications by |
| 38 | + decomposing n into binary. For example, x^13 = x^8 * x^4 * x^1 |
| 39 | + since 13 = 1101 in binary. |
| 40 | +
|
| 41 | + At each step, we check if current bit is set (n & 1). If so, |
| 42 | + multiply result by current power of x. Then square x and shift n. |
| 43 | + Handles negative exponents by inverting x and negating n. |
| 44 | + """ |
| 45 | + |
| 46 | + def myPow(self, x: float, n: int) -> float: |
| 47 | + # Handle negative exponent: x^(-n) = (1/x)^n |
| 48 | + if n < 0: |
| 49 | + x = 1 / x |
| 50 | + n = -n |
| 51 | + |
| 52 | + result = 1.0 |
| 53 | + |
| 54 | + while n > 0: |
| 55 | + # If current bit is set, multiply result by current power |
| 56 | + if n & 1: |
| 57 | + result *= x |
| 58 | + |
| 59 | + # Square x for next bit position |
| 60 | + x *= x |
| 61 | + # Move to next bit |
| 62 | + n >>= 1 |
| 63 | + |
| 64 | + return result |
| 65 | + |
| 66 | + |
| 67 | +class SolutionRecursive: |
| 68 | + """ |
| 69 | + Recursive binary exponentiation with divide and conquer. |
| 70 | +
|
| 71 | + The recurrence relation is: |
| 72 | + - x^n = (x^(n/2))^2 if n is even |
| 73 | + - x^n = x * (x^(n/2))^2 if n is odd |
| 74 | + - x^0 = 1 (base case) |
| 75 | +
|
| 76 | + This naturally halves the problem each step, giving O(log n) depth. |
| 77 | + Uses O(log n) stack space for recursion. |
| 78 | + """ |
| 79 | + |
| 80 | + def myPow(self, x: float, n: int) -> float: |
| 81 | + # Handle negative exponent |
| 82 | + if n < 0: |
| 83 | + x = 1 / x |
| 84 | + n = -n |
| 85 | + |
| 86 | + return self._pow(x, n) |
| 87 | + |
| 88 | + def _pow(self, x: float, n: int) -> float: |
| 89 | + # Base case |
| 90 | + if n == 0: |
| 91 | + return 1.0 |
| 92 | + |
| 93 | + # Recursive case: compute x^(n/2) |
| 94 | + half = self._pow(x, n // 2) |
| 95 | + |
| 96 | + # Square the result |
| 97 | + if n % 2 == 0: |
| 98 | + return half * half |
| 99 | + else: |
| 100 | + return half * half * x |
| 101 | + |
| 102 | + |
| 103 | +def judge(actual, expected, input_data: str) -> bool: |
| 104 | + """ |
| 105 | + Validate power computation with tolerance for floating point. |
| 106 | + """ |
| 107 | + import json |
| 108 | + |
| 109 | + lines = input_data.strip().split("\n") |
| 110 | + x = json.loads(lines[0]) |
| 111 | + n = json.loads(lines[1]) |
| 112 | + |
| 113 | + # Compute expected using Python's pow |
| 114 | + expected_result = pow(x, n) |
| 115 | + |
| 116 | + # Allow small relative error for floating point |
| 117 | + if expected_result == 0: |
| 118 | + return abs(actual) < 1e-9 |
| 119 | + return abs(actual - expected_result) / abs(expected_result) < 1e-5 |
| 120 | + |
| 121 | + |
| 122 | +JUDGE_FUNC = judge |
| 123 | + |
| 124 | + |
| 125 | +def solve(): |
| 126 | + import sys |
| 127 | + import json |
| 128 | + |
| 129 | + lines = sys.stdin.read().strip().split("\n") |
| 130 | + |
| 131 | + # Parse input: x and n |
| 132 | + x = json.loads(lines[0]) |
| 133 | + n = json.loads(lines[1]) |
| 134 | + |
| 135 | + # Get solver and compute power |
| 136 | + solver = get_solver(SOLUTIONS) |
| 137 | + result = solver.myPow(x, n) |
| 138 | + |
| 139 | + # Output with reasonable precision |
| 140 | + print(json.dumps(result, separators=(",", ":"))) |
| 141 | + |
| 142 | + |
| 143 | +if __name__ == "__main__": |
| 144 | + solve() |
0 commit comments