LeetCode0015——3 Sum——Two Pointers

这道题是双指针问题的一个变式问题,但是一开始处理起来会显得比较棘手。因为它同时涉及到了三个指针,三个指针的搜索范围有重叠,但是在最终输出结果里要求不能有重复的三元组。

题目详情如下:
在这里插入图片描述
解决这个问题的时候可以使用转化的思想,将三个指针中的一个暂时固定(fixed),剩下两个指针像传统的双指针那样工作。双指针分为对撞指针和快慢指针。这样的题目显然是在寻找正负数相抵消的情况,是对撞指针擅长处理的问题。対撞指针还需要遍历的序列有序,所以可以想见需要事先对输入数组进行排序。

为了不让结果含有重复的三元组,我们需要在遍历整个数组的同时“去重”。排序之后的数组是有序的,相同的元素都相邻的存放在一起。去重需要做的就是将相同的相邻元素只处理一次,剩下的全部跳过,这样不仅提升了搜索效率,也同时实现了去重。我在AC代码中写了以下函数来跳过相邻重复元素:

// return the next element index, jump through all the same elements in between
// Direction = 0, ->
// Direction = 1, <-
void ModifyIndex(int& Present, int Terminal, vector<int>& nums, bool Direction)
{
    
    
    if(!Direction)
        while(Present < Terminal && nums[Present] == nums[Present - 1])
            ++Present;
    else
        while(Present > Terminal && nums[Present] == nums[Present + 1])
            --Present;
}

有了这个函数,就可以开始编写核心代码了,如同上面所说,让一个指针固定(Fixed),剩下两个指针在[Fixed+1, nums.size() - 1]的范围内进行传统的对撞指针运算。当Fixed指针从[0, nums.size()-2]遍历完整一遍时,我们就得到了全部解,当然这里指针的修改全部要使用ModifyIndex来跳过重复的元素。

vector<vector<int>> threeSum(vector<int>& nums)
{
    
    
        vector<vector<int>> Result;

        // if the size of input vector less than 3, return null vector
        if(nums.size() < 3)
            return Result;

        // sort the input vector as ascending order
        sort(nums.begin(), nums.end());

        // keep a pointer fixed, let the other 2 pointers search the solution space
        int Fixed = 0;
        while(Fixed < nums.size() - 1)	// outer loop [0, nums.size() - 2]
        {
    
    
            int Left = Fixed + 1, Right = nums.size() - 1;
            while(Left < Right)			// inner loop [Fixed + 1, nums.size() - 1]
            {
    
    
                // if the sum is less than 0
                if(nums[Left] + nums[Right] + nums[Fixed] < 0)
                    ModifyIndex(++Left, Right, nums, 0);
                else if(nums[Left] + nums[Right] + nums[Fixed] > 0)
                    ModifyIndex(--Right, Left, nums, 1);
                else
                {
    
    
                    Result.push_back({
    
    nums[Left], nums[Right], nums[Fixed]});
                    ModifyIndex(++Left, Right, nums, 0);
                    ModifyIndex(--Right, Left, nums, 1);
                }

            }
            // modify the fixed pointer position
            ModifyIndex(++Fixed, nums.size() - 1, nums, 0);
        }
        return Result;
}

上述代码就完成了这样一个双指针的变式问题。

猜你喜欢

转载自blog.csdn.net/zzy980511/article/details/115250928