当初の公開:
2つの数字の合計(2つの合計)は、典型的な面接の質問であり、LeetCodeの最初の質問でもあります。説明を簡単にするために、元の質問を簡略化します。
配列a [N]が与えられた場合、2つの要素の合計がkであるかどうかを判別します。
アルゴリズム1:2層ループ
各a [i]について、配列a [N]を再度トラバースし、a [i] + a [j]の値がkに等しいかどうかを判断します。ここで、j> iです。これは最も直感的で暴力的です。解決。時間計算量はO(N * N)であり、空間計算量はO(1)です。
このように答えると、正解ですが、面接は間違いなく失敗します。
分析し、各a [i]について、妥当なa [j]を見つけるプロセスで、線形検索が使用されます。明らかにヒットです。ハッシュ検索を使用してみませんか?
アルゴリズム2:単層ループ+ハッシュテーブル
アルゴリズム1を改善しましょう:
各a [i]について、配列a [N]でka [i]の値を見つける必要があり、最速のルックアップはハッシュルックアップです(時間計算量はO(1)です)。したがって、全体的な時間計算量は次数はO(N)です。ハッシュテーブルが使用されるため、空間計算量もO(N)になります。
時間と空間のトレードオフのこの慣行は、しばしば使用されます。この解決策は、書面による面接の要件を満たすことです。
コードは次のように実装されます(結果は、条件を満たす値の添え字です)。
func twoSum(nums []int, target int) []int {
var result []int
m := make(map[int]int)
lenN := len(nums)
for i, v := range nums {
m[v] = i
}
for i := 0; i < lenN; i++ {
if j, ok := m[target - nums[i]]; ok && i < j {
result = append(result, i, j)
}
}
return result
}
テスト結果は次のとおりです。
上記のコードは、単層ループですが、ループは2回使用されます。実際、引き続き最適化して1つのループに統合することができます。この最適化は難しくないので、繰り返しません。
アルゴリズム3:高速ソート+ダブルポインター
空間の複雑さをO(logN)にする必要があり、時間の複雑さが可能な限り低い場合はどうなりますか?
次のように、クイックソートとダブルポインタの方法を検討できます。
ステップ1:クイックソート
ステップ2:次のようにダブルポインタークランプ力:
ループ条件はwhile(左<高)です:
a [left] + a [right]がたまたまkに等しい場合、合計がkである2つの数が見つかります。
a [left] + a [right]がkより小さい場合、left ++の場合は、大きい数値で試してください。
a [left] + a [right]がkより大きい場合は、右-、小さい数で試してください。
このソリューションも非常に巧妙です。全体的な時間計算量はO(N * logN)であり、空間計算量はO(logN)であり、書面によるインタビューの要件も満たすことができます。
2つの数の合計については上で説明しましたが、3つの数の合計の問題にどのように対処するのでしょうか。明らかに、3つの方法もあります。
アルゴリズム1:3層ループ(この暴力的な解決策は、書面によるインタビューに合格できません)
時間計算量はO(N * N * N)であり、空間計算量はO(1)です。
アルゴリズム2:ダブルループ+ハッシュテーブル
時間計算量はO(N * N)であり、空間計算量はO(N)です。
アルゴリズム3:高速ソート+ダブルポインター
時間計算量はO(N * N)であり、空間計算量はO(logN)です。
アリババ、テンセント、今日頭条のインタビュアーは、リートコードが大好きです。お気に入りのオファーがあればいいのにと思います。