-
Notifications
You must be signed in to change notification settings - Fork 0
Solved: 198. House Robber #35
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| ## 取り組み方 | ||
| - step1: 5分以内に空で書いてAcceptedされるまで解く + テストケースと関連する知識を連想してみる | ||
| - step2: 他の方の記録を読んで連想すべき知識や実装を把握した上で、前提を置いた状態で最適な手法を選択し実装する | ||
| - step3: 10分以内に1回もエラーを出さずに3回連続で解く | ||
|
|
||
| ## step1 | ||
| `nums`の要素がi番目までの時、 | ||
| 盗める最大はひとつ前を使うか、使わないで`nums[i]`を使うかの大きい方が答え。 | ||
| つまり、`amount_total_money`、`prev_amount_total_money`、`prev_prev_amount_total_money`を管理していけば良い。 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def rob(self, nums: List[int]) -> int: | ||
| if len(nums) == 0: | ||
| return 0 | ||
| if len(nums) == 1: | ||
| return nums[0] | ||
| prev_prev_total_amount_money = nums[0] | ||
| prev_total_amount_money = max(nums[0], nums[1]) | ||
| total_amount_money = max( | ||
| prev_prev_total_amount_money, | ||
| prev_total_amount_money | ||
| ) | ||
| for i in range(2, len(nums)): | ||
| total_amount_money = max( | ||
| prev_prev_total_amount_money + nums[i], | ||
| prev_total_amount_money | ||
| ) | ||
| prev_prev_total_amount_money = prev_total_amount_money | ||
| prev_total_amount_money = total_amount_money | ||
| return total_amount_money | ||
| ``` | ||
|
|
||
| ## step2 | ||
| ### 読んだコード | ||
| - https://github.com/hayashi-ay/leetcode/pull/48/files | ||
| - https://github.com/fhiyo/leetcode/pull/36/files | ||
| - https://github.com/nittoco/leetcode/pull/39/files | ||
|
|
||
| ### 感想 | ||
| - 変数名が微妙、`max_money_so_far`あたりをつけるべき。 | ||
| - 更新のループは0からはじめるようにしても良いが、2から始めた方が意図が伝わる気がする。 | ||
| - メモ化再帰の発想がパッとは思い付かない。規則性がみえたら漸化式をおいてみる->ボトムアップのアプローチと考えがちな気がする。 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def rob(self, nums: List[int]) -> int: | ||
| if len(nums) <= 2: | ||
| return max(nums) | ||
| prev_prev_max_money = nums[0] | ||
| prev_max_money = max(nums[0], nums[1]) | ||
| max_money = None | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これは好みが分かれると思いますが、max_moneyの型がOptional[int]になってしまうので、0で初期化のほうがいいかなと思います。今回の場合はlen(nums) <= 2を処理しているので、下のforループを必ず通ることが保証されていますが、多分max_moneyの型Optional[int]とreturnの型のintで不整合という型エラーになるlinterが多いと思います。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. レビューありがとうございます。 |
||
|
|
||
| for num in nums[2:]: | ||
| max_money = max( | ||
| num + prev_prev_max_money, | ||
| prev_max_money | ||
| ) | ||
| prev_prev_max_money = prev_max_money | ||
| prev_max_money = max_money | ||
| return max_money | ||
| ``` | ||
|
|
||
| ## step3 | ||
| 1,2回目はstep2とほぼ同じになってしまったので、3回目は0番目からループに入れるようにした。悪くない気もする。 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def rob(self, nums: List[int]) -> int: | ||
| SENTINEL = 0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 私はこれを番兵とは呼ばないかなと思います。言葉としては柔らかく使われているのですが、多くの場合、範囲外へのアクセスや条件を吸収するために特殊な値を置いておくことですが、この場合は、単に足していくときの初期値という意味合いが強いので、この値でないと駄目ですね。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. レビューありがとうございます。
言われてみれば、おっしゃる通りだなと納得しました。 |
||
| prev_prev_max_money = SENTINEL | ||
| prev_max_money = SENTINEL | ||
| max_money = SENTINEL | ||
|
|
||
| for num in nums: | ||
| max_money = max( | ||
| num + prev_prev_max_money, | ||
| prev_max_money | ||
| ) | ||
| prev_prev_max_money = prev_max_money | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prev_prev_max_moneyが少し見にくいかなと感じました。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. レビューありがとうございます。 前々回の〜〜といった日本語をよく見る気がしたので使いましたが、確かに max_profit_two_houses_ago
max_profit_one_houses_ago
max_profitThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 英語的に正しいかは分かりませんが、ニュアンスはそんな感じです。 |
||
| prev_max_money = max_money | ||
| return max_money | ||
| ``` | ||
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.
再帰を思いつく方法としては、
という管理対象すべてtotal_moneyなので、つまり単純に前回の結果を使っている、みたいなところを意識すると比較的わかりやすい書き換えができると思います。
この場合、prev_prevが-2、prevが-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.
コメントありがとうございます。
慣れな気もするので、いただいたアドバイスを元に練習したいと思います。