On the sum of three numbers

Keywords: less

Problem solving

subject

thinking

When I first saw this problem, I still had the solution of "sum of two numbers" in my mind. And according to the prompt of the button, it seems that after an element is fixed, the function of "sum of two numbers" can be called to complete.

Then, traverse the entire array, making target=-nums[i], so that the "sum of two numbers" can be called perfectly.
Finally, set is used to de duplicate the result array.
Unfortunately, it's over time.

I decided to use double pointer after referring to netizen's solution. The left and right pointers are i-1 and i+1
Then i=1 to i=size-2
Every time the sum of three numbers is equal to 0, an array is temporarily created, three numbers are inserted into the array, and after sorting (convenient for de duplication), the array is inserted into the result array. Then l++,r –
If the sum of three numbers is less than 0, then l + +; otherwise r –
And then Time out. There are more than one hundred zeros in the last example, none of which have been passed.

So I had to change the thinking of double pointer.
Change from l=i-1,r=i+1 to l=i+1,r=size-1
Then, especially for the last example, when sum of three numbers is sum=0, if the value of the left pointer does not change, it always jumps; so does the right pointer. Thus, in the last example, it avoids the trouble of going over again after calculating a large number of [0,0,0] results.

Generally speaking, the time complexity of the three codes is actually O(n ²). But the key is the run time for the particular samples. Sometimes the special pit made by the buckle Later, I learned that less than 30% of the submission accuracy of this question, most of which was due to the overtime

code

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        
        if(nums.size()==0)return ans;//For one of the '[]' samples
        sort(nums.begin(),nums.end());//Sorting, easy to traverse
        for(int i=0;i<nums.size()-1;i++){
            if(nums[i]>0)break;//When it is greater than 0, the value of double pointer must be greater than 0, and there must be no problem
            int l=i+1,r=nums.size()-1;//Double pointer
            while(l<r){
                //Within limits
                int sum=nums[i]+nums[l]+nums[r];
                if(sum==0){
                    vector<int> tmp;
                    tmp.push_back(nums[i]);
                    tmp.push_back(nums[l]);
                    tmp.push_back(nums[r]);
                    sort(tmp.begin(),tmp.end());//Sorting, convenient for de duplication
                    ans.push_back(tmp);
                    while (l<r && nums[l] == nums[l+1]) l++; // De duplication for the last example
                    while (l<r && nums[r] == nums[r-1]) r--; // duplicate removal

                    r--;l++;
                }
                else if(sum>0){
                    r--;
                }
                else {
                    l++;
                }
            }

        }
        set<vector<int>> st(ans.begin(),ans.end());
        ans.assign(st.begin(),st.end());//Convenient set de duplication
        return ans;
    }
    
};

Code with two pointers to the left and right (last example timed out)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        
        if(nums.size()==0)return ans;
        sort(nums.begin(),nums.end());
        for(int i=1;i<nums.size()-1;i++){
            int l=i-1,r=i+1;//Double pointer
            while(l>=0&&r<=nums.size()-1){
                //Within limits
                int sum=nums[i]+nums[l]+nums[r];
                if(sum==0){
                    vector<int> tmp;
                    tmp.push_back(nums[i]);
                    tmp.push_back(nums[l]);
                    tmp.push_back(nums[r]);
                    sort(tmp.begin(),tmp.end());
                    ans.push_back(tmp);
                    r++;l--;
                }
                else if(sum<0){
                    r++;
                }
                else {
                    l--;
                }
            }

        }
        set<vector<int>> st(ans.begin(),ans.end());
        ans.assign(st.begin(),st.end());
        return ans;
    }
    
};

Code calling "sum of two" (failed)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        for(int i=0;i<nums.size();i++){
            int t=-nums[i];
            vector<int> tmp=twoSum(nums,t,i);
            if(tmp[0]!=-99){//-99 is to screen out the solution
                tmp.push_back(nums[i]);//The two elements obtained plus the element are a solution
                sort(tmp.begin(),tmp.end());//To prepare for a remake
                ans.push_back(tmp);
            }

            
        }
        set<vector<int>> st(ans.begin(),ans.end());
        ans.assign(st.begin(),st.end());
        return ans;
    }
    vector<int> twoSum(vector<int>& n, int t,int index) {
        
        map<int,int> a;
        vector<int> b(2,-99);
        
       
        int len=n.size();
        for(int i=0;i<len;i++){
            if(i==index)continue;
            if(a.count(t-n[i])>0&&a[t-n[i]]!=i){
                //It's not clear if repeating elements are not allowed
                b[0]=n[i];
                b[1]=n[a[t-n[i]]];//a[t-n[i]] means that the subscript a of t-n[i] plays the role of inverse function
            }
            a[n[i]]=i;
        }
        
        return b;
    }//Code of sum of two numbers
};

Posted by dstantdog3 on Thu, 11 Jun 2020 22:09:23 -0700