优选算法:四数目标和(双指针)

优选算法:四数目标和(双指针)_第1张图片

        题目详情:. - 力扣(LeetCode) 

一. 题目解析

        题意还是比较好理解的。给一个数组,然后再数组中找到四个重复的数之和刚好等于目标和即可,再其次就是最终返回的结果不能有重复的元组。

二. 算法原理

        其实这里的算法原理与我上一篇文章(优选算法:三数目标之和(双指针)-CSDN博客)大致相似,只是这里多了一个大循环而已。 大家可以先去看一看这篇文章,以便于更好的理解下面思路。

        首先,我们可以先固定一个数,只考虑三个数动态的情况,那其实这里就是求三个数的目标和的问题。而三个数的目标和的方法,其实也就是先固定一个数然后去求动态的两个数。那求两个数就非常好求了。

        那么下面讲解具体步骤:

        一. 先用sort函数对整个数组进行排序。然后定义出四个指针:fix1 fix2 left right。 fix1作为考虑三个数目标和时所固定的数:fix1=0;  fix2作为考虑两个目标和时所固定的数:fix2=fix1+1;  left作为考虑动态两个数时的最左边,同理right作为最右边。 由于题目要求返回多个数组,所以我们定义一个二维数组ret作为返回结果

优选算法:四数目标和(双指针)_第2张图片

        二. 首先一个fix1的for循环 fix1

        三. 我们找到了所有元素还没有完这道题还没有完。我们还有极为重要的一步:去重。

        1.当我们找到符合的四个值时,我们压入元素,然后left 和 right会移动到下一位置,但是如果left和right移动了以后仍是重复的元素的话,我们就需要跳过重复元素才行优选算法:四数目标和(双指针)_第3张图片

        跳过重复元素,我们可以借助while循环实现: while(left

        2.同理,当left与right相遇时跳出循环,fix2++时。fix2也可能会遇到重复的元素,一旦fix2重复了那么就意味着,这一轮固定的元素与上轮的元素相同,那么就以为着这一轮找到的符合条件的四个元素就一定是重复的。所以fix2也需要跳过循环。优选算法:四数目标和(双指针)_第4张图片

        同样的我们也可以借助while循环跳过重复元素:while (fix2 < =nums.zie()-3 && nums[fix2] == nums[fix2-1]) fix2++;

        3.同理fix1也会出现重复的情况,也需要跳过重复元素: while (fix1 && fix1 <= size - 3 && nums[fix1] == nums[fix1 - 1])  fix1++;

        最后对于这道题,有一个比较坑的点就是使用int类型计算四个元素的和时会溢出优选算法:四数目标和(双指针)_第5张图片

        所以我们要用一下 longlong 才不会溢出,这里要注意一下 

三. 代码实现

class Solution {
public:
    vector> ret;

    vector> fourSum(vector& nums, int t)
    {
        sort(nums.begin(), nums.end());
        int fix1 = 0;
        int size = nums.size() - 1;
        for (; fix1 <= size - 3;)
        {
            int fix2 = fix1 + 1;
            for (; fix2 <= size - 2;)
            {
                int left = fix2 + 1;
                int right = size;
                while (left < right)
                {
                    long long sum = (long long)nums[left] + nums[right] + nums[fix1] + nums[fix2];
                    if (sum == t)
                    {
                        ret.push_back({ nums[fix1] ,nums[fix2],nums[left],nums[right] });
                        left++;
                        right--;

                        //跳过left right重复元素
                        while (left < right && nums[left] == nums[left - 1])
                            left++;
                        while (left < right && nums[right] == nums[right + 1])
                            right--;
                    }
                    else if (sum > t)
                        right--;
                    else
                        left++;
                }
            //跳过fix2的重复元素
            fix2++;
            while (fix2 > 1 && fix2 <= size - 2 && nums[fix2] == nums[fix2 - 1])
                fix2++;
            }
            //跳过fix1的重复元素
            fix1++;
            while (fix1 && fix1 <= size - 3 && nums[fix1] == nums[fix1 - 1])
                fix1++;
        }
        return ret;
    }
};

优选算法:四数目标和(双指针)_第6张图片 

你可能感兴趣的:(优选算法,算法,笔记,c++)