-
Notifications
You must be signed in to change notification settings - Fork 0
198. House Robber #39
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,97 @@ | ||
| ### Step1 | ||
|
|
||
| - 大学受験の漸化式っぽい問題 | ||
| - 配列やresult_so_farあたりの命名は迷った | ||
|
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. resultだとあまり意味を含んでいないので他の命名が良いかなと思いました。 |
||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| IS_ROBBING = 1 | ||
| NOT_ROBBING = 0 | ||
|
|
||
| def rob(self, nums: List[int]) -> int: | ||
| max_amount_can_rob = [[0] * 2 for _ in range(len(nums) + 1)] | ||
|
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.
また2次元配列の部分ですが、クラス変数を使って index を扱うのは(少なくとも僕は)見たことがないです。初見で何をしているかがわかりづらかったので、避けたほうがよさそうです。hayashi-ay さんが書いているように2つに分けるか、クラスを定義してあげるとわかりやすくなりそうです。(クラス定義はやり過ぎ感があるかもですが)
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.
なるほど、確かにそう読めますね。
なるほど、「見たことない」のはかなり判断の基準になります。ありがとうございます。 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. 配列に違和感を感じる理由を考えていたんですけど、順序に意味がないからなのかなと思いました。 もっと極端な例を考えると、順序のない状態をn個考えて、それらを配列で管理すると、配列のインデックスとの対応が任意(書く人の決めの問題)なので、かなり分かりにくくなるんじゃないでしょうか。
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. これ納得感がありすっきりしました。ありがとうございます。 |
||
| result_so_far = 0 | ||
| for passed_house_count in range(1, len(nums) + 1): | ||
|
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. ありがとうございます。 |
||
| max_amount_can_rob[passed_house_count][self.IS_ROBBING] = ( | ||
| max_amount_can_rob[passed_house_count - 1][self.NOT_ROBBING] | ||
| + nums[passed_house_count - 1] | ||
| ) | ||
| max_amount_can_rob[passed_house_count][self.NOT_ROBBING] = result_so_far | ||
| result_so_far = max( | ||
| max_amount_can_rob[passed_house_count][self.IS_ROBBING], | ||
| max_amount_can_rob[passed_house_count][self.NOT_ROBBING], | ||
| ) | ||
| return result_so_far | ||
| ``` | ||
|
|
||
| ### Step2 | ||
|
|
||
| - よく考えたら、いくつ家を通過したかを表すindexはいらない(こういうのつけちゃう癖がある) | ||
| - 前の状態をたくさん持ってる必要がある時以外はいらないということか | ||
| - ただ、IS_ROBBINGの変数が何を表しているかわからなくなるかも(一応コメントをつけた) | ||
| - max_amount_can_rob[self.RECENT_PASSED]の値が、for文の1回目で出てくる時と2回め以降で意味が違ってくる(しかも1行目でそれ使って代入してる)のはわかりにくい? | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| # 最新の家から盗んだかどうか | ||
| IS_ROBBING = 1 | ||
| RECENT_PASSED = 0 | ||
|
|
||
| def rob(self, nums: List[int]) -> int: | ||
| max_amount_can_rob = [0] * 2 | ||
| result_so_far = 0 | ||
| for house_count in range(1, len(nums) + 1): | ||
| max_amount_can_rob[self.IS_ROBBING] = ( | ||
| max_amount_can_rob[self.RECENT_PASSED] + nums[house_count - 1] | ||
| ) | ||
| max_amount_can_rob[self.RECENT_PASSED] = result_so_far | ||
| result_so_far = max( | ||
| max_amount_can_rob[self.IS_ROBBING], | ||
| max_amount_can_rob[self.RECENT_PASSED], | ||
| ) | ||
| return result_so_far | ||
| ``` | ||
|
|
||
| - https://github.com/fhiyo/leetcode/pull/36/files | ||
| - 結構読み解くのに時間かかった。思考回路が多分自分と違った。 | ||
| - 多分、前2つのうちどちらが最後に盗んだかで分けよう!というのが思考回路として最初に出てる?ので、今の家で盗んだか盗んでないかで分けようというのが自分と思考回路が違ったのかな | ||
| - フィボナッチ数列のちょっと変えたやつみたいな(説明が下手) | ||
| - max_money_so_farの、[1]と[0]がそれぞれ何を表しているのかわからない、というのはあるかも | ||
| - https://github.com/seal-azarashi/leetcode/pull/33 | ||
| - twoBackとあるので、やはり最後に盗んだのが2つ前か1つ前かという思考らしい | ||
| - どうせ保存する値は2つなので、わざわざ配列にする必要ないのは確かに | ||
| - numsが空の場合の例外処理をちゃんと考えてなかったが、上の自分の実装の場合は結果的に0になる(書かなくて良いにしてもちゃんと考えた方が良かった) | ||
| - https://github.com/Ryotaro25/leetcode_first60/pull/36 | ||
| - https://github.com/rossy0213/leetcode/pull/20/files | ||
| - dpの長さをlen(nums) + 2になるのはマジックナンバー感がありあまり好みでない | ||
| - https://github.com/YukiMichishita/LeetCode/pull/16 | ||
| - 今を含むかで場合わけしており、自分と思考が近め | ||
| - https://github.com/shining-ai/leetcode/pull/35 | ||
| - currentではなくmax_amount_1_beforeを返すのはあんまり納得いかないかも | ||
| - maxのdefaultは勉強になったが、あまり好まないかも | ||
| - https://github.com/hayashi-ay/leetcode/pull/48/files | ||
| - 結構前2つのmaxという発想の人は多いみたい | ||
| - https://github.com/Yoshiki-Iwasa/Arai60/pull/50/files | ||
| - rob_3が自分の思考回路と近そうだが、命名がしっくりこなかった(コメントがあったのでスムーズに読めはした) | ||
|
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. Yoshiki-Iwasa/Arai60#50 (comment) このodaさんのコメント、自分はしっくり来ました。
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. ありがとうございます。 |
||
|
|
||
| ## Step3 | ||
|
|
||
| - DPらしさが跡形もなくなったが、以下のようになった | ||
| - 自然な気がする | ||
| - 長さが0, 1の場合の例外処理がいらないのも好み | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def rob(self, nums: 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. ありがとうございます。recentlyは実態と違っており良くなかったと今改めて見て思いました。lastの方が適切でした。 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. skipped_previous, robbed_previous とかどうでしょうか。 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. [1]を2変数で書き直すと[2]になります。@nittocoさんの方法と同じだと思います。多重代入を使わないと一時変数が必要になります。[3]は変数の意味が、元の@nittocoさんの方法とは少し異なります。 class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) {
return nums[0];
}
nums[1] = max(nums[0], nums[1]);
for (int i = 2; i < nums.size(); ++i) {
nums[i] = max(nums[i - 1], nums[i] + nums[i - 2]);
}
return nums.back();
}
};[2] class Solution {
public:
int rob(vector<int>& nums) {
int max_amount = 0, previous_max_amount = 0;
for (int num : nums) {
int next_previous_max_amount = max_amount;
max_amount = max(max_amount, previous_max_amount + num),
previous_max_amount = next_previous_max_amount;
}
return max_amount;
}
};[3] class Solution {
public:
int rob(vector<int>& nums) {
int skipped_previous = 0;
int robbed_previous = 0;
for (int num : nums) {
int next_skipped_previous = max(skipped_previous, robbed_previous);
robbed_previous = skipped_previous + num;
skipped_previous = next_skipped_previous;
}
return max(skipped_previous, robbed_previous);
}
};
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_result = 0 | ||
| result_so_far = 0 | ||
| recently_passed = 0 | ||
| for money_amount_in_house in nums: | ||
| result_so_far = max(prev_result, recently_passed + money_amount_in_house) | ||
| recently_passed = prev_result | ||
| prev_result = result_so_far | ||
| return result_so_far | ||
| ``` | ||
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.
分かります。まあDP全般そうですよね〜。