leetcode必回:四数之和

54 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

引言

算法的技能对于程序员是百益而无一害,作为程序员无论是前端还是后端算法技能对于我们都是十分十分的重要,我将陆续整理并讲解前端程序员必须掌握的经典算法。

题目描述

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

 

示例 1:

输入: nums = [1,0,-1,0,-2,2], target = 0
输出: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

输入: nums = [2,2,2,2,2], target = 8
输出: [[2,2,2,2]]

 

提示:

  • 1 <= nums.length <= 200
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109

分析

四数之和与前面三数之和的思路几乎是一样的,嗝。(刚好前些天才写了三数之和的题解) 如果前面的三数之和会做了的话,这里其实就是在前面的基础上多添加一个遍历的指针而已。 会做三数之和的可以不用看下面的了。。

使用四个指针(a<b<c<d)。固定最小的a和b在左边,c=b+1,d=_size-1 移动两个指针包夹求解。 保存使得nums[a]+nums[b]+nums[c]+nums[d]==target的解。偏大时d左移,偏小时c右移。c和d相 遇时,表示以当前的a和b为最小值的解已经全部求得。b++,进入下一轮循环b循环,当b循环结束后。 a++,进入下一轮a循环。 即(a在最外层循环,里面嵌套b循环,再嵌套双指针c,d包夹求解)。

解答

        class Solution{ public: vector<vector<int>> fourSum(vector<int>& nums, int target) { sort(nums.begin(),nums.end()); vector<vector<int> > res; if(nums.size()<4) return res; int a,b,c,d,_size=nums.size(); for(a=0;a<=_size-4;a++){ if(a>0&&nums[a]==nums[a-1]) continue; //确保nums[a] 改变了 for(b=a+1;b<=_size-3;b++){ if(b>a+1&&nums[b]==nums[b-1])continue; //确保nums[b] 改变了 c=b+1,d=_size-1; while(c<d){ if(nums[a]+nums[b]-target<-(nums[c]+nums[d]))//原写法num[a]+num[b]+num[c]+num[d]<target为了防止溢出,见下面的补充修改 c++; else if(nums[a]+nums[b]-target>-(nums[c]+nums[d]))//同上 d--; else{ res.push_back({nums[a],nums[b],nums[c],nums[d]}); while(c<d&&nums[c+1]==nums[c]) //确保nums[c] 改变了 c++; while(c<d&&nums[d-1]==nums[d]) //确保nums[d] 改变了 d--; c++; d--; } } } } return res; } }; 

总结

上面的算法思路让我学到了许多知识啊