18. 四数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,__b,cd ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。 注意: 答案中不可以包含重复的四元组。 示例: 给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]

解题思路

核心思想

  1. 将原始数组排序。
  2. 双层循环遍历数组,固定位置 18. 四数之和 - 图1 ,游标 18. 四数之和 - 图218. 四数之和 - 图3 根据当前四数之和来进行向右或向左移动。

想到和 【15. 三数之和】类似,只是相比其要多一层循环,所以直接在【三数之和】的基础上修改代码。
还需要注意的是

  • 这里的四数之和比较的值是给定的参数 18. 四数之和 - 图4,而不简单的是 0
  • 18. 四数之和 - 图5 可能是正数或是负数,提前判断 18. 四数之和 - 图6 而直接返回结果,可能会导致漏掉一些解
    1. class Solution {
    2. public:
    3. vector<vector<int>> fourSum(vector<int>& nums, int target) {
    4. vector<vector<int>> res;
    5. int n = nums.size();
    6. if( n < 4 )
    7. return res;
    8. //排序nums
    9. sort(nums.begin(),nums.end());
    10. //遍历数组
    11. for(int i=0;i<n;i++) {
    12. //跳过相同的值
    13. if(i>0 && nums[i] == nums[i-1])
    14. continue;
    15. for(int j=i+1;j<n;j++) {
    16. //跳过相同的值
    17. if(j>i+1 && nums[j] == nums[j-1])
    18. continue;
    19. //游标left和right
    20. int left = j+1;
    21. int right = n-1;
    22. while(left < right) {
    23. int sum = nums[i] + nums[j] + nums[left] + nums[right];
    24. //得到一个解
    25. if( sum == target){
    26. vector<int> temp;
    27. temp.push_back(nums[i]);
    28. temp.push_back(nums[j]);
    29. temp.push_back(nums[left]);
    30. temp.push_back(nums[right]);
    31. res.push_back(temp);
    32. //跳过相同的值
    33. while(left < right && nums[left] == nums[left+1]){ left++;}
    34. while(left < right && nums[right] == nums[right-1]){right--;}
    35. left++;right--;
    36. //大于target,右游标right向左移
    37. }else if( sum > target ){
    38. right--;
    39. //小于target,左游标left向右移
    40. }else{
    41. left++;
    42. }
    43. }
    44. }
    45. }
    46. return res;
    47. }
    48. };