# ハッシュを使った最適化 アルゴリズムの問題では、**線形探索をハッシュ探索に置き換えることで、時間計算量を減らす方法をよく使います**。一つの問題を通して理解を深めましょう。 !!! question 整数配列 `nums` と目標要素 `target` が与えられます。配列内から和が `target` になる二つの要素を探し、それぞれのインデックスを返してください。解はいずれか一つでかまいません。 ## 線形探索:時間を使って領域を節約する すべての組み合わせを直接調べることを考えます。下図のように二重ループを使い、各反復で二つの整数の和が `target` かどうかを判定し、そうであればインデックスを返します。 ![線形探索で二数の和を求める](replace_linear_by_hashing.assets/two_sum_brute_force.png) コードは次のとおりです。 ```src [file]{two_sum}-[class]{}-[func]{two_sum_brute_force} ``` この方法の時間計算量は $O(n^2)$、空間計算量は $O(1)$ であり、データが多いと非常に時間がかかります。 ## ハッシュ探索:領域を使って時間を節約する 配列の要素をキー、そのインデックスを値とするハッシュテーブルを使うことを考えます。配列をループで走査し、各反復で下図の手順を実行します。 1. 数値 `target - nums[i]` がハッシュテーブルにあるか調べ、あれば二つの要素のインデックスをそのまま返します。 2. `nums[i]` とインデックス `i` のペアをハッシュテーブルに追加します。 === "<1>" ![補助ハッシュテーブルで二数の和を求める](replace_linear_by_hashing.assets/two_sum_hashtable_step1.png) === "<2>" ![ハッシュテーブルによる二数の和の探索の手順 2](replace_linear_by_hashing.assets/two_sum_hashtable_step2.png) === "<3>" ![ハッシュテーブルによる二数の和の探索の手順 3](replace_linear_by_hashing.assets/two_sum_hashtable_step3.png) 実装は次のとおりで、一重のループだけで済みます。 ```src [file]{two_sum}-[class]{}-[func]{two_sum_hash_table} ``` この方法では、ハッシュ探索によって時間計算量を $O(n^2)$ から $O(n)$ に減らし、実行効率を大きく向上させています。 追加のハッシュテーブルを維持する必要があるため、空間計算量は $O(n)$ です。**それでも、時間と空間の効率のバランスがよいため、この問題の最適な解法となります**。