Skip to content
Open
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
112 changes: 112 additions & 0 deletions 39/39.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
## 何も見ずに解いてみる

```cpp
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> result;
vector<int> initial_combination;
combinationSumHelper(candidates, initial_combination, target, result);
return result;
}
private:
void combinationSumHelper(vector<int>& candidates, vector<int> combination, int target, vector<vector<int>>& result) {
if (target == 0) {
result.emplace_back(combination);
return;
}
if (candidates.empty()) {
return;
}
int num = candidates.back();
candidates.pop_back();
while (target >= 0) {
combinationSumHelper(candidates, combination, target, result);
combination.emplace_back(num);
target -= num;
}
candidates.emplace_back(num);
}
};
```

## 他の人のコードを見てみる

https://github.com/tokuhirat/LeetCode/pull/52/files
https://github.com/ryosuketc/leetcode_arai60/pull/41/files
https://github.com/Ryotaro25/leetcode_first60/pull/56/files

最初に書いたコードはcombinationが値渡しであったことで結構時間がかかっていたようです。
以下のようにするだけでleetcode上の実行時間が20msぐらいから1msぐらいになりました。

```cpp
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> result;
vector<int> combination;
combinationSumHelper(candidates, combination, target, result);
return result;
}
private:
void combinationSumHelper(vector<int>& candidates, vector<int>& combination, int target, vector<vector<int>>& result) {
if (target == 0) {
result.emplace_back(combination);
return;
}
if (candidates.empty()) {
return;
}
int num = candidates.back();
candidates.pop_back();
while (target >= 0) {
combinationSumHelper(candidates, combination, target, result);
combination.emplace_back(num);
target -= num;
}
candidates.emplace_back(num);
while (!combination.empty() && combination.back() == num) {
combination.pop_back();
}

Choose a reason for hiding this comment

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

while (target >= 0) が回る回数を数えておき、以下のようにした方が直接理解しやすいと思いました。

        while (count) {
            combination.pop_back();
            --count;
        }

}
};
```

大きい数字から見ていったほうが若干高速ではありそうですが、出力の形がきれいじゃなくなってしまいますね。

## 最終コード

```cpp
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> result;
vector<int> initial_combination;
combinationSumHelper(candidates, initial_combination, 0, target, result);
return result;
}
private:
void combinationSumHelper(
const vector<int>& candidates,
vector<int>& combination,
int processed_until,

Choose a reason for hiding this comment

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

processed_until は candidates のインデックスなので、candidates の直後に書きたいです。また好みではありますが、start ぐらいでも伝わるかなと思いました。
元の引数が candidates なのでなんとも言えないところですが、combination も results に入るかどうかの候補なので、candidates は nums とした方が自然に読みやすいと思いました。

Choose a reason for hiding this comment

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

説明的ではあると思うのですが、candidates_index など、インデックスであることがわかりやすい名前のほうがよいかなと思いました。

int target,
vector<vector<int>>& result
) {
if (target < 0) {
return;
}
if (target == 0) {
result.emplace_back(combination);
return;
}
for (int i = processed_until; i < candidates.size(); ++i) {
combination.emplace_back(candidates[i]);
combinationSumHelper(candidates, combination, i, target - candidates[i], result);
combination.pop_back();
}
}
};
```

最後のiという変数名にはもう少し意味を持たせたいと思ったのですが、あまり簡潔な変数名が思いつかず・・・