• 【算法——双指针】LeetCode 18 四数之和


    题目描述:

    解题思路:双指针

            四数之和与前面三数之和思路一样,排序后,枚举 nums[a]作为第一个数,枚举 nums[b]作为第二个数,那么问题变成找到另外两个数,使得这四个数的和等于 target,也是用双指针解决。

    对于 nums[a]的枚举:

    1. 设 s=nums[a]+nums[a+1]+nums[a+2]+nums[a+3]。如果 s>targets,由于数组已经排序,后面无论怎么选,选出的四个数的和不会比 s 还小,所以后面不会找到等于 target的四数之和了。所以只要 s>targets,就可以直接 break 外层循环了。
    2. 设 s=nums[a]+nums[n−3]+nums[n−2]+nums[n−1]。如果 s
    3. 如果 a>0且 nums[a]=nums[a−1],那么 nums[a]和后面数字相加的结果,必然在之前算出过,所以无需执行后续代码,直接 continue 外层循环。(可以放在循环开头判断。)

    对于 nums[b]的枚举(b从 a+1开始),也同样有类似优化:

    1. 设 s=nums[a]+nums[b]+nums[b+1]+nums[b+2]。如果 s>targets,由于数组已经排序,后面无论怎么选,选出的四个数的和不会比 s还小,所以后面不会找到等于 target的四数之和了。所以只要 s>targets,就可以直接 break。
    2. 设 s=nums[a]+nums[b]+nums[n−2]+nums[n−1]。如果 s
    3. 如果 b>a+1且 nums[b]=nums[b−1],那么 nums[b]和后面数字相加的结果,必然在之前算出过,所以无需执行后续代码,直接 continue。注意这里 b>a+1的判断是必须的,如果不判断,对于示例 2 这样的数据,会直接 continue,漏掉符合要求的答案。

    另外:对于C++语言,相加结果可能会超过32位整数范围,需要用64位整数存储四数之和。

    代码:

    1. class Solution
    2. {
    3. public:
    4. vector<vector<int>> fourSum(vector &nums, int target)
    5. {
    6. sort(nums.begin(), nums.end());
    7. vector<vector<int>> ans;
    8. int n = nums.size();
    9. for (int a = 0; a < n - 3; a++) // 枚举第一个数
    10. {
    11. long long x = nums[a]; // 使用 long long 避免溢出
    12. if (a > 0 && x == nums[a - 1])
    13. continue; // 跳过重复数字
    14. if (x + nums[a + 1] + nums[a + 2] + nums[a + 3] > target)
    15. break; // 优化一
    16. if (x + nums[n - 3] + nums[n - 2] + nums[n - 1] < target)
    17. continue; // 优化二
    18. for (int b = a + 1; b < n - 2; b++) // 枚举第二个数
    19. {
    20. long long y = nums[b];
    21. if (b > a + 1 && y == nums[b - 1])
    22. continue; // 跳过重复数字
    23. if (x + y + nums[b + 1] + nums[b + 2] > target)
    24. break; // 优化一
    25. if (x + y + nums[n - 2] + nums[n - 1] < target)
    26. continue; // 优化二
    27. int c = b + 1, d = n - 1;
    28. while (c < d) // 双指针枚举第三个数和第四个数
    29. {
    30. long long s = x + y + nums[c] + nums[d]; // 四数之和
    31. if (s > target)
    32. d--;
    33. else if (s < target)
    34. c++;
    35. else // s == target
    36. {
    37. ans.push_back({(int) x, (int) y, nums[c], nums[d]});
    38. for (c++; c < d && nums[c] == nums[c - 1]; c++); // 跳过重复数字
    39. for (d--; d > c && nums[d] == nums[d + 1]; d--); // 跳过重复数字
    40. }
    41. }
    42. }
    43. }
    44. return ans;
    45. }
    46. };

    结果:

  • 相关阅读:
    基于5G工业CPE打造智慧煤矿无人巡检监测应用
    基于Taro + React 实现微信小程序半圆滑块组件、半圆进度条、弧形进度条、半圆滑行轨道(附源码)
    阿里云ECS和轻量服务器有什么区别?
    C++智能指针
    ffmpeg视频编解码 demo初探(一)(包含下载指定windows版本ffmpeg)分离视频文件中的视频流每一帧YUV图片
    Android 内存泄漏分析思路和案例剖析
    【微信小程序】数据绑定
    [LiteratureReview]A Collaborative Visual SLAM Framework for Service Robots
    SSM+好乐买超市管理系统 毕业设计-附源码111743
    Mac版2024 CleanMyMac X 4.14.6 核心功能详解
  • 原文地址:https://blog.csdn.net/weixin_44906102/article/details/133470952