1. 程式人生 > >LeetCode OJ 之 4Sum (”四個數的和“)

LeetCode OJ 之 4Sum (”四個數的和“)

題目:

Given an array S of n integers, are there elements abc, 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)

思路:

程式碼:

class Solution {
public:
vector<vector<int>> fourSum(vector<int>& num, int target) 
{
	vector<vector<int> > result;
	if (num.size() < 4) 
		return result;
	sort(num.begin(), num.end());
	vector<int>::iterator last = num.end();
	for (vector<int>::iterator a = num.begin(); a < last - 3 ; ++a) 
	{
		for (vector<int>::iterator b = a + 1 ; b < last - 2 ; ++b) 
		{
			vector<int>::iterator c = b + 1 ;
			vector<int>::iterator d = last - 1 ;
			while (c < d) 
			{
				if (*a + *b + *c + *d < target)
				{
					++c;
				} 
				else if (*a + *b + *c + *d > target) 
				{
					--d;
				} 
				else 
				{
					result.push_back({ *a, *b, *c, *d });
					++c;
					--d;
				}
			}
		}
	}
	sort(result.begin(), result.end());//注意sort不是vector的庫函式,而是algorithm庫的泛型演算法sort
	//unique的功能是去除相鄰的重複元素(只保留一個),其實它並不真正把重複的元素刪除,而是把重複的元素移到後面去了
	//然後返回的迭代器指向超出無重複的元素範圍末端的下一個位置。因為unique去除的是相鄰的重複元素,所以一般用之前都會要排一下序。
	//然後呼叫erase刪除後面的重複的元素
	result.erase(unique(result.begin(), result.end()), result.end());
	return result;
	}
};

程式碼2:

//map 做快取
// LeetCode, 4Sum
// 用一個 hashmap 先快取兩個數的和
// 時間複雜度,平均 O(n^2) ,最壞 O(n^4) ,空間複雜度 O(n^2)
class Solution {
public:
vector<vector<int> > fourSum(vector<int> &num, int target) 
{
	vector<vector<int> > result;
	if (num.size() < 4) 
		return result;
	sort(num.begin(), num.end());
	unordered_map<int, vector<pair<int, int> > > cache;
	
	//把num中任意兩個數的和作為鍵,這兩個數的下標對作為值儲存在cache中,(小的在前,大的在後)如果有兩對數的和相同,則鍵相同,下標對放在同一個vector裡
	for (size_t a = 0; a < num.size(); ++a) 
	{
		for (size_t b = a + 1; b < num.size(); ++b) 
		{
			cache[num[a] + num[b]].push_back(pair<int, int>(a, b));
		}
	}
	for (int c = 0; c < num.size(); ++c) 
	{
		for (size_t d = c + 1; d < num.size(); ++d) 
		{
			int key = target - num[c] - num[d];
			//如果key能在cache中的鍵中找到,則找到符合條件的,否則繼續查詢
			if (cache.find(key) == cache.end()) 
				continue;
			vector<pair<int, int> > vec = cache[key];//vec裡面可能有多個pair
			for (size_t k = 0; k < vec.size(); ++k) 
			{
				if (c <= vec[k].second)
					continue; // 為了防止重疊,可以讓 c > vec[k].second 或者 d < vec[k].first
				result.push_back( { num[vec[k].first],num[vec[k].second], num[c], num[d] });
				//	if (d >= vec[k].first)
				//	continue; 
				//  result.push_back( { num[c], num[d] , num[vec[k].first],num[vec[k].second] });
			}
		}
	}
	sort(result.begin(), result.end());
	result.erase(unique(result.begin(), result.end()), result.end());
	return result;
}
};