問題:配列Aであるn個の整数を含む整数xを入力し、A [i] + A [j] = xを満たすiとjを見つけ、そのような要素の合計がない場合は-1と-1を返す。
私の分析は次のとおりです。
この質問に注意する必要があります。配列に重複した要素がある可能性があり、条件を満たす複数のソリューションセットがあります。
たとえば、配列A [1,3,2,2]とx = 4が与えられると、条件を満たす解は次のようになります。
(0、1):1 + 3 = 4および(2、3):2 + 2 = 4。
ソリューション1:暴力的なソリューション
各要素A [i]を反復処理し、xA [i]に等しい値を持つターゲット要素があるかどうかを確認します。
テストケースと実行結果:
解決策2:最初にソートする+ポインター+ HashMap
与えられた配列を最初にソートしてから、2つのポインター(i、j)を作成します。1つは開始ノードからi ++の後ろまで、もう1つはテールノードからj--の前までです。
3つのケースがあります。
int i = 0, j = A.length;
while(i < j) {
if(A[i]+A[j] < x)
i++;
else if(A[i]+A[j] > x)
j--;
else
System.out.print("find out!");
}
ただし、配列のインデックスは並べ替えのために混乱します。そのため、元の配列要素とそのインデックスをソート前にハッシュテーブルに格納できます。ポインタで要素が見つかった後、元のインデックスをハッシュテーブルから取り出すことができます。
時間の複雑さの分析、アクセスハッシュテーブルはO(n)、順序はO(nlog(n))、ポインター検索はO(n)です。これは約O(2n + nlog(n))です。
解決策3:ハッシュテーブル
hm:要素とインデックスを<key、value>の形式でハッシュテーブルhmに配列に格納します(ハッシュテーブルの2回の走査からハッシュテーブルの1回の走査に段階的に最適化されます)。
(1)最初の考えは、ハッシュテーブルを2回トラバースすることです:f(n)= 2n
*初回は、配列の各要素とそのインデックスをキーと値のペアの形式でハッシュテーブルに格納します
* 2回目は、各要素A [i]を順番にトラバースして、xA [i]がハッシュテーブルのキーであるかどうかを確認し、存在する場合、キー値はインデックスです。
しかし、この状況の問題は、トラバーサルが(1、2)や(2、1)などの解を2回出力するためです。
(2)上記の2つのトラバーサルハッシュテーブルは、1つのトラバーサルf(n)= nに変更できます。つまり、ハッシュテーブルに配列要素a [i]を追加する前に、まずxa [i]が現在のハッシュにあるかどうかを判断します。テーブルで、次に追加します。これにより、重複する出力ソリューションがなくなります。
*ハッシュテーブルはスペースを時間と交換し、スペースの複雑度はO(n)、時間の複雑度はO(n)
*短所:ハッシュテーブルでは重複するキーを使用できないため、このアルゴリズムでは配列内の同じ要素の状況を解決できません。
注意:いくつかの問題は、そのようなソリューションのペアが1つしかないことを示します。この状況は比較的単純です。繰り返される要素を考慮する必要はなく、ソリューションが見つかればプログラムを終了できます。