-
Notifications
You must be signed in to change notification settings - Fork 0
Solved Arai60/213. House Robber II #36
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,84 @@ | ||
## Step 1. Initial Solution | ||
|
||
- あまり集中できておらず、どうやったら最後の処理がうまいことできるのか考えて手が止まってしまった | ||
- 結局各回の最大値保持してやるのを2パターン分保持するようにすれば最低限の要件は満たすのでそれで実装 | ||
- 最初の家+3軒目以降最後除く | ||
- 2軒目以降最後まで | ||
|
||
の2通りの制約の中で大きい方を選ぶ | ||
|
||
|
||
```python | ||
class Solution: | ||
def rob(self, nums: List[int]) -> int: | ||
if len(nums) <= 1: | ||
return nums[-1] | ||
robbed_with_first = [nums[0], nums[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. 最初の家で盗むのであれば、 2 軒目では盗めないため、 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. 確かにそうですね。ここは意味にこだわらないと違和感がありますね。 |
||
robbed_without_first = [0, nums[1]] | ||
for i in range(2, len(nums)-1): | ||
robbed_with_first.append(max(robbed_with_first[-2] + nums[i], robbed_with_first[-1])) | ||
robbed_without_first.append(max(robbed_without_first[-2] + nums[i], robbed_without_first[-1])) | ||
robbed_without_first.append(max(robbed_without_first[-2] + nums[-1], robbed_without_first[-1])) | ||
return max(robbed_with_first[-1], robbed_without_first[-1]) | ||
``` | ||
|
||
### Complexity Analysis | ||
|
||
- 時間計算量:O(n) | ||
- 家の数に比例 | ||
- 空間計算量:O(n) | ||
- 家の数分の配列が2つできる | ||
|
||
## Step 2. Alternatives | ||
|
||
- 関数に切り分けて2軒目以降の配列と最後より前の配列を処理する方法もある | ||
- シンプルで読みやすいがパッと思いつかなかった | ||
- 1人の作業者の目線でしか見れてない気がする | ||
- 2人の作業者のうち大きくなりそうな方を選ぶのが良さそう | ||
- https://github.com/tokuhirat/LeetCode/pull/36/files#diff-0ada15169c1bfbc855ba450fe39ac9bc5f80ec8f67e80356fce67b87aa72a6baR20 | ||
- index管理すればスプリットしなくてOKというお決まりの話もある | ||
- 一軒目をループに入れる方法もある | ||
- https://github.com/tokuhirat/LeetCode/pull/36/files#diff-0ada15169c1bfbc855ba450fe39ac9bc5f80ec8f67e80356fce67b87aa72a6baR63 | ||
- cacheも自然に選択肢に出てくるようにしたい | ||
- https://github.com/olsen-blue/Arai60/pull/36/files#diff-ce0cd96bb02b9d0f849c47d3ecac921373d9a9834854c70c62942f51d909f929R94 | ||
- 使うならこういうことも知っておきたい | ||
|
||
> - 結果のキャッシュは辞書なので、関数の引数は ハッシュ可能なものが必要 | ||
> | ||
> | ||
> - 引数のパターンが異なる場合は、別々のキャッシュエントリーになる | ||
> | ||
> 例えば、 f(a=1, b=2) と f(b=2, a=1) は別になる | ||
> | ||
- キーワードの順序によって別のキャッシュが作られることに関しては、ソートの計算時間を省略するためらしい | ||
- https://github.com/python/cpython/blob/39b2f82717a69dde7212bc39b673b0f55c99e6a3/Lib/functools.py#L456-L473 | ||
- 自作するとこんな感じらしい分かりやすい | ||
|
||
```python | ||
@my_cache | ||
def my_cache(func): | ||
global cache | ||
cache = dict() | ||
def wrap(*args, **kwargs): | ||
if args | ||
``` | ||
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. 正しく理解されているか記載いただいた内容からは読み取れませんでした。一度実装してみることをおすすめいたします。 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. 確かに少し変でした。修正しました。
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. cache は global とするより wrap 関数内で nonlocal と書きたいです。my_cache より広いスコープである必要はないですよね。global とすると以下のようにおかしなことが起きます。 @my_cache
def f(a, b):
return a * b
@my_cache
def g(a, b):
return a + b
print(f(1, 2)) # 2
print(g(1, 2)) # 2 さらに、cache は dict で、ミュータブルなオブジェクトを変更しているだけなので nonlocal も不要と思います。(手元で検証する際に from functools import cache とすると名前が衝突してしまい動かなくなってしまいました。名前空間を汚すのは、global を使うデメリットの一つですね。import functools として functools.cache とするのが良いということでもあると思いますが。) ちなみに、この解法の場合 rob_range は2回しか呼ばれず、cache は使われないですね。 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. nonlocalとglobalの使い分けができていませんでした。ご指摘いただきありがとうございます。 |
||
|
||
|
||
## Step 3. Final Solution | ||
|
||
- 変数名はなるべくシンプルに | ||
|
||
```python | ||
class Solution: | ||
def rob(self, nums: List[int]) -> int: | ||
def rob_range(start: int, end: int) -> int: | ||
rob = 0 | ||
rob_prev = 0 | ||
for i in range(start, end): | ||
rob_with_i = rob_prev + nums[i] | ||
rob_prev = rob | ||
rob = max(rob, rob_with_i) | ||
return rob | ||
return nums[0] if len(nums) == 1 else \ | ||
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(nums) == 1
return nums[0]
return max(rob_range(0, len(nums)-1), rob_range(1, len(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. 確かにそうですね。最初に一行で書いて、ちょっと長くなったから改行ということをしていましたがちゃんと見直すべきでした。 |
||
max(rob_range(0, len(nums)-1), rob_range(1, len(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. -の前後はスペースを入れるのが一般的だと思います。 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. Pep8はどちらでも良いらしいです。 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. 補足いただきありがとうございます。単に自分がよく見るコードがそうだっただけみたいですね。。。 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. ありがとうございます。自分も演算子の周りをどうするかは基本各自判断と記憶していて、入れたり入れなかったりですね。入れる方が良いという考えも頂戴しておきます |
||
``` | ||
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. 変数名が分かりやすかったです。 |
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.
numsに空配列が渡される場合も考慮すると,以下のような書き方もあります