[LeetCode] 15. 3つの数値の合計3Sum(C ++)


件名のソース:https//leetcode-cn.com/problems/3sum/

タイトル説明

n個の整数を含む配列numsが与えられた場合、a + b + c = 0となるように、numsに3つの要素a、b、cがあるかどうかを判別します。そして、あなたが見つけるのはゼロであり、重複するトリプルはありません

注:回答に繰り返しトリプルを含めることはできません。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:

输入:nums = []
输出:[]
示例 3:

输入:nums = [0]
输出:[]
 

提示:

0 <= nums.length <= 3000
-105 <= nums[i] <= 105

一般的なアイデア

  • 配列を指定して、配列を一緒に0に等しくなるように設定すべての3つの数値を返し、されて繰り返されていない配列は、その下の状況を検討することができ、問題のために繰り返されていない、配列満足する条件を見つけるための簡単なソートされた配列を知るために、回避の重複にしますこれは、結果セット内のすべてのサブセットが特定の単調性に従うようにするためです。
  • 暴力的なサイクルO(n ^ 3)、配列の長さ∈[0,3000]では、タイムアウトする可能性があります
  • 1番目と2番目に異なる要素を選択して、重複する要素の列挙がないようにします。2番目<3番目は、2番目と3番目が交換および繰り返されないようにします。

[− 1、1、0] [1、− 1、0] [0、− 1、1] [-1,1,0] \ quad [1、-1,0] \ quad [0、-1 1] [ 1 1 0 ][ 1 1 0 ][ 0 1 1 ]

ソート+ダブルポインタ

  • 上記の考え方では、配列を小さいものから大きいものに並べ替えた後、次の式でaを決定すると、添え字はbとともに小さいものから大きいものへと徐々に移動します。bが徐々に増加すると、条件を満たすcは徐々に減少します。つまり、当初考えられていたようにbとcをトラバースするのに必要な時間計算量O(n ^ 2)はO(n)に減少します(bは左から右に最大n回トラバースされ、cは右から最大でトラバースされます)左へ。n回、nは配列の長さ)、スライディングウィンドウ問題の分析と同様に
    a + b + c = 0 a + b '+ c' = 0(ifb'≥b、Thenc'≤c )\ begin {collected} a + b + c = 0 \\ a + b ^ {'} + c ^ {'} = 0 \ quad(if \ quad {b ^ {'}}≥b、Then \ quad { c {'}≤c})\ end {gathered}a+b+c=0a+b+c=0私はfbb T h e ncC
  • ポインタを移動するたびに同じ処理を行うように注意してください。前の要素の値と等しいかどうかを判断する必要があります。
class Solution {
    
    
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
    
    
        sort(nums.begin(), nums.end(), less<int>() );
        vector<vector<int>> ans;
        int len = nums.size();
        if(len < 3) return ans;
        for(int first = 0 ; first < len ; ++first){
    
    
            if(first > 0 && nums[first] == nums[first - 1])
                continue;
            int third = len - 1;
            for(int second = first + 1; second < len ; ++second){
    
    
                if(second > first + 1 && nums[second] == nums[second - 1])
                    continue;
                int target = -(nums[second] + nums[first]);
                while(second < third && nums[third] > target)
                    --third;
                if(second == third)
                    break;
                if(nums[third] == target)
                    ans.push_back({
    
    nums[first], nums[second], nums[third]});
            }
        }
        return ans;
    }
};

複雑さの分析

  • 時間計算量:O(n ^ 2)。nは配列の長さ、aはn回トラバースされ、bとcのトラバーサルの時間計算量はO(n)です。
  • スペースの複雑さ:O(logn)。nは配列の長さであり、クイックソートで使用される平均スペース複雑度はO(logn)です。最悪の場合、n-1回の再帰呼び出しが必要であり、スペース複雑度はO(n)です。

おすすめ

転載: blog.csdn.net/lr_shadow/article/details/114021349