-
Notifications
You must be signed in to change notification settings - Fork 0
213. House Robber II #48
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,90 @@ | ||
| # 213. House Robber II | ||
| - 問題: https://leetcode.com/problems/house-robber-ii/ | ||
| - 言語: Python | ||
|
|
||
| ## Step1 | ||
| ### 方針 | ||
| - 見積: 最大 $n = 100$ 、 計算量: $O(n)$ 、 Pythonの実行時間: $10^{7}$ ステップ/秒 とすると、$10^{-5}$ 秒 | ||
| - `198. House Robber` と条件はほぼ同じだが、家が環状(最初の家と最後の家が隣接)に配置されている | ||
| - 環状をなんとかしてただの配列にしようと考えて10分経過 | ||
|
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. 方針のたてかたは、以下のやりとりが参考になるかもしれません。 |
||
|
|
||
| ### 正答 | ||
| #### 方針 | ||
| - 以下をそれぞれ実行する | ||
| - 最後の家を除いた `nums[:-1]` で線形DPを実行 | ||
| - 最初の家を除いた `nums[1:]` で線形DPを実行 | ||
|
|
||
| ```py | ||
| class Solution: | ||
| def rob(self, nums: List[int]) -> int: | ||
| if len(nums) <= 1: | ||
| return max(nums, default = 0) | ||
| if len(nums) == 2: | ||
| return max(nums) | ||
|
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. 22行目~23行目は不要だと思います。
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. 確かに不要ですね。 |
||
|
|
||
| def rob_linear(houses: List[int]) -> int: | ||
|
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. 確かにこのままだと何が返ってくるかは分かりづらいですね。ご指摘ありがとうございます。 |
||
| if len(houses) <= 1: | ||
| return max(houses, default = 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. if len(houses) == 1:
return houses[0]のほうが素直に感じます。 |
||
|
|
||
| max_values = [0] * len(houses) | ||
| max_values[0] = houses[0] | ||
| max_values[1] = max(houses[0], houses[1]) | ||
|
|
||
| for i in range(2, len(houses)): | ||
| max_values[i] = max(max_values[i - 2] + houses[i], max_values[i - 1]) | ||
|
|
||
| return max_values[-1] | ||
|
|
||
| # 最後を除くケース と 最初を除くケース の大きい方 | ||
| return max(rob_linear(nums[:-1]), rob_linear(nums[1:])) | ||
| ``` | ||
| - 時間計算量: $O(n)$ | ||
| - 空間計算量: $O(n)$ | ||
|
|
||
| ## Step2 | ||
| - 典型コメント集: https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.8gnsrornagjc | ||
|
|
||
| - https://github.com/TakayaShirai/leetcode_practice/pull/35 | ||
| - Dart | ||
| - 考え方 | ||
| - > 極端な話、まず、2^n 通り列挙して、そこから条件を満たしているものだけ取り出して、それぞれ和を取って最大値を取ればいけますよね。この 2^n 枚の紙をバインダーに挟んで、このパターンで盗んだときに、いくらになるかを計算し、最大にならない紙を捨てて、一番大きい紙を見つける方法でやってみましょう。 | ||
| > | ||
| > 各家の前に、泥棒が立って、バインダーが回ってきます。2^n 枚の紙の自分の担当の情報を埋めていくわけです。 | ||
| > | ||
| > 泥棒文句言うと思うんですね。ほとんどの紙は条件を満たしていません。先に捨てておけよ。 | ||
| > あと、最大になりようがないのも回ってきますね。自分は10人目なのにまだ1件も入っていない。先に捨てておけよ。 | ||
| > | ||
| > え、でも全部捨てたら怒られますよね。じゃあ、何は捨てたらだめですか。 | ||
| > | ||
| > これすると同じようなことが書かれている紙だけが残ります。 | ||
| > これ、1件目の家で盗んだか盗んでいないか、一つ前の家で盗んだか盗んでいないか、それぞれの最大の4種類だけですね。 | ||
| - src: https://github.com/TakayaShirai/leetcode_practice/pull/35#discussion_r2929595782 | ||
|
|
||
| ## Step3 | ||
| ```py | ||
| class Solution: | ||
| def rob(self, nums: List[int]) -> int: | ||
| if len(nums) <= 1: | ||
| return max(nums, default = 0) | ||
| if len(nums) == 2: | ||
| return max(nums) | ||
|
|
||
| def rob_linear(houses: List[int]) -> int: | ||
| if len(houses) <= 1: | ||
| return max(houses, default = 0) | ||
|
|
||
| max_values = [0] * len(houses) | ||
| max_values[0] = houses[0] | ||
| max_values[1] = max(houses[0], houses[1]) | ||
|
|
||
| for i in range(2, len(houses)): | ||
| max_values[i] = max(max_values[i - 2] + houses[i], max_values[i - 1]) | ||
|
|
||
| return max_values[-1] | ||
|
|
||
| return max(rob_linear(nums[:-1]), rob_linear(nums[1:])) | ||
| ``` | ||
| - 所要時間: | ||
| - 1回目: 4:03 | ||
| - 2回目: 3:37 | ||
| - 3回目: 4:11 | ||
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.
確かにいきなり見積を書くのは、不自然ですね。ご指摘ありがとうございます。