From 4a0f15cfdadd177018318b20beb6115e43ca7203 Mon Sep 17 00:00:00 2001 From: Ryohei Sato <130881456+Satorien@users.noreply.github.com> Date: Thu, 4 Dec 2025 11:54:30 +0900 Subject: [PATCH] Created 50. Pow(x, n).md --- Python3/50. Pow(x, n).md | 107 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 Python3/50. Pow(x, n).md diff --git a/Python3/50. Pow(x, n).md b/Python3/50. Pow(x, n).md new file mode 100644 index 0000000..a4c61d5 --- /dev/null +++ b/Python3/50. Pow(x, n).md @@ -0,0 +1,107 @@ +## Step 1. Initial Solution + +- 素直にやるならx * x^(n-1)とする方法がある + - このまま取りあえず実装してみると再帰の深さがnになるので + • `-2^31 <= n <= 2^31-1` + + を見ると微妙 + +- 自分で計算するときは{x^(n//2)}^2のようにすることが多いのでこれを実装 + - 少し条件分岐が多くなったがひとまずこれで実装 + +```python +class Solution: + @cache + def myPow(self, x: float, n: int) -> float: + if x == 0: + return 0 + + if n < 0: + return 1 / self.myPow(x, -n) + if n == 0: + return 1 + if n == 1: + return x + if n == 2: + return x * x + + if n % 2 == 1: + return x * self.myPow(x, n - 1) + return self.myPow(self.myPow(x, n // 2), 2) +``` + +### Complexity Analysis + +- 時間計算量:O(log n) +- 空間計算量:O(log n) + +## Step 2. Alternatives + +- https://github.com/tokuhirat/LeetCode/pull/45/files#diff-ce284075b2a3f6e20cd3d4ff805c3cb4ab0540e9ace2b462e43b40955dfd3dc1R32 + - 中で x*xにする考え方もある + - 最後のelseは要らなさそう + - 分岐を参考にして修正 + +```python +class Solution: + @cache + def myPow(self, x: float, n: int) -> float: + if n < 0: + return 1 / self.myPow(x, -n) + if n == 0: + return 1 + if n % 2 == 1: + return x * self.myPow(x, n-1) + return self.myPow(x, n // 2) * self.myPow(x, n // 2) +``` + +- https://github.com/TORUS0818/leetcode/pull/47/files#diff-91647df59bb2863e62120bcb064c143cab9cb1c4e78ed9feab30fc009844b5d0R198-R200 + - 確かにPythonではあまり気にすることがないが1.0表記の方がfloatであることが明らかなので良さそう + - x=0 かつ n≤0の場合は処理できないのでZeroDivisionErrorか0^0=1が返ることになる + - Step1の実装も正しくはないので微妙 +- https://github.com/TORUS0818/leetcode/pull/47/files#r2038337006 + - ビットシフトでループを回す方法もあるらしい + - 実際に手作業でこの演算をやることを考えるとあまり直感的ではない + +```python +class Solution: + def myPow(self, x: float, n: int) -> float: + assert x != 0 or n > 0 + if n < 0: + x = 1.0 / x + n = -n + + result = 1.0 + bit = 1 + exponent = x + while n >= bit: + if n & bit: + result *= exponent + bit <<= 1 + exponent *= exponent + return result +``` + +## Step 3. Final Solution + +- 以下でassert x ≠ 0 or n < 0を最初に入れてx==0の場合分けを入れないと答えが倍数精度で0.0表示になるときにエラーが起きる + - 再帰をするときは再帰で呼び出されるケースを網羅的に考える必要がある + +```python +class Solution: + @cache + def myPow(self, x: float, n: int) -> float: + assert x != 0 or n > 0 + + if n == 0: + return 1.0 + if x == 0: + return 0 + if n < 0: + x = 1.0 / x + n = -n + + if n % 2 == 1: + return x * self.myPow(x, n-1) + return self.myPow(x*x, n//2) +```