LeetCode之4Sum(经典)

题目:

Given an array S of n integers, are there elements a,b,c, and d in S such that a+b+c+d = target?

Find all unique quadruplets in the array which gives the sum of target.

Note:

? Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)

? The solution set must not contain duplicate quadruplets.

For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

A solution set is:

(-1, 0, 0, 1)

(-2, -1, 1, 2)

(-2, 0, 0, 2)

分析:给定一个包含n个数的数组,问是否在数组中存在四个数abcd,使得a+b+c+d = target。在数组中找出所有的符合条件的四个数的集合。要求每个集合不重复,并且abcd从小到大排列。方法三种:

1.先排序,然后左右夹逼,时间复杂度 O(n^3),空间复杂度 O(1)

2.先排序然后缓存两个数的和,最后,遍历。

3.先排序,然后缓存两个数的和,然后对这些和进行2sum。要求坐标不等。

代码:

#include "stdafx.h"
#include <ctime>
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

using namespace stdext;
using namespace std;
class Solution{
public:
	vector< vector<int> > FourSum1(vector<int>& num, int target){
		vector<vector<int>> result;
		vector<int> temp(4);
		sort(num.begin(),num.end());

		auto last = num.end();
		for (auto a = num.begin();a != last - 3;++a){
			for(auto b = next(a);b != prev(last,2);++b){
				auto c = next(b);
				auto d = prev(last);
				while(c < d){
					if (*a + *b + *c + *d < target){
						c++;
					}
					else if (*a + *b + *c + *d >target){
						d--;
					}else{
						temp[0]=*a;  temp[1]=*b;
						temp[2]=*c;  temp[3]=*d;
						result.push_back(temp);
						++c;--d;
					}
				}
			}
		}
		sort(result.begin(), result.end());
		//unique移除相邻重复的元素,然后返回的是新的结尾指针,erase擦除多余的内存部分。
		result.erase(unique(result.begin(),result.end()), result.end());

		return result;
	}

	vector< vector<int> > FourSum2(vector<int>& num, int target){
		vector<vector<int>> result;
		if (num.size() < 4) return result;

		vector<int> temp(4);
		sort(num.begin(),num.end());
		unordered_map<int, vector<pair<int, int>> > twoSum; //重复的键值,将其存放在一个vector中
		auto last = num.end();
		for (size_t a=0;a<num.size();++a){
			for (size_t b = a+1;b<num.size();++b){
				twoSum[num[a] + num[b]].push_back(pair<int,int>(num[a],num[b]));
			}
		}

		int sub = 0;
		for(size_t c=0;c<num.size();++c){
			for (size_t d=c+1;d<num.size();++d){
				sub = target - num[c] - num[d];
				if(twoSum.find(sub) == twoSum.end())
					continue;
				auto& subRst = twoSum[sub];//可能有多个结果。
				for (size_t i=0;i<subRst.size();++i){
					if(num[c] <= subRst[i].first || num[d] <= subRst[i].second) //去除重复的情况,pair中的元素从小到大排序,所以second
						continue;

					temp[0] = subRst[i].first;
					temp[1] = subRst[i].second;
					temp[2] = num[c];
					temp[3] = num[d];
					sort(temp.begin(),temp.end());
					result.push_back(temp);
				}
			}
		}
		sort(result.begin(), result.end());
		result.erase(unique(result.begin(),result.end()), result.end());

		return result;
	}

