LeetCode 18.四数之和 C++
思路🧐:
由题意得,四个数组里面的整数相加需要得到target这个目标值,且结果不能重复 ,那么我们可以用排序+双指针 的方式进行解答,将该数组变为升序数组 ,然后固定左边两个数,从第二个固定的数下一位开始创建一个left指针,数组结尾创建一个right指针。
创建好指针后,我们将target减去固定的两个数得到变量ret,这样只需要考虑两个指针相加是否等于ret。
此时两个指针相加有三种情况:
- left+right>ret,数组升序,那么left往右所有数与right相加都大于ret,则需要right--
- left+right<ret,数组升序,那么right往左所有数与left相加都小于ret,则需要left++
- left+right==ret,表示找到了,记录四元组,left++和right--。此时需要考虑去重问题,当left++值与left一样,则继续++,当right--与right值一样,则继续--。
当left>right时,该次循环结束,找到了固定最左边两数的四元组,接下来第二个固定的数++,并判断是否一样,一样就继续++,然后继续双指针遍历,直到第二个固定的数走完数组,就该第一个固定的数开始++和去重,反复循环,直到第一个固定的数遍历完数组。
代码🔎:
c++class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { sort(nums.begin(),nums.end()); int n = nums.size(); vector<vector<int>> fourV; for(int i = 0; i < n;) //固定第一个数 { for(int j = i + 1; j < n;) //固定第二个数 { int left = j + 1; int right = nums.size() - 1; long long ret = (long long)target - nums[i] - nums[j]; //防止int溢出,所以用longlong while(left < right) { if(nums[left] + nums[right] > ret) //>ret,right-- right--; else if(nums[left] + nums[right] < ret) //<ret,left++ left++; else { fourV.push_back({nums[left],nums[right],nums[i],nums[j]}); left++; right--; while(left < right && nums[left - 1] == nums[left]) //去重 left++; while(left < right && nums[right + 1] == nums[right]) right--; } } //固定数去重,这里防止漏判,所以先++ j++; while(j < n && nums[j] == nums[j - 1]) j++; } i++; while(i < n && nums[i] == nums[i - 1]) i++; } return fourV; } };
时间复杂度:O (N ^2^LogN) 空间复杂度:O(N)