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
61 changes: 61 additions & 0 deletions 1_two_sum/answer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
問題:https://leetcode.com/problems/two-sum/description/

## step1
問題は
1.numsという配列と整数targetを与えられる。
2.numsの中から二つの値の和がtargetになる組を見つけてreturnする。この組は一つしかない。
というもの。

arai60の分類だとhashmapに該当するのだが、どこでmapを使うべきかわからなかった。
今までの問題だとsum_to_pairのmapを作ることが多かった。
前回の問題でも(https://leetcode.com/problems/find-k-pairs-with-smallest-sums/) 、そのようなsum_to_pairで全走査する方式を使って上手くいかなかったが思いつかなかったので今回も全走査した。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちらのことでしょうか?そうでしたら、mapではなくて、pairですね。
https://github.com/nicah4o/arai60/pull/10/files#diff-4441ba9bfe4587a375388da6cd11a2db15081cba994b37ca9f2ec8fddf3b327eR22-R23

        using pi = pair<int, vector<int>>;
        priority_queue<pi, vector<pi>, greater<pi>> sum_to_pair;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。


ただ、返り値が一意に定まるという条件があるので、mapは作らずに合計値がtargetになる組を二重のforで探すのみにした。

```cpp
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int i, j;
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 = 0; i <= (nums.size() - 1); i++)のように使う直前に宣言すると良いと思います。

for (i = 0; i <= (nums.size() - 1); 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.

この(nums.size() - 1)で、外側のかっこが無いほうが見慣れた感じで好みです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

レビューありがとうございます。
理解不足で括弧必要だと勘違いしていました。
i < nums.size()でもいけますね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

演算子の優先順位で調べてみると良いと思います。自明ではないなら、不要でも括弧をつけるのもありですね。

https://en.cppreference.com/cpp/language/operator_precedence

for (j = i + 1; j <= (nums.size() - 1); j++) {
if (nums[i] + nums[j] == target) {
vector<int> ans = {i, j};
return ans;
}
}
}
return {};
}
};
```

時間計算量がO(N^2)で空間計算量はO(1)。acceptされたが43msで最頻値が0ms,2msなので20倍以上遅い解法である。

## step2
leetcodeの解法見た。unordered_mapをsum_to_pairでなくnum_to_indexで作る。
targer-nums[i] をnum_to_indexで検索すると一瞬で答えがわかる。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hash tableの仕組み(衝突回避やリアロケーションなど)についても、まだ調べていなかったら見てみると良いと思います。
https://en.wikipedia.org/wiki/Hash_table

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

レビューありがとうございます。
ハッシュテーブルの仕組みについては調べていなかったのでリンク参考になります。
挙げていただいた論点についても調べてみます。

この問題で真に求めたいのはペアの数字の値じゃなくてインデックスであるということを分からないと解けない。

```cpp
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> num_to_index;
for (int i = 0; i < nums.size(); i++) {
int complement = target - nums[i];
if (num_to_index.contains(complement)) {
vector<int> ans = {i, num_to_index[complement]};
Copy link
Copy Markdown

@TaisukeFujise TaisukeFujise May 13, 2026

Choose a reason for hiding this comment

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

以下のように直接returnをかけるので、ansのような一次変数におく必要はないと思います。

return {i, num_to_index[complement]};

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

レビューありがとうございます。
なるほど、なぜか3msから変わらないと思っていたらこの変数がボトルネックになっていました。
ご指摘助かりました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

コンパイラでおそらく最適化されますし、これがボトルネックになることはないと思います。実行時間のブレは、LeetCodeの環境によるものかと思われます。

return ans;
}
else {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ifの中で returnしているので、このelseを消してインデントを下げられますね。どちらでも趣味の範囲だと思います。

num_to_index.insert({nums[i], i});
}
}
return {};
}
};
```

時間計算量はO(N)で空間計算量もO(N)。
実装では特に先にmapにメモして探すのではなく探してからメモするという仕組みが思いつかなかった。