Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions 198/step1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Solve Time: 10:49
//
// Space Complexity: O(n)
// Time Complexity: O(n)

/*

なんとなく方針をを決めてそのまま実装する
配列を用意して、特定の位置における最大利益、とする。
同日に隣接する箇所は襲えないので、前日の値をそのまま持ってくるか、一昨日の利益に当日の利益を足すか、のどちらかを選ぶ。

benefit += maximumBenefit[i - 2];
とすべき箇所を
benefit += nums[i - 2];
としてしまった

*/

class Solution {
public:
int rob(vector<int>& nums) {
vector<int> maximumBenefit(nums.size(), 0);
if (nums.size() == 1) {
return nums[0];
}
Comment on lines +23 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nums.size() == 1のみを例外処理している点に違和感を覚えました.
というのもnums.size() == 1でもこの行以降のコードは正しく動くからです.コーナーケースとして明示的に扱うなら,(問題の制約上あり得ないですが)nums.size() == 0(つまりnums.empty() == True)も考慮したコードの方が,実用的に感じました.

maximumBenefit[0] = nums[0];
for (int i = 1; i < nums.size(); ++i) {
int benefit = nums[i];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

benefitは単なる利益でなくnums[i]から奪った時の最大利益なので,やや説明的すぎる気もしますが,

  • benefit_with_ith_house
  • benefit_robbing_ith_house
  • benefit_robbing_last_house

などはいかがでしょうか.
(もっとも,この規模のコードならbenefitでも十分に意図は伝わると思います.)

if (i >= 2) {
benefit += maximumBenefit[i - 2];
}
maximumBenefit[i] = max(benefit, maximumBenefit[i - 1]);
}
return maximumBenefit.back();
}
};
15 changes: 15 additions & 0 deletions 198/step2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Solution {
public:
int rob(vector<int>& nums) {
vector<int> maximumBenefit(nums.size(), 0);
maximumBenefit[0] = nums[0];
for (int i = 1; i < maximumBenefit.size(); ++i) {
int benefit = nums[i];
if (i >= 2) {
benefit += maximumBenefit[i - 2];
}
maximumBenefit[i] = max(benefit, maximumBenefit[i - 1]);
}
return maximumBenefit.back();
}
};
17 changes: 17 additions & 0 deletions 198/step2_2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 2変数で行う手法
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) {
return nums.front();
}
int twoPreviousMaximumRobbedMoney = nums[0];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maximum という単語は、しばしば Max と略されるのを目にします。 Minimum も Min と略されるように思います。

int previousMaximumRobbedMoney = max(nums[0], nums[1]);
Comment on lines +8 to +9
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらは2つの状態、A:「最後に盗んだのが2つ以上前の家であるとき
」, B:「1つ以上前の家であるとき」に分けて考えたと思いますが、A ⊃ Bなので、以下のように分けると排反になって良いかなと思いました。

  • 1つ前の家をスキップしたとき = last_skipped
  • 1つ前の家に盗みに入ったとき = last_robbed
    具体的な解法は過去のコメントにあったと思います。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらなどにありますね.

一方で私は必ずしも排反にする必要性もないかな,と感じました.というのも今回は排反にすることで嬉しいことが起こるケースもありますが,今回は特に嬉しさは感じなかったためです.
むしろ,「一つ前を盗んでいる可能性があるかどうか」で場合分けする方が,条件から素直に出てくる考えでわかりやすいと感じます.
この辺は感性の問題だと思いますので,単なる一意見として参考にしてください.

for (int i = 2; i < nums.size(); ++i) {
int currentMaximumRobbedMoney = max(previousMaximumRobbedMoney, twoPreviousMaximumRobbedMoney + nums[i]);
twoPreviousMaximumRobbedMoney = previousMaximumRobbedMoney;
previousMaximumRobbedMoney = currentMaximumRobbedMoney;
}
return previousMaximumRobbedMoney;
}
};
15 changes: 15 additions & 0 deletions 198/step3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) {
return nums[0];
}
vector<int> maximumRobbedMoney(nums.size(), 0);
maximumRobbedMoney[0] = nums[0];
maximumRobbedMoney[1] = max(nums[0], nums[1]);
for (int i = 2; i < nums.size(); ++i) {
maximumRobbedMoney[i] = max(maximumRobbedMoney[i - 1], maximumRobbedMoney[i - 2] + nums[i]);
}
return maximumRobbedMoney.back();
}
};