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
Binary file added 1_two_sum/a.out
Binary file not shown.
136 changes: 136 additions & 0 deletions 1_two_sum/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# 1. Two Sum

https://leetcode.com/problems/two-sum/description/

初めてCPPで書いてみる。


## Comments

### step1
```C++
#include <iostream>
#include <vector>
#include <unordered_map>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

細かいですが、includeはアルファベット順がいいと思いました。

Within each section the includes should be ordered alphabetically.
https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes


std::vector<int> twoSum(std::vector<int>& nums, int target) {
std::unordered_map<int, int> num_to_index;

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

C++スタイルのstatic_cast(nums.size())とする方がいいと思います。
これはキャストの見つけやすさとキャストの意図が明確になることからMore Effective c++の第二項で推奨されておりました。

int complement = target - nums[i];
if (num_to_index.find(complement) != num_to_index.end()) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

unordered_mapにはcontainsというものがございます。
if (num_to_index.contains(complement))と書くこともできます。
https://en.cppreference.com/w/cpp/container/unordered_map/contains.html

return {num_to_index[complement], i};
}
num_to_index[nums[i]] = i;
}
return {};
Comment on lines +19 to +26
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;
	for (const auto& num : nums) {
		int complement = target - num;
		if (num_to_index.find(complement) != num_to_index.end()) {
			return {num_to_index[complement], i};
		}
		num_to_index[num] = i;
		i++;
	}
	return {};

}

int main() {
std::vector<int> nums = {2, 7, 11, 15};
int target = 9;

std::vector<int> result = twoSum(nums, target);
std::cout << "Indices : " << result[0] << ", " << result[1] << std::endl;

return 0;
}
```

とりあえず、答え見ながら写して書いてみた。
全体的にC言語と同じ。
#include と、型宣言の書き方が違うくらい。
vectorが便利すぎる。mallocもfreeもしなくていいのすごい。
.find .sizeなどで、一気に個数などを求められるのも便利。
とりあえず、次は見ずに書いてみる。

*

### step2
```c++
#include <iostream>
#include <vector>
#include <unordered_map>

std::vector<int> twoSum(std::vector<int>& nums, int target) {
std::unordered_map<int, int> num_to_index;

for (int i = 0; i < (int)nums.size() ; ++i) {
int complement = target - nums[i];
if (num_to_index.find(complement) != num_to_index.end()) {
return {num_to_index[complement], i};
}
num_to_index[nums[i]] = i;
}
return {};
}

int main() {
std::vector<int> nums = {2, 7, 11, 15};
int target = 9;

std::vector<int> result =twoSum(nums, target);
std::cout << "Indices : " << result[0] << ", " << result[1] << std::endl;

return 0;
}
```

全然見ずに書けなかったので諦め。
やっぱ理解していないところは書けない。
特にunordered_mapの使い方がわからなかった。
これなんや???
調べてみる。

[unordered_map - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/unordered_map/unordered_map.html)

hash tableらしい。
今回使用しているのは、intを入れてintを返すモノかな。
うーん、いまいちイメージがつかない。
Comment on lines +87 to +89
Copy link
Copy Markdown

@skypenguins skypenguins Jun 12, 2025

Choose a reason for hiding this comment

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

unordered_mapは、ハッシュマップなのでPythonでいうdict(辞書)ですね。今回はint型とint型を組にしているので、たまたま「intを入れてintを返す」動作になっています。

```c++
for (int i = 0; i < (int)nums.size() ; ++i) {
int complement = target - nums[i];
if (num_to_index.find(complement) != num_to_index.end()) {
return {num_to_index[complement], i};
}
num_to_index[nums[i]] = i;
}
```
構造的には、for → ifなので、「初めて〇〇したとき」という論理。
今回の問題から逆算すると、おそらく「初めて2つの和がtargetと一致したとき」ということだろう。
ってことは、if文内条件式は、「2つの和が一致したとき」。
この時に、num_to_index[complement]は、complementの値を持つ要素のindexを返す。
そして、iは現在の要素のindex。

