-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
50. Pow(x, n) #41
base: main
Are you sure you want to change the base?
50. Pow(x, n) #41
Conversation
if n == 0: | ||
return 1 | ||
if n < 0: | ||
return 1 / self.myPow(x, -n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n を正の数に変換するために再帰呼び出しをしている点は理解できるのですが、読んでいてやや認知負荷が高いです。もう少し平易な書き方はできますでしょうか?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この再帰はループで表現したほうが、読んでいて認知負荷が低くなると思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 cumprod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ループと再帰、どちらが認知負荷が低くなるか、直感的に思えるかは、個人差があると思います。業務でコードを書く場合は、平均的な開発メンバーにとって、どちらが認知負荷が低いか、直感的に思えるか感触を確かめ、そちらで書くのが良いと思います。また、もしコーディングインタビューでどちらで書くか迷った場合は、面接官に対しどちらで書こうか迷っている、どちらで書くのが良いか?と聞いてしまっても良いと思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
選択肢の幅があることが大事ですね。
個人的には再帰の方が直感的に思え読みやすいなと思いました。
もう少し言語化してみました。再帰の方が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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n の符号と絶対値を保存しておき、 n の符号が負の場合は最後に 1 / hoge としたほうが、読んでいて認知負荷が低くなると思います。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
よくよく考えたところ、
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
digits ですと、複数の桁を表すことになり、変数の本来の意味から離れるように思います。代案として、累積を表す cumulated あたりはいかがでしょうか?形容詞のためやや微妙かもしれませんが…。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
累積積(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 cumprod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
指摘と命名逆かも。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この変数に保持される値を表す、具体的な変数名を付けたほうが良いと思います。 powered あたりでしょうか…。形容詞のためやや微妙かもしれません…。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
思いつかなかったのでres(result)にしたのですがpoweredの方が良さそうです。
https://leetcode.com/problems/powx-n/