-
Notifications
You must be signed in to change notification settings - Fork 0
Solved Arai60/1011. Capacity To Ship Packages Within D Days #44
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
base: main
Are you sure you want to change the base?
Conversation
def shipWithinDays(self, weights: List[int], days: int) -> int: | ||
if days <= 0: | ||
return -1 | ||
if not weights: |
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.
おそらくL128のmaxでエラーを出さないために入れていると思うのですが、maxにdefault引数を指定してこれは消してしまっても良いと思います。
https://docs.python.org/ja/3.13/library/functions.html#max
daily_load = weight | ||
return required_days <= days | ||
|
||
return bisect_left( |
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.
面白い書き方だと思いました。
個人的にはindexという一見capacityとは対応していなさそうに見えるものを返すのは一瞬不思議に思いましたが、慣れればそうでもないのかもしれません。
sequence = range(max(weights), sum(weights) + 1)
index = bisect_left(sequence, True, key=canShipWithCapacity)
return sequence[index]
このようにしてしまう選択肢もあると思いました。
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.
お疲れ様です、思考やコードが丁寧に書かれていてとても読みやすかったです。
min_capacity = max(max(weights), sum(weights) // days) | ||
daily_capacity = min_capacity | ||
days_left = days | ||
while True: |
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.
min_capacityはループの中で必ず1ずつ増えていくので自分ならforループにするかなと思いました
return min_capacity | ||
days_left = days | ||
min_capacity += 1 | ||
daily_capacity = min_capacity |
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.
23行目と同様にfor weight in weights:
の前に書くかなと思いました。
daily_capacity -= weight | ||
if days_left > 0: | ||
return min_capacity | ||
days_left = days |
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.
自分はこれはforループの前の初期化のイメージなのでfor weight in weights:
の前に書くかなと思いました。
そうすると12行目の代入も省けそうです
```python | ||
class Solution: | ||
def shipWithinDays(self, weights: List[int], days: int) -> int: | ||
min_capacity = max(max(weights), sum(weights) // days) |
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.
私はぱっと見だと分からず少し思考が必要だったので、単にmax(weights)という明らかに最小だと分かるものにしておくのもよいかもしれません。
ただ、可能な限り大きい値にしておけばループの回数も減るのでその辺はトレードオフになりそうです。
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.
常にmax(weights)
>= sum(weights) // days
が成立するので、いずれにせよ冗長だと思います。
|
||
- max(weights)とsum(weights)の間に答えがあると考えられる(!)のでこれを用いて二分探索する方法がある | ||
- これがどれだけ速いのかをよく理解できていない | ||
- 元々期待値として線形に船の容量を上げるとどうなるのか? |
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.
探索の範囲を具体的に考えてみるとどうでしょうか。例えば長さ10000の範囲だとして、線形探索では最悪何ステップかかって二分探索だと最悪何ステップになるか、という具体例を考えてみるとどれだけ速くなるかが定量的につかめるかなと思います。
- これがどれだけ速いのかをよく理解できていない | ||
- 元々期待値として線形に船の容量を上げるとどうなるのか? | ||
- bisect_leftの引数に自分で定義した関数を渡す方法 | ||
- https://github.com/tokuhirat/LeetCode/pull/44/files#diff-06f87195f0dc2635b3c326a3257c212b916a27bd5f47afbf0368d37831b513a3R29 |
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.
このような方法があるのですね、これは勉強になりました!
- https://github.com/Fuminiton/LeetCode/pull/44/files | ||
- https://github.com/nittoco/leetcode/pull/47/files | ||
- いつも思うがなぜ皆同じような解法になっているんだろうか?自分だけ何かを理解できていないような気分 | ||
- 取りあえず今回のような範囲を思いつきにくい場合でも二分探索を軸に考えるのは一般的と理解しておく |
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.
イメージとしてはどっかでTrue/Falseが入れ替わる境界があるときに二分探索が使えそうだな~という発想になるのかなと思っています。
今回のケースで言うと「days日間でcapacityの船で全ての積み荷を輸送できるか?」というブール値がcapacityを増やしていくと
False, False, ..., False, True, True, ...
と明確に「ここから下は全てFalse」「ここから上は全てTrue」という境界があるはずなので二分探索できるなという気持ちですかね。
left = max(weights) | ||
right = sum(weights) |
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.
left, rightがどのような不変条件を満たしているかを言語化してみて変数名をつけるとより分かりやすくなるのかなと思いました。
二分探索を考える際、以下の議論なども参考になるかもしれません。
KentaroJay/Leetcode#18 (comment)
potrue/leetcode#41 (comment)
if days <= 0: | ||
return -1 | ||
|
||
def canShipWithCapacity(capacity: int) -> bool: |
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.
inner function の関数名は、 lower_snake で書くことが多いと思います。 LeetCode が指定している関数名は仕方ないと思います。
参考までにスタイルガイドへのリンクを貼ります。
https://peps.python.org/pep-0008/#function-and-variable-names
Function names should be lowercase, with words separated by underscores as necessary to improve readability.
https://google.github.io/styleguide/pyguide.html#316-naming
function_name
上記のスタイルガイドは唯一絶対のルールではなく、複数あるスタイルガイドの一つに過ぎないということを念頭に置くことをお勧めします。また、所属するチームにより何が良いとされているかは変わります。自分の中で良い書き方の基準を持ちつつ、チームの平均的な書き方で書くことをお勧めいたします。
問題文:https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/description/