From f0e9d40f5c537251fced1cd04facf00ffd7abf3a Mon Sep 17 00:00:00 2001 From: mayota Date: Tue, 16 Jun 2026 20:44:32 +0900 Subject: [PATCH 1/5] step1 --- 1-Two-Sum/note.md | 23 +++++++++++++++++++++++ 1-Two-Sum/step1.py | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 1-Two-Sum/note.md create mode 100644 1-Two-Sum/step1.py diff --git a/1-Two-Sum/note.md b/1-Two-Sum/note.md new file mode 100644 index 0000000..8a7459e --- /dev/null +++ b/1-Two-Sum/note.md @@ -0,0 +1,23 @@ +# 1. Two Sum + + + +## step1(まず通す) + +配列長さ n に対して、任意の2要素の和を計算しようとすると n(n+1)/2 回の足し算とそれを保存するスペースが必要だが、以下のやり方で時間計算量、空間計算量ともに O(n) でできる + +1. `{num:list of indices}` の辞書を作る +2. nums の先頭から順に、 キーが `target - num` であるような辞書の要素(num と足して target になってくれるような他の `nums` の要素)が存在するかを見ていく + +気をつけるポイント + +1. 同じ値が複数ある時は index はリストになる +2. その際、 3+3=6 みたいな時はリストの中からインデックスを選ぶ方法に注意する(同じインデックスのペアは禁止) + 1. 結局書いたコードは、答えが一意じゃなくても最初に見つかったやつを返してくれるコードになった + 2. 答えが一意を鵜呑みにするなら、ペアが見つかった時に以下のように判定できるが汎用性が低そう + 1. pair_indices が長さ 1 なら [index, pair_indices[0]] が答え + 2. pair_indices の長さが 2 なら pair_indices が答え + +## step2(整形&他の人のコードを読む) + +## step3(10分以内にさっとかける * 3回) diff --git a/1-Two-Sum/step1.py b/1-Two-Sum/step1.py new file mode 100644 index 0000000..8442ac4 --- /dev/null +++ b/1-Two-Sum/step1.py @@ -0,0 +1,24 @@ +from typing import Dict, List + + +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + num_to_indices: Dict[int, List[int]] = {} + for index in range(len(nums)): + num = nums[index] + if num in num_to_indices: + num_to_indices[num].append(index) + else: + num_to_indices[num] = [index] + + for index in range(len(nums)): + num = nums[index] + pair_indices = num_to_indices.get(target - num) + if pair_indices is None: + continue + pair_indices = [ + pair_index for pair_index in pair_indices if pair_index != index + ] + if not pair_indices: + continue + return [index, pair_indices[0]] From e774690a9d27fb5a4e528e34f0d807a7f4bda8c4 Mon Sep 17 00:00:00 2001 From: mayota Date: Tue, 16 Jun 2026 20:54:53 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=E8=A8=98=E8=BF=B0=E3=81=AE=E9=96=93?= =?UTF-8?q?=E9=81=95=E3=81=84=E3=81=AB=E6=B0=97=E3=81=A5=E3=81=84=E3=81=9F?= =?UTF-8?q?=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-Two-Sum/note.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/1-Two-Sum/note.md b/1-Two-Sum/note.md index 8a7459e..2b7be0e 100644 --- a/1-Two-Sum/note.md +++ b/1-Two-Sum/note.md @@ -4,7 +4,7 @@ ## step1(まず通す) -配列長さ n に対して、任意の2要素の和を計算しようとすると n(n+1)/2 回の足し算とそれを保存するスペースが必要だが、以下のやり方で時間計算量、空間計算量ともに O(n) でできる +配列長さ n に対して、任意の2要素の和を計算しようとすると n(n+1)/2 回の足し算~~とそれを保存するスペース~~が必要だが、以下のやり方で時間計算量、空間計算量ともに O(n) でできる 1. `{num:list of indices}` の辞書を作る 2. nums の先頭から順に、 キーが `target - num` であるような辞書の要素(num と足して target になってくれるような他の `nums` の要素)が存在するかを見ていく @@ -17,7 +17,19 @@ 2. 答えが一意を鵜呑みにするなら、ペアが見つかった時に以下のように判定できるが汎用性が低そう 1. pair_indices が長さ 1 なら [index, pair_indices[0]] が答え 2. pair_indices の長さが 2 なら pair_indices が答え + 3. 実は、num_to_indices は index のリストじゃなくて同じ値のうち最後に見つかったやつのインデックスだけを持ってもいい + 1. 答えを一つだけ返すという前提なら答えが一意じゃなくてもこれでいい + 2. しかし、「あれ、これでいいんだっけ?」とはなりやすそうだし target になる全部のペア返して、となった時に変更が大きくなりそう ## step2(整形&他の人のコードを読む) +先ほどは +> 実は、num_to_indices は index のリストじゃなくて同じ値のうち最後に見つかったやつのインデックスだけを持ってもいい +> +> 答えを一つだけ返すという前提なら答えが一意じゃなくてもこれでいい +> +> しかし、「あれ、これでいいんだっけ?」とはなりやすそうだし target になる全部のペア返して、となった時に変更が大きくなりそう + +と思っていたが、今回のコードだと1つだけ持った方がコード自体がとてもシンプルになるという利点があるのでそっちで書いてみる + ## step3(10分以内にさっとかける * 3回) From 3ebab03a7c3f484088176a066b31a31295273e05 Mon Sep 17 00:00:00 2001 From: mayota Date: Tue, 16 Jun 2026 21:53:19 +0900 Subject: [PATCH 3/5] step2 --- 1-Two-Sum/note.md | 15 +++++++++++++++ 1-Two-Sum/step2.py | 9 +++++++++ 1-Two-Sum/step2_sort.py | 14 ++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 1-Two-Sum/step2.py create mode 100644 1-Two-Sum/step2_sort.py diff --git a/1-Two-Sum/note.md b/1-Two-Sum/note.md index 2b7be0e..2146ac4 100644 --- a/1-Two-Sum/note.md +++ b/1-Two-Sum/note.md @@ -32,4 +32,19 @@ と思っていたが、今回のコードだと1つだけ持った方がコード自体がとてもシンプルになるという利点があるのでそっちで書いてみる +- + - nums を1回だけなめて辞書に詰める or ペアを見つける の2者択一をやると速いし、自分自身とのペアになっていないかをチェックしなくて良い + - 型は 3.9 からビルトインの小文字の方を使うのが推奨になっているようだ + - + - ループの最初で `num = nums[index]` しなくて `enumerate` でいい + - ソートする方とはなんだろう? + - ソートして、先頭と末尾の和から見ていって↓を繰り返すとか? + - 和が target より大きいなら、後ろのポインタを一つ前に + - 〃小さいなら、前のポインタを一つ後ろに + - これでうまくいくの? + - うまく例が作れないがポインタが行きすぎてしまったりしないのか? + - いろんな例を考えてるがならなそう + - 証明: `num[answer1] + num[answer2] (answer1 < answer2) = target` になるとき、`i < answer1 < answer2 < j` に対しての `num[i] + num[j]` は target より大きいか小さいかわからないけど、`num[i] + num[answer2] < target < num[answer1] + num[j]` なのでどちらかが answer に到達した時点であとはもう片方が答えに近づくだけであり行きすぎることはない。 + - 指滑らせて棒の重心探すやつみたい + ## step3(10分以内にさっとかける * 3回) diff --git a/1-Two-Sum/step2.py b/1-Two-Sum/step2.py new file mode 100644 index 0000000..ce9f2a8 --- /dev/null +++ b/1-Two-Sum/step2.py @@ -0,0 +1,9 @@ +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + num_to_index = {} + for index, num in enumerate(nums): + pair_index = num_to_index.get(target - num) + if pair_index is None: + num_to_index[num] = index + continue + return [index, pair_index] diff --git a/1-Two-Sum/step2_sort.py b/1-Two-Sum/step2_sort.py new file mode 100644 index 0000000..3b0a48f --- /dev/null +++ b/1-Two-Sum/step2_sort.py @@ -0,0 +1,14 @@ +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + num_and_index = sorted([(num, index) for index, num in enumerate(nums)]) + front = 0 + rear = len(nums) - 1 + while front < rear: + sum_ = num_and_index[front][0] + num_and_index[rear][0] + if sum_ < target: + front += 1 + continue + if target < sum_: + rear -= 1 + continue + return [num_and_index[front][1], num_and_index[rear][1]] From c13d57a3684abca304a5593d276a0dd0d074b29e Mon Sep 17 00:00:00 2001 From: mayota Date: Tue, 16 Jun 2026 21:56:44 +0900 Subject: [PATCH 4/5] step3 --- 1-Two-Sum/note.md | 2 ++ 1-Two-Sum/step3.py | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 1-Two-Sum/step3.py diff --git a/1-Two-Sum/note.md b/1-Two-Sum/note.md index 2146ac4..b47eb87 100644 --- a/1-Two-Sum/note.md +++ b/1-Two-Sum/note.md @@ -48,3 +48,5 @@ - 指滑らせて棒の重心探すやつみたい ## step3(10分以内にさっとかける * 3回) + +step2で書いたソート版は、front < rear を確かめてないと答えが存在しなかった時にすれ違ってエラーで落ちる diff --git a/1-Two-Sum/step3.py b/1-Two-Sum/step3.py new file mode 100644 index 0000000..ce9f2a8 --- /dev/null +++ b/1-Two-Sum/step3.py @@ -0,0 +1,9 @@ +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + num_to_index = {} + for index, num in enumerate(nums): + pair_index = num_to_index.get(target - num) + if pair_index is None: + num_to_index[num] = index + continue + return [index, pair_index] From 65937d2ba9555797d5927eab96a67e1e16f9db64 Mon Sep 17 00:00:00 2001 From: mayota Date: Tue, 16 Jun 2026 21:58:59 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-Two-Sum/note.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/1-Two-Sum/note.md b/1-Two-Sum/note.md index b47eb87..0c69aad 100644 --- a/1-Two-Sum/note.md +++ b/1-Two-Sum/note.md @@ -46,6 +46,9 @@ - いろんな例を考えてるがならなそう - 証明: `num[answer1] + num[answer2] (answer1 < answer2) = target` になるとき、`i < answer1 < answer2 < j` に対しての `num[i] + num[j]` は target より大きいか小さいかわからないけど、`num[i] + num[answer2] < target < num[answer1] + num[j]` なのでどちらかが answer に到達した時点であとはもう片方が答えに近づくだけであり行きすぎることはない。 - 指滑らせて棒の重心探すやつみたい +- 他にも読んだコード + - + - ## step3(10分以内にさっとかける * 3回)