	vector< vector<int> > FourSum3(vector<int>& num, int target){
		vector<vector<int>> result;
		if (num.size() < 4) return result;

		vector<int> temp(4);
		sort(num.begin(),num.end());
		unordered_multimap< int,pair<int, int> > twoSum;
		for(size_t i = 0;i<num.size();++i){
			for (size_t j=i+1;j<num.size();++j){
				twoSum.insert(make_pair(num[i]+ num[j], make_pair(num[i],num[j])));
			}
		}

		for(auto i=twoSum.begin();i!=twoSum.end();++i){
			int sub = target - i->first;
			auto range = twoSum.equal_range(sub);
			for(auto j=range.first;j!=range.second;++j){
				pair<int,int> k = i->second;
				int a = k.first ;
				int b = k.second;
				int c = j->second.first;
				int d = j->second.second;
				if(a!=c && a!=d && b != c && b!=d){
					temp[0] = a;
					temp[1] = b;
					temp[2] = c;
					temp[3] = d;
					sort(temp.begin(),temp.end());
					result.push_back(temp);
				}
			}

		}
		sort(result.begin(), result.end());
		result.erase(unique(result.begin(),result.end()), result.end());

		return result;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	vector<int> v1;
	vector<vector<int>> result;

	v1.push_back(1);
	v1.push_back(0);
	v1.push_back(-1);
	v1.push_back(0);
	v1.push_back(-2);
	v1.push_back(2);

	//v1.push_back((rand()%200 - 100));v1.push_back((rand()%200 - 100));

	Solution s;
	clock_t start,finish;
	long i = 100000L;
	double duration;

	start = clock();
	result = s.FourSum1(v1,0);
	finish = clock();
	duration = (double)(finish - start)/CLOCKS_PER_SEC;
	cout<< "FourSum1 Runtime:" << duration << endl;

	start = clock();
	result = s.FourSum2(v1,0);
	finish = clock();
	duration = (double)(finish - start)/CLOCKS_PER_SEC;
	cout<< "FourSum2 Runtime:" << duration << endl;

	start = clock();
	result = s.FourSum3(v1,0);
	finish = clock();
	duration = (double)(finish - start)/CLOCKS_PER_SEC;
	cout<< "FourSum3 Runtime:" << duration << endl;
	return 0;
}

小结:

很值得研究的一道题目,建议自己写一遍,不仅对算法思想提升有帮助,而且在使用stl的学习上,也是有帮助的。根据我测试,就运行时间来说,方法一最快,二其次,三最慢。

另外,方法二实验unordered_map,其中key值相同的话,相同的key的value保存在一个vector桶中。而方法三使用unordered_multimap,当存在key相同的情况,并不是像前者那样存储,而是分开存储。

比如:unordered_map中形式如:   [1] = (-2, [2]((-2, 0),(-2, 0)))  相同的键值都放在一起。不允许重复的键值。

unordered_multimap中 形式如:(-2, (-2, 0)),(-2, (-2, 0))  虽然键值不一样,但是都是分开存放的。允许重复的键值。

时间: 2024-10-20 00:35:43

LeetCode之4Sum(经典)的相关文章

LeetCode 017 4Sum

[题目] Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. Note: Elements in a quadruplet (a,b,c,d) must be in non-descending o

[LeetCode] 018. 4Sum (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 018.4Sum (Medium) 链接: 题目:https://oj.leetcode.com/problems/4sum/ 代码(github):https://github.com/illuz/leetcode 题意: 给一个数列 S ,找出四个数 a,b,c,d 使得a + b + c + d = targ

[LeetCode] 454. 4Sum II 四数之和II

Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero. To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the r

[LeetCode] 18. 4Sum ☆☆

Given an array S of n integers, are there elements a, b, c, and d in S such that 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. For exampl

【Leetcode】4Sum

题目链接:https://leetcode.com/problems/4sum/ 题目: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. Note: Elements in a quadrupl

[LeetCode][JavaScript]4Sum

4Sum Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. Note: Elements in a quadruplet (a,b,c,d) must be in non-descending o

LeetCode——18. 4Sum

一.题目链接:https://leetcode.com/problems/4sum/ 二.题目大意: 给定一个数组A和一个目标值target,要求从数组A中找出4个数来使之构成一个4元祖,使得这四个数的和等于target,找出所有的四元组,当然这些四元组不能有重复的. 三.题解: 这道题实质就是3sum的变形,关于4sum问题,已经在https://www.cnblogs.com/wangkundentisy/p/9079622.html这里说过了,无外乎最外面两层循环,最里面的循环使用哈希表或

LeetCode 18. 4Sum (四数之和)

Given an array S of n integers, are there elements a, b, c, and d in S such that 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. For exampl

[LeetCode][Java] 4Sum

题目: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. Note: Elements in a quadruplet (a,b,c,d) must be in non-descending or