うーん、イマイチわからん!!
もう一回書いてみるか。
*

### step3
```c++
#include <iostream>
#include <vector>
#include <unordered_map>

std::vector<int> twoSum(std::vector<int>& nums, int target) {
std::unordered_map<int, int> num_to_index;
for (int i = 0; i < (int)nums.size(); ++i) {
int complement = target - nums[i];
if (num_to_index.find(complement) != num_to_index.end()) {
return {num_to_index[complement], i};
}
num_to_index[nums[i]] = i;
}
return {};
}

int main() {
std::vector<int> nums = {2, 11, 3, 4, 6, 7};
int target = 9;
std::vector<int> result = twoSum(nums, target);
std::cout << "Incides : " << result[0] << ", " << result[1] << std::endl;
return 0;
}
```
やっぱ、unordered_mapの使い方がわからない...
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C で関数を呼ぶとき、関数の中身を把握するというレイヤーと関数を呼んだら何が起きるかというレイヤーの2つがあると思うんですが、データ構造も、どういう中身なのかと、外から見たらどういうものなのかという2つの層があるように思います。まずは、外から見たらどういうものかを考えてみたらよいかと思います。

*
26 changes: 26 additions & 0 deletions 1_two_sum/step1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <iostream>
#include <vector>
#include <unordered_map>

std::vector<int> twoSum(std::vector<int>& nums, int target) {
std::unordered_map<int, int> num_to_index;

for (int i = 0; i < (int)nums.size(); ++i) {
int complement = target - nums[i];
if (num_to_index.find(complement) != num_to_index.end()) {
return {num_to_index[complement], i};
}
num_to_index[nums[i]] = i;
}
return {};
}

int main() {
std::vector<int> nums = {2, 7, 11, 15};
int target = 9;

std::vector<int> result = twoSum(nums, target);
std::cout << "Indices : " << result[0] << ", " << result[1] << std::endl;

return 0;
}
26 changes: 26 additions & 0 deletions 1_two_sum/step2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <iostream>
#include <vector>
#include <unordered_map>

std::vector<int> twoSum(std::vector<int>& nums, int target) {
std::unordered_map<int, int> num_to_index;

for (int i = 0; i < (int)nums.size() ; ++i) {
int complement = target - nums[i];
if (num_to_index.find(complement) != num_to_index.end()) {
return {num_to_index[complement], i};
}
num_to_index[nums[i]] = i;
}
return {};
}

int main() {
std::vector<int> nums = {2, 7, 11, 15};
int target = 9;

std::vector<int> result =twoSum(nums, target);
std::cout << "Indices : " << result[0] << ", " << result[1] << std::endl;

return 0;
}
23 changes: 23 additions & 0 deletions 1_two_sum/step3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <iostream>
#include <vector>
#include <unordered_map>

std::vector<int> twoSum(std::vector<int>& nums, int target) {
std::unordered_map<int, int> num_to_index;
for (int i = 0; i < (int)nums.size(); ++i) {
int complement = target - nums[i];
if (num_to_index.find(complement) != num_to_index.end()) {
return {num_to_index[complement], i};
}
num_to_index[nums[i]] = i;
Comment on lines +6 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

この場合,unordered_mapのkeyに相当するのは,今までの数字の中でnums[i]を足すとtargetになる数(complement)だと思うのでnum_to_indexよりはcomp_to_indexなどのほうが適切かもしれませんね

}
return {};
}

int main() {
std::vector<int> nums = {2, 11, 3, 4, 6, 7};
int target = 9;
std::vector<int> result = twoSum(nums, target);
std::cout << "Incides : " << result[0] << ", " << result[1] << std::endl;
return 0;
}
Binary file added 1_two_sum/two_sum
Binary file not shown.