Conversation
| if n == 0: | ||
| return 1 | ||
| if n < 0: | ||
| return 1 / self.myPow(x, -n) |
There was a problem hiding this comment.
n を正の数に変換するために再帰呼び出しをしている点は理解できるのですが、読んでいてやや認知負荷が高いです。もう少し平易な書き方はできますでしょうか?
There was a problem hiding this comment.
return self.myPow(1 / x, -n)
これだと負荷が減りますか?
| if n < 0: | ||
| return 1 / self.myPow(x, -n) | ||
| if n % 2: | ||
| return x * self.myPow(x * x, n // 2) |
There was a problem hiding this comment.
Iterativeで書いてみました。個人的には再帰の方が直感的に思え読みやすいなと思いました。
ただ読みやすさに議論の余地があるなら関数呼び出しを行わず空間計算量がO(1)のループに分があるような気がします。
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n < 0:
x = 1 / x
n = -n
cumprod = 1
while n > 0:
if n % 2:
cumprod *= x
x *= x
n //= 2
return cumprodThere was a problem hiding this comment.
ループと再帰、どちらが認知負荷が低くなるか、直感的に思えるかは、個人差があると思います。業務でコードを書く場合は、平均的な開発メンバーにとって、どちらが認知負荷が低いか、直感的に思えるか感触を確かめ、そちらで書くのが良いと思います。また、もしコーディングインタビューでどちらで書くか迷った場合は、面接官に対しどちらで書こうか迷っている、どちらで書くのが良いか?と聞いてしまっても良いと思います。
There was a problem hiding this comment.
選択肢の幅があることが大事ですね。
個人的には再帰の方が直感的に思え読みやすいなと思いました。
もう少し言語化してみました。再帰の方がTop Downで宣言的に書けることが多いのに対して、ループだとBottom Upで書く必要があるので、再帰の方が読みやすいのかなと思いました。
| if n == 0: | ||
| return 1 | ||
| if n < 0: | ||
| return self.myPow(1 / x, -n) |
There was a problem hiding this comment.
n の符号と絶対値を保存しておき、 n の符号が負の場合は最後に 1 / hoge としたほうが、読んでいて認知負荷が低くなると思います。
There was a problem hiding this comment.
よくよく考えたところ、
if n < 0:
n = -n
x = 1.0 / x
でよいような気がしてきました。
| if n < 0: | ||
| return self.myPow(1 / x, -n) | ||
| res = 1 | ||
| digits = x |
There was a problem hiding this comment.
digits ですと、複数の桁を表すことになり、変数の本来の意味から離れるように思います。代案として、累積を表す cumulated あたりはいかがでしょうか?形容詞のためやや微妙かもしれませんが…。
There was a problem hiding this comment.
累積積(cumulative product)が良いかなと思いました。ちょっと長いのでcumprodにしました。
命名などを見直して再度書き直しました。
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n < 0:
x = 1 / x
n = -n
# left to right binary exponentation
# exponeitationを2進数表記して2進数表記の各桁ごとに分解する
# 例) 3^14 = 3^(2^3) * 3^(2^2) * 3^(2^1)
cumprod = 1
powered = x
while n > 0:
if n % 2:
cumprod *= powered
powered *= powered
n >>= 1
return cumprodThere was a problem hiding this comment.
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n < 0:
x = 1 / x
n = -n
# left to right binary exponentation
# exponeitationを2進数表記して2進数表記の各桁ごとに分解する
# 例) 3^14 = 3^(2^3) * 3^(2^2) * 3^(2^1)
powered = 1
cumprod = x
while n > 0:
if n % 2:
powered *= cumprod
cumprod *= cumprod
n >>= 1
return powered| return 1 | ||
| if n < 0: | ||
| return self.myPow(1 / x, -n) | ||
| res = 1 |
There was a problem hiding this comment.
この変数に保持される値を表す、具体的な変数名を付けたほうが良いと思います。 powered あたりでしょうか…。形容詞のためやや微妙かもしれません…。
There was a problem hiding this comment.
思いつかなかったのでres(result)にしたのですがpoweredの方が良さそうです。
https://leetcode.com/problems/powx-n/