-
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?
Conversation
| @@ -0,0 +1,97 @@ | |||
| ### Step1 | |||
|
|
|||
| - 大学受験の漸化式っぽい問題 | |||
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全般そうですよね〜。
| ### Step1 | ||
|
|
||
| - 大学受験の漸化式っぽい問題 | ||
| - 配列や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.
resultだとあまり意味を含んでいないので他の命名が良いかなと思いました。max_amount_so_farとか、のようにresultの部分をもう少しカラフルにすると良いかなと思います。
| 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 comment
The reason will be displayed to describe this comment to others. Learn more.
自分なら二次元配列にしないで、インデックスで表される家に盗みに入るのと入らないのと2つの配列を作るかなと思いました。
| ```python | ||
|
|
||
| class Solution: | ||
| def rob(self, nums: List[int]) -> int: |
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.
なんか変数名が全体的にふわっとしていて読むのが難しかったです。たぶんrecentlyというワードチョイスも良くないと思います、なにを指しているのかが曖昧なので、結局コードを全部読む必要がありました。
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.
ありがとうございます。recentlyは実態と違っており良くなかったと今改めて見て思いました。lastの方が適切でした。
あと2つはmax_amount_so_farと、max_amount_prevですかねえ。max_amount_prevが特に、これでわかりやすいかが迷います。
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.
skipped_previous, robbed_previous とかどうでしょうか。
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.
[1]を2変数で書き直すと[2]になります。@nittocoさんの方法と同じだと思います。多重代入を使わないと一時変数が必要になります。[3]は変数の意味が、元の@nittocoさんの方法とは少し異なります。
[1]
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);
}
};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.
皆さんありがとうございます。
そうですよね、skipped_previous, robbed_previous という変数名だと、Step3で書いたコードだと違ってくるかなと思いました(Step1を2変数にしたのに近い)
max_amount, previous_max_amount, skipped_previousあたりですかね(難しい)
| 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 comment
The reason will be displayed to describe this comment to others. Learn more.
max_amount_can_rob という変数名だと「max amount(主語)は奪うことができる」という風に読めるため、個人的には違和感がありました。(can が使われていると bool をイメージします)
max_robbed_amount や max_robbery_amount くらいで、can の要素を明示的に入れなくても伝わりそうです。
また2次元配列の部分ですが、クラス変数を使って index を扱うのは(少なくとも僕は)見たことがないです。初見で何をしているかがわかりづらかったので、避けたほうがよさそうです。hayashi-ay さんが書いているように2つに分けるか、クラスを定義してあげるとわかりやすくなりそうです。(クラス定義はやり過ぎ感があるかもですが)
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.
max_amount_can_robという変数名だと「max amount(主語)は奪うことができる」という風に読めるため、個人的には違和感がありました。(can が使われていると bool をイメージします)max_robbed_amountやmax_robbery_amountくらいで、can の要素を明示的に入れなくても伝わりそうです。
なるほど、確かにそう読めますね。
なかなかまだ読む人の心のモデルを構築できないです(英語力の問題もあるかも)
また2次元配列の部分ですが、クラス変数を使って index を扱うのは(少なくとも僕は)見たことがないです。初見で何をしているかがわかりづらかったので、避けたほうがよさそうです。hayashi-ay さんが書いているように2つに分けるか、クラスを定義してあげるとわかりやすくなりそうです。(クラス定義はやり過ぎ感があるかもですが)
なるほど、「見たことない」のはかなり判断の基準になります。ありがとうございます。
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は泥棒に入ろうとしている順に家のお金が並んでいますが、max_amount_can_robの要素の配列の中身の順序は、特に意味がないのかなと思います。
もっと極端な例を考えると、順序のない状態をn個考えて、それらを配列で管理すると、配列のインデックスとの対応が任意(書く人の決めの問題)なので、かなり分かりにくくなるんじゃないでしょうか。
要は、マジックナンバーを避けるために変数を定義するくらいなら、最初から辞書やデータクラスでキーアクセスする方が自然なんじゃないかなと。
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.
これ納得感がありすっきりしました。ありがとうございます。
0, 1のDPというのはAtcoderとかだとテクニックとしてあるんですが、実用コード書く時は少し慎重にしてもいいかもですね。
| def rob(self, nums: List[int]) -> int: | ||
| max_amount_can_rob = [[0] * 2 for _ in range(len(nums) + 1)] | ||
| 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 comment
The reason will be displayed to describe this comment to others. Learn more.
passed_house_count は変数名の長さに対してわかりやすくはなっていない(むしろ読みにくくなっている)ように思いました。「通過した軒数」≒「何番目の軒数」と言えそうなので、個人的には i で十分な気がします。(for ループの時点で nums を順番に見ていくことはわかりそうです)
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.
ありがとうございます。
そうですねえ、ただ for i in range(nums) は、問題文の意味からちょっとわかりにくい気が個人的にしてます。
LeetCode側の問題ですが、numsが良くない気がします(house_to_money_amountとかならiでわかる気がします。
| - 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Yoshiki-Iwasa/Arai60#50 (comment)
このodaさんのコメント、自分はしっくり来ました。
あとから他のDPを解き直すときもリアルな情景をイメージすると自然に解法までたどり着く印象があります
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.
ありがとうございます。
そうですね。確かに、リアルな状況を思い浮かべると、変数名も付けやすい気がしてます。(自分も変数名なかなかうまくつけれてないですが…)
|
見ました。自分もすでに議論済みの変数名の部分が気になりましたが、それ以外は良いと思いました。 |
URL: https://leetcode.com/problems/house-robber/description/
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.