From b522e3370b982ace20c0cd3d336d3281cb0eadf7 Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Tue, 1 Sep 2026 13:42:12 +0900 Subject: [PATCH 1/4] step1 --- 213-House-Robber-II/step1.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 213-House-Robber-II/step1.py diff --git a/213-House-Robber-II/step1.py b/213-House-Robber-II/step1.py new file mode 100644 index 0000000..4503c4b --- /dev/null +++ b/213-House-Robber-II/step1.py @@ -0,0 +1,24 @@ +class Solution: + def rob(self, nums: list[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + max_monies_from_begin = [nums[0], max(nums[0], nums[1])] + max_monies_without_begin = [0, nums[1]] + for i in range(2, len(nums)): + max_monies_from_begin.append( + max( + max_monies_from_begin[-1], + max_monies_from_begin[-2] + nums[i], + ) + ) + max_monies_without_begin.append( + max( + max_monies_without_begin[-1], + max_monies_without_begin[-2] + nums[i], + ) + ) + + return max(max_monies_from_begin[-2], max_monies_without_begin[-1]) From 11851deaabdfc04e3ba6d31ade9d17fa06e9c4e2 Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Tue, 1 Sep 2026 13:42:21 +0900 Subject: [PATCH 2/4] step2,3 --- 213-House-Robber-II/note.md | 55 ++++++++++++++++++++++++++++++++++++ 213-House-Robber-II/step2.py | 31 ++++++++++++++++++++ 213-House-Robber-II/step3.py | 29 +++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 213-House-Robber-II/note.md create mode 100644 213-House-Robber-II/step2.py create mode 100644 213-House-Robber-II/step3.py diff --git a/213-House-Robber-II/note.md b/213-House-Robber-II/note.md new file mode 100644 index 0000000..4deb0e5 --- /dev/null +++ b/213-House-Robber-II/note.md @@ -0,0 +1,55 @@ +# 213. House Robber II + +https://leetcode.com/problems/house-robber-ii/ + +## step1(まず通す) + +輪になっていない場合(198. House Robber)は、目の前の家までで盗める最高額は以下二つの max だった: + +- 目の前から盗まない→一つ前の家までの最高額 +- 目の前から盗む→二つ前の家までの最高額 + 今の家で盗める額 + +輪になっていると、リストの先頭と末尾以外は今までと同じだが、先頭と末尾は両方から盗むことはできないので、 + +1. 先頭を入れてもよくて目の前の家までで盗める最高額 +2. 2つ目の家からから始めて(先頭を含めずに)目の前の家までで盗める最高額 + +の2つを計算し続け、最後の家の 2 と一つ前の家の 1 を比較することになる。 + +## step2(整形&他の人のコードを読む) + +append するより最初にlen(nums) の長さを確保した配列用意してから値を入れていく方が見やすいかも。(漸化式っぽい見た目になるので) +→書いてみたが別にそんなことはなかった。初期化の行が増えるだけみづらいかも。 + +```python +class Solution: + def rob(self, nums: list[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + max_monies_from_begin = [0] * len(nums) + max_monies_from_begin[0] = nums[0] + max_monies_from_begin[1] = max(nums[0], nums[1]) + + max_monies_without_begin = [0] * len(nums) + max_monies_without_begin[1] = nums[1] + for i in range(2, len(nums)): + max_monies_from_begin[i] = max( + max_monies_from_begin[i - 1], + max_monies_from_begin[i - 2] + nums[i], + ) + max_monies_without_begin[i] = max( + max_monies_without_begin[i - 1], + max_monies_without_begin[i - 2] + nums[i], + ) + + return max(max_monies_from_begin[-2], max_monies_without_begin[-1]) +``` + +198. House Robber と同じく、配列は不要で2つ前まで覚えていればいいのでそれで書く。 + +## step3(10分以内にさっとかける \* 3回) + +prev と prevprev を return するのは違和感あったので変数名を変えた(これでもあんまりいいとは思わないが) diff --git a/213-House-Robber-II/step2.py b/213-House-Robber-II/step2.py new file mode 100644 index 0000000..2c81e32 --- /dev/null +++ b/213-House-Robber-II/step2.py @@ -0,0 +1,31 @@ +class Solution: + def rob(self, nums: list[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + prevprev_from_begin = nums[0] + prev_from_begin = max(nums[0], nums[1]) + current_from_begin = 0 + + prevprev_without_begin = 0 + prev_without_begin = nums[1] + current_without_bein = 0 + + for i in range(2, len(nums)): + current_from_begin = max( + prev_from_begin, + prevprev_from_begin + nums[i], + ) + prevprev_from_begin = prev_from_begin + prev_from_begin = current_from_begin + + current_without_bein = max( + prev_without_begin, + prevprev_without_begin + nums[i], + ) + prevprev_without_begin = prev_without_begin + prev_without_begin = current_without_bein + + return max(prevprev_from_begin, current_without_bein) diff --git a/213-House-Robber-II/step3.py b/213-House-Robber-II/step3.py new file mode 100644 index 0000000..12bbadd --- /dev/null +++ b/213-House-Robber-II/step3.py @@ -0,0 +1,29 @@ +class Solution: + def rob(self, nums: list[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + prev_from_begin = nums[0] + current_from_begin = max(nums[0], nums[1]) + + prev_without_begin = 0 + current_without_begin = nums[1] + + for i in range(2, len(nums)): + next_from_begin = max( + prev_from_begin + nums[i], + current_from_begin, + ) + prev_from_begin = current_from_begin + current_from_begin = next_from_begin + + next_without_begin = max( + prev_without_begin + nums[i], + current_without_begin, + ) + prev_without_begin = current_without_begin + current_without_begin = next_without_begin + + return max(current_without_begin, prev_from_begin) From 3f7f8453e78bc388be9e6041c21f317806d1da4f Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Tue, 1 Sep 2026 13:44:52 +0900 Subject: [PATCH 3/4] fix --- 213-House-Robber-II/note.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/213-House-Robber-II/note.md b/213-House-Robber-II/note.md index 4deb0e5..d617471 100644 --- a/213-House-Robber-II/note.md +++ b/213-House-Robber-II/note.md @@ -16,7 +16,7 @@ https://leetcode.com/problems/house-robber-ii/ の2つを計算し続け、最後の家の 2 と一つ前の家の 1 を比較することになる。 -## step2(整形&他の人のコードを読む) +## step2(整形) append するより最初にlen(nums) の長さを確保した配列用意してから値を入れていく方が見やすいかも。(漸化式っぽい見た目になるので) →書いてみたが別にそんなことはなかった。初期化の行が増えるだけみづらいかも。 From 35b09ad517a1970645c9f52fa1856b18243e167b Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Fri, 4 Sep 2026 18:21:14 +0900 Subject: [PATCH 4/4] step4 --- 213-House-Robber-II/note.md | 8 ++++++++ 213-House-Robber-II/step4.py | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 213-House-Robber-II/step4.py diff --git a/213-House-Robber-II/note.md b/213-House-Robber-II/note.md index d617471..912dfee 100644 --- a/213-House-Robber-II/note.md +++ b/213-House-Robber-II/note.md @@ -53,3 +53,11 @@ class Solution: ## step3(10分以内にさっとかける \* 3回) prev と prevprev を return するのは違和感あったので変数名を変えた(これでもあんまりいいとは思わないが) + +## step4 + +> 同じロジックを 2 回書くより、ロジックを関数にくくりだし、開始インデックスと終了インデックスを 2 種類渡して max を取るほうがシンプルになると思いました。 + +これで書いてみる + +実質的な初期値(`nums[begin]` など)をあらかじめ代入して range(begin + 2, end) でループするか、仮の初期値 0 を入れておいて range(begin, end) でループするかは迷う。みて意味がわかりやすいのは前者な気がするが、配列のインデックスの範囲を気にする必要がありちょっと煩雑か。 diff --git a/213-House-Robber-II/step4.py b/213-House-Robber-II/step4.py new file mode 100644 index 0000000..657eaa7 --- /dev/null +++ b/213-House-Robber-II/step4.py @@ -0,0 +1,22 @@ +class Solution: + def rob(self, nums: list[int]) -> int: + def calculate_max_money(begin: int, end: int) -> int: + prev_max = 0 + current_max = 0 + + for i in range(begin, end): + next_max = max(prev_max + nums[i], current_max) + prev_max = current_max + current_max = next_max + + return current_max + + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + return max( + calculate_max_money(0, len(nums) - 1), + calculate_max_money(1, len(nums)), + )