[Algorithm - Double Pointer] LeetCode 15 Sum of Three Numbers

Topic description:

Problem-solving ideas: double pointers

        First, sort the array in ascending order. Then, we can solve it using the following steps:

        Initialize an empty result set result to store the found triples whose sum is 0.

        Traverse the entire array until the third to last element (because what we need is a triple). For each element, use two pointers (a left pointer L and a right pointer R) to find all triples whose sum is 0.

  1. Initialize the left pointer L and set it to the next element of the current element; initialize the right pointer R and set it to the last element of the array.
  2. If the current element is the same as the previous element (if it exists), we simply skip the current element, since we need to avoid duplicate solutions, and proceed to the next element.
  3. For the current element nums[i], check the sum of nums[i] + nums[L] + nums[R]:
    1. If the sum is less than 0, increment the left pointer L;
    2. If the sum is greater than 0, decrease the right pointer R;
    3. If the sum is equal to 0, add this triplet [nums[i], nums[L], nums[R]] to the result set result, and move the left pointer L and the right pointer R at the same time until it encounters the same element as the current element Unequal elements (to avoid duplicate solutions).
    4. Finally, the result set result is returned.

        The time complexity of this method is O(n^2), because the entire array needs to be traversed, and each element may need to be traversed once.

        When writing your implementation, make sure to move to unequal elements when handling left and right pointers to avoid duplicate solutions.

Code:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) 
    {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size() - 1; i++)
        {  
            if(nums[i] > 0)
                return result;    //数组递增
            if(i > 0 && nums[i] == nums[i - 1])
            {
                continue;    //对a去重,如果i=1与i=0对应的元素相同,那么跳过下面的所有操作,left,right不需要考虑了。
            }
            //a满足去重,再来确定left,right以及去除问题。
            int left = i + 1;
            int right = nums.size() - 1;
            while(left < right)
            {
                //当left==right时,b,c为同一个数,不符合要求。
                if(nums[i] + nums[left] + nums[right] < 0) 
                    left++;
                else if(nums[i] + nums[left] + nums[right] > 0) 
                    right--;
                else
                {
                    vector<int> v = {nums[i], nums[left], nums[right]};
                    result.push_back(v);
                    //下面考虑left,right的移动情况。
                    while (right > left && nums[right] == nums[right - 1])
                        right--;
                    //再次加上right>left的原因是:进入上面的循环时是复合right>left的,但是
                    //可能在循环中left与right发生改变。
                    while (right > left && nums[left] == nums[left + 1]) 
                        left++;
                    /*
                    为什么是while?举个例子
                    [0 -1 -1 -1 -1 -1 1 1 1 1 1 1 ]
                    因为当i= 0时,left与right就已经收集到了正确的结果
                    此时应该持续地移动left 与 right,一次是不够。
                    */
                   
                    left++;
                    right--;

                    //是为了在找到一个有效的三元组后,将left和right分别向前和向后移动一位,以便在后续的循环中继续寻找其他可能的三元组。这样可以确保所有的有效三元组都被找到。
                }
            }
        }           
    return result;   
    }
};

result:

Guess you like

Origin blog.csdn.net/weixin_44906102/article/details/133418632