From 4ff3328eb1f7ec7db6828b9419356236235eaea0 Mon Sep 17 00:00:00 2001 From: Masakuni Date: Sat, 10 Jan 2026 20:50:31 +0900 Subject: [PATCH 1/3] step1 --- problems/1.two-sum/memo.md | 27 +++++++++++++++++++++++++++ problems/1.two-sum/step1-2.py | 33 +++++++++++++++++++++++++++++++++ problems/1.two-sum/step1-3.py | 18 ++++++++++++++++++ problems/1.two-sum/step1.py | 16 ++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 problems/1.two-sum/memo.md create mode 100644 problems/1.two-sum/step1-2.py create mode 100644 problems/1.two-sum/step1-3.py create mode 100644 problems/1.two-sum/step1.py diff --git a/problems/1.two-sum/memo.md b/problems/1.two-sum/memo.md new file mode 100644 index 0000000..403b32d --- /dev/null +++ b/problems/1.two-sum/memo.md @@ -0,0 +1,27 @@ +## step1 +- (step1)二重ループにするとO(n2)で解けそう + - 全部回すと10^8/2くらいでpythonでもギリギリいけそう +- (step1-2)sortしてあったら二分探索で片方を見つけた時に二分探索で答えを探せそう + - ソートでO(NlogN)、N回二分探索でO(NlogN) + - indexをつけて、sortするには下記のようにするみたい + - 実装したが、indexずらすのとかで結構ごちゃごちゃしたコードになった +```py +indexed_data = list(enumerate(data)) + +# 値(タプルの2番目の要素)でソート +# 値が同じ場合は元のインデックス(タプルの1番目の要素)で安定ソートされる +sorted_indexed_data = sorted(indexed_data, key=lambda item: item[1]) +``` + + +- (step1-3)いやそもそも1回のfor文でこれまで辿ってきた履歴に求める数があるかどうかで答えが出せるはず + - 出てきた数をkey,indexをvalueにしておく、答えは1つに求まるのでindexの上書きは気にしなくていい + +leetcode上での数値は下記 +O(n2)の解法:1716ms +O(nlogn)の解法:111ms +O(n)の解法:0ms +## step2 + +## step3 + diff --git a/problems/1.two-sum/step1-2.py b/problems/1.two-sum/step1-2.py new file mode 100644 index 0000000..a703f74 --- /dev/null +++ b/problems/1.two-sum/step1-2.py @@ -0,0 +1,33 @@ +# +# @lc app=leetcode id=1 lang=python3 +# +# [1] Two Sum +# +import bisect + + +# @lc code=start +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + index_nums = list(enumerate(nums)) + sorted_index_nums = sorted(index_nums, key=lambda item: item[1]) + + for index, (root_index, num) in enumerate(sorted_index_nums): + search_num = target - num + candidate_index = ( + bisect.bisect_left( + sorted_index_nums[index + 1 :], search_num, key=lambda x: x[1] + ) + + index + + 1 + ) + if candidate_index >= len(sorted_index_nums): + continue + if sorted_index_nums[candidate_index][1] == search_num: + return ( + min([root_index, sorted_index_nums[candidate_index][0]]), + max([root_index, sorted_index_nums[candidate_index][0]]), + ) + + +# @lc code=end diff --git a/problems/1.two-sum/step1-3.py b/problems/1.two-sum/step1-3.py new file mode 100644 index 0000000..d9a26f3 --- /dev/null +++ b/problems/1.two-sum/step1-3.py @@ -0,0 +1,18 @@ +# +# @lc app=leetcode id=1 lang=python3 +# +# [1] Two Sum +# +# @lc code=start +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + checked_num_index = {} + + for index, num in enumerate(nums): + seached_num = target - num + if seached_num in checked_num_index: + return [checked_num_index[seached_num], index] + checked_num_index[num] = index + + +# @lc code=end diff --git a/problems/1.two-sum/step1.py b/problems/1.two-sum/step1.py new file mode 100644 index 0000000..177dd88 --- /dev/null +++ b/problems/1.two-sum/step1.py @@ -0,0 +1,16 @@ +# +# @lc app=leetcode id=1 lang=python3 +# +# [1] Two Sum +# + +# @lc code=start +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + for i in range(len(nums)): + for j in range(i + 1, len(nums)): + if nums[i] + nums[j] == target: + return [i, j] + + +# @lc code=end From 5e690441983ffe22bf376f8ec2b9e0ea5aeee2e2 Mon Sep 17 00:00:00 2001 From: Masakuni Date: Sat, 10 Jan 2026 21:55:18 +0900 Subject: [PATCH 2/3] step2 --- problems/1.two-sum/memo.md | 25 +++++++++++++++++++++++++ problems/1.two-sum/step2.py | 21 +++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 problems/1.two-sum/step2.py diff --git a/problems/1.two-sum/memo.md b/problems/1.two-sum/memo.md index 403b32d..52f1d13 100644 --- a/problems/1.two-sum/memo.md +++ b/problems/1.two-sum/memo.md @@ -22,6 +22,31 @@ O(n2)の解法:1716ms O(nlogn)の解法:111ms O(n)の解法:0ms ## step2 +- 問題としては答えがあることを保証しているが、答えがない場合はNoneを返すのがいいと思う +- また答えが複数あるケースでバグるようなことがないかは気にしておきたい + - 今回は大丈夫 +- 他の人のコードをみる +- https://github.com/mamo3gr/arai60/pull/11/files + - 配列の長さが0,1の時エラーを投げてるのはいいと思う + - エラーを返すかNoneを返すか毎回悩む + - `complement`は全く選択肢に出てこなかったので調べた + +``` +数学・アルゴリズムの世界では昔から: +a + b = target +b は a の complement +という言い方をします。 +``` + +- https://github.com/MasukagamiHinata/Arai60/pull/9/files + - `メソッドの出力のtype hintがList[int]となっているので、ここをOptional[List[int]]]としてNoneも返りうることを明示しておくか、return [-1, -1]など型のあった返り値にすると良い気がします。` + - 答えがない時に、[-1,-1]も考えたが-1だと後続の処理で配列の末尾を指して処理が進み、意図しないところでバグが健在化する可能性があるので、Noneかエラーにした方が親切だと自分は判断した + - `あとは設計思想の問題ですが、複数解に対応するということは利用者は解が何個あるか知らないことが想定され、その中には解が含まれないケースも含まれると思います。解が何個あるか知るために使ったところ0個で、エラーが出ると利用者としては少々仰々しくて使いにくいという気持ちになりそうだと思いました。(解が最低1個あることを先に調べないとエラーが出てしまうため。)自分なら、解が0個のとき、つまりresults = []のときでもそのままreturnするように書くと思います。` + - 確かに、複数の解を想定している場合は解がない場合にエラーはやめてほしいと思った。このような想定されるケースへの拡張性を考慮に入れて、エラーを投げるかNoneを返すか迷った際にNoneを選択できるといいと思った。 + - dictの命名でkey_to_valueはとても良いので毎回候補の中に入れるようにしたい +- checked_は今回のような短いコードの場合はすぐわかるので書かなくて良さそう +- step1-2でミスでtupleで返してもLeetCode的にOKになっていた + - 内部的にどういう感じでOK/NGの判定をしているのかイメージしたところfor文で判定してたりするとこのような現象が起こりそうだと思った ## step3 diff --git a/problems/1.two-sum/step2.py b/problems/1.two-sum/step2.py new file mode 100644 index 0000000..0c08fd9 --- /dev/null +++ b/problems/1.two-sum/step2.py @@ -0,0 +1,21 @@ +# +# @lc app=leetcode id=1 lang=python3 +# +# [1] Two Sum +# + +# @lc code=start +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + num_to_index = {} + + for index, num in enumerate(nums): + complement = target - num + if complement in num_to_index: + return [num_to_index[complement], index] + num_to_index[num] = index + + return + + +# @lc code=end From 58e6e7381a9f42b4daadf530895a454fafb35119 Mon Sep 17 00:00:00 2001 From: Masakuni Date: Sat, 10 Jan 2026 21:56:43 +0900 Subject: [PATCH 3/3] step3 --- problems/1.two-sum/memo.md | 1 + problems/1.two-sum/step3.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 problems/1.two-sum/step3.py diff --git a/problems/1.two-sum/memo.md b/problems/1.two-sum/memo.md index 52f1d13..21bb7d5 100644 --- a/problems/1.two-sum/memo.md +++ b/problems/1.two-sum/memo.md @@ -49,4 +49,5 @@ b は a の complement - 内部的にどういう感じでOK/NGの判定をしているのかイメージしたところfor文で判定してたりするとこのような現象が起こりそうだと思った ## step3 +- 短かったのと頭の中で整理ができていたのとで難なく書けた diff --git a/problems/1.two-sum/step3.py b/problems/1.two-sum/step3.py new file mode 100644 index 0000000..c45ab46 --- /dev/null +++ b/problems/1.two-sum/step3.py @@ -0,0 +1,21 @@ +# +# @lc app=leetcode id=1 lang=python3 +# +# [1] Two Sum +# + +# @lc code=start +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + num_to_index = {} + + for index, num in enumerate(nums): + complemnt = target - num + if complemnt in num_to_index: + return [num_to_index[complemnt], index] + num_to_index[num] = index + + return + + +# @lc code=end