欢迎来到 CILMY23的博客
🏆本篇主题为:双指针算法之18. 四数之和(力扣)
🏆个人主页:CILMY23-CSDN博客
🏆系列专栏:Python | C++ | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法专题 | 代码训练营
🏆感谢观看,支持的可以给个一键三连,点赞收藏+评论。如果你觉得有帮助,还可以点点关注
题目:
18. 四数之和 - 力扣(LeetCode)
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

题目解析:
这道题在有二数之和和三数之和的前提上,理解起来是比较快的。
1.给了一个目标值target
2.不重复的四元组
[nums[a], nums[b], nums[c], nums[d]]3.找出不重复的四元组
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
算法原理:
个人感觉:感觉四数之和比三数之和难多了
首先根据前两题的经验,我们很快就能推算出,这是一题双指针算法的题目,大致思路还是跟之前一样,双指针求和,然后去重。
所以我们能写出如下代码:
class Solution
{
public:
    static vector<vector<int>> fourSum(vector<int>& nums, int target)
    {
        vector<vector<int>> ret;
        //排序数组
        sort(nums.begin(), nums.end());
        int k = nums.size() - 1; //固定k
        for (k = nums.size() - 1; k > 2;)
        {
            for (int j = k - 1; j > 1;)
            {
                int sum1 = nums[k] + nums[j];
                int left = 0;
                int right = j - 1;
                while (left < right)
                {
                    int sum2 = nums[left] + nums[right];
                    if (sum2 + sum1 == target)
                    {
                        ret.push_back({ nums[left],nums[right],nums[j],nums[k] });
                        left++;
                        right--;
                    }
                    else if (sum2 > (target - sum1))
                    {
                        right--;
                    }
                    else if (sum2 < (target - sum1))
                    {
                        left++;
                    }
                }
            }
        }
        return ret;
    }
}; 
第一个,我用一个sum1进行存储两个固定的数的值,sum2存储两个指针的值。
接下来是重点,我的两个指针和两个固定的值相加要和target一样,所以两个指针的值要和target-sum1进行比较。
这个很重要,我当时和sum1比较发现是行不通的,没把target搞进去,因为我们最终是要和target目标值进行比较的。
接下来是去重,首先,是两个指针的去重,这个相对容易一些。
while (left < right && nums[left - 1] == nums[left])
{
    left++;
}
while (left < right && nums[right + 1] == nums[right])
{
    right--;
} 
其次是两个固定数的去重,由于我这次去重将放在循环的末尾了,所以会有一些变化。
for (k = nums.size() - 1; k > 2;)
{
    for (int j = k - 1; j > 1;)
    {
        //......
        while (left < right)
        {
            //......
        }
        j--;
        //j去重
        while (j > 1 && nums[j + 1] == nums[j])
        {
            j--;
        }
    }
    k--;
    //k去重
    while (k > 2 && nums[k + 1] == nums[k])
    {
        k--;
    }
} 
去重前,先保证固定的数会走到下一个位置,然后再进行比较。
然后还有一个坑的点是这题

会出现一个数值过大的问题,所以要把sum1和sum2都改成long long即可。
代码编写:
class Solution
{
public:
    static vector<vector<int>> fourSum(vector<int>& nums, int target)
    {
        vector<vector<int>> ret;
        //排序数组
        sort(nums.begin(), nums.end());
        int k = nums.size() - 1; //固定k
        for (k = nums.size() - 1; k > 2;)
        {
            for (int j = k - 1; j > 1;)
            {
                long long int sum1 = nums[k] + nums[j];
                int left = 0;
                int right = j - 1;
                while (left < right)
                {
                    long long int sum2 = nums[left] + nums[right];
                    if (sum2 + sum1 == target )
                    {
                        ret.push_back({ nums[left],nums[right],nums[j],nums[k] });
                        left++;
                        right--;
                        while (left < right && nums[left - 1] == nums[left])
                        {
                            left++;
                        }
                        while (left < right && nums[right + 1] == nums[right])
                        {
                            right--;
                        }
                    }
                    else if (sum2 > (target-sum1))
                    {
                        right--;
                    }
                    else if (sum2 < (target-sum1))
                    {
                        left++;
                    }
                }
                j--;
                //j去重
                while (j > 1 && nums[j + 1] == nums[j])
                {
                    j--;
                }
            }
            k--;
            //k去重
            while (k > 2 && nums[k + 1] == nums[k])
            {
                k--;
            }
        }
        return ret;
    }
}; 
🛎️感谢各位同伴的支持,本期C++算法专题就讲解到这啦,下期我们将详解滑动窗口知识点,如果你觉得写的不错的话,可以给个一键三连,点赞,收藏+评论,可以的话还希望点点关注,若有不足,欢迎各位在评论区讨论。



















