【LeetCode】18. 4Sum(C++)

地址:https://leetcode.com/problems/4sum/

题目:

Given an array nums of n integers and an integer target, are there elements a , b , c a, b, c a,b,c, and d d d in nums such that a + b + c + d = a + b + c + d = a+b+c+d=target? Find all unique quadruplets in the array which gives the sum of target.

Note:
The solution set must not contain duplicate quadruplets.

Example:
【LeetCode】18. 4Sum(C++)_第1张图片

理解:

和前面的3sum很相似。不同的就是多一层循环。

实现:

仿照着3sum写了一版,同一版代码跑出了56ms和24ms

class Solution {
public:
	vector> fourSum(vector& nums, int target) {
		vector> res;
		if (nums.empty()) return res;
		sort(nums.begin(), nums.end());
		for (int i = 0; i < nums.size(); ++i) {
			for (int j = i + 1; j < nums.size(); ++j) {
				int target2 = target - nums[i] - nums[j];
				int l = j + 1, r = nums.size() - 1;
				while (l < r) {
					int left = nums[l];
					int right = nums[r];
					if (nums[l] + nums[r] > target2) {
						while (l < r&&nums[r] == right) --r;
					}
					else if (nums[l] + nums[r] < target2) {
						while (l < r&&nums[l] == left) ++l;
					}
					else {
						res.push_back(vector{nums[i], nums[j], nums[l], nums[r]});
						while (l < r&&nums[l] == left) ++l;
						while (l < r&&nums[r] == right) --r;
					}
				}
				while (j + 1 < nums.size() && nums[j + 1] == nums[j]) ++j;
			}
			while (i + 1 < nums.size() && nums[i + 1] == nums[i]) ++i;
		}
		return res;
	}
};

看了submission里有一种8ms的方法,针对现在的方法做了一些优化,感觉挺好的。
大概思路就是

  • 如果循环到了目前的位置,最近的四个元素之和都大于target的话,后面的肯定更大,直接break;
  • 如果目前位置最前和最后的和小于target,说明后面更新的肯定更小,直接continue就可以了,避免重复计算
  • 没有的话,就说明前四个之和小于target,但是首尾之和大于target,中间可能存在等于的。再寻找

按这个思路优化,代码如下:

class Solution {
public:
	vector> fourSum(vector& nums, int target) {
		vector> res;
		if (nums.empty()) return res;
        int n=nums.size();
		sort(nums.begin(), nums.end());
		for (int i = 0; i < nums.size(); ++i) {
            if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target) break;
            if(nums[i]+nums[n-1]+nums[n-2]+nums[n-3]target) break;
                if(nums[i]+nums[j]+nums[n-1]+nums[n-2] target2) {
						while (l < r&&nums[r] == right) --r;
					}
					else if (nums[l] + nums[r] < target2) {
						while (l < r&&nums[l] == left) ++l;
					}
					else {
						res.push_back(vector{nums[i], nums[j], nums[l], nums[r]});
						while (l < r&&nums[l] == left) ++l;
						while (l < r&&nums[r] == right) --r;
					}
				}
				while (j + 1 < nums.size() && nums[j + 1] == nums[j]) ++j;
			}
			while (i + 1 < nums.size() && nums[i + 1] == nums[i]) ++i;
		}
		return res;
	}
};

你可能感兴趣的:(LeetCode)