記事ディレクトリ
トピック分析
まず、このトピックの考え方を説明しましょう
- この質問の意味は非常に単純であることがわかります。この配列を検索することです
nums
。2 つの数値の合計が見つかった場合はtarget
、結果セットを形成して返します。
アルゴリズム思考分析
次に、この質問のアイデアを分析しましょう
- ブルートフォースソリューション
- まず、最初の解決策は、誰もが考える [暴力的な解決策] です。つまり、2 層の for ループを使用して 1 つずつマッチング作業を行うことですが、この種の解決策では必ずタイムアウトが発生することが想像できます。なので、ここではあまり物語的なことはしません。
for(int i = 0;i < nums.size(); ++i)
for(int j = i + 1;j < nums.size(); ++j)
- 単調性を利用し、ダブル ポインター アルゴリズムを使用して解決します。
- 私たちのケースでは、この問題を解決するために主にダブル ポインタの解決策を使用します。1 つの
left
ポインタは左端を指し、もう 1 つのright
ポインタは右端を指します。前方および後方のトラバースを通じて、どの 2 つの数値が構造を形成できるかを見つけることができます。結果[目標]
- ここには 3 つの状況があります。1 つ目は最初の状況です。これに遭遇した場合
nums[left] + nums[right] < target
、現時点では難しい仕事を行うことができます。 - 読者はこの質問のタイトルをもう一度注意深く読むと、配列シーケンスが昇順であることがわかり、[2] と最大の [21] は両方とも前の [21 ] よりも小さいため、いくつかの数字が表示されます
target
。現時点では、複数の比較を一度に行う必要はありません。この時点ではただ実行するだけですleft++
- 次に、この状況をもう一度考えてみましょう
nums[left] + nums[right] > target
。そうすれば、この状況も矛盾していることがわかりますが、判断を下すときにさらに単純化することができます。 - 読者はまず考えてください。現時点ではどの数字を除外すべきでしょうか。それは明らかにこれ [21] ですが、なぜですか? この[21]を考えてみると、最小の[11]を超えて
target
、残りの[15]と[19]はさらに超えることになるでしょうか? - したがって、この [21] は破棄する必要があり、対応するコードは次のとおりです。
right--
- 最後のデータが見つかった場合は、これら 2 つのデータの結果セットを返すだけで済みます。
複雑さ
- 時間計算量:
最悪のケース、つまり検索を横断しているときに 2 つの左右のポインタが出会った場合、それは見つからなかったこと、つまりシーケンスを 1 回横断したことを意味し、その時間計算量は O ( n ) O(n )O ( n )
- 空間の複雑さ:
追加のスペースは割り当てられないため、スペースの複雑さはO ( 1 ) O(1)になります。○ (1)
コード
以下はコード表示です
- これとこれについて話しましょう
{nums[left], nums[right]}
。一部の友人はあまり明確ではないかもしれません。これはC++ 初期化リストの関連知識に属します。 - 一般に、LeetCode で 2 つの数値のコレクションを返す場合、新しいベクトル コレクションを作成する必要はありませんが、暗黙的な型変換を通じてベクトル コレクションを形成して返します。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
int sum = 0;
while(left < right)
{
sum = 0;
sum = nums[left] + nums[right];
if(sum < target){
left++;
}else if(sum > target){
right--;
}else{
return {
nums[left], nums[right]};
}
}
return {
-1, -1};
}
};