程序員面試題目總結--數組(27)【Two Sum 、3Sum、3Sum Closest 、4Sum】

27、Two Sum 

題目:給定一個整數數組,找出和爲指定數值的兩個數,返回這兩個數的下標,要求下標以1爲基準

Input: numbers={2, 7, 11, 15}, target=9
  Output: index1=1, index2=2
原題:Given an array of integers, find two numbers such that they add up to a specific target number.The function twoSum should return indices of the two numbers such that they add  up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not
zero-based. You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9

Output: index1=1, index2=2    

分析:hash法,用一個哈希表,存儲每個數對應的下標,複雜度O(n).  

#include<iostream>
#include <hash_map>
#include <vector>
#include <algorithm>
using namespace std;
using stdext::hash_map;
vector<int> twoSum(vector<int> &num, int target) 
{
	hash_map<int, int> mapping;
	vector<int> result;
	for (int i = 0; i < num.size(); i++) 
	{
		mapping[num[i]] = i;
	}
	for (int i = 0; i < num.size(); i++) 
	{
		const int gap = target - num[i];
		if (mapping.find(gap) != mapping.end()) 
		{
			result.push_back(i + 1);
			result.push_back(mapping[gap] + 1);
			break;
		}
	}
	return result;
}
擴展1:3Sum 

題目:給定一個整型數組,找出這個數組中和爲0的三個數,要求找出所有符合條件的數
given array S = {-1 0 1 2 -1 -4}.
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
原題:Given an array S of n integers, are there elements a; b; c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
• Elements in a triplet (a; b; c) must be in non-descending order. (ie, a<= b<=c)
• The solution set must not contain duplicate triplets.
For example, given array S = {-1,0,1,2,-1,-4}.
A solution set is:
(-1, 0, 1)
(-1, -1, 2)                                                                     

分析:先排序,然後左右夾逼,複雜度O(n2)。這個方法可以推廣到k-Sum,先排序,然後做k-2次循環,在最內層循環左右夾逼      
      

vector<vector<int> > threeSum(vector<int>& num) 
{
	vector<vector<int> > result;
	if (num.size() < 3) return result;
	sort(num.begin(), num.end());
	const int target = 0;
	vector<int>::iterator last = num.end();
	for (vector<int>::iterator a = num.begin(); a < last; ++a) 
	{
		vector<int>::iterator b = a+1;
		vector<int>::iterator c = last-1;
		while (b < c) 
		{
			if (*a + *b + *c < target)
			{
				++b;
			}
			else if (*a + *b + *c > target)
			{
				--c;
			} 
			else 
			{
				vector<int> tmp;  
				tmp.push_back(*a);  
				tmp.push_back(*b);  
				tmp.push_back(*c);  
				result.push_back(tmp);
				++b;
				--c;
			}
		}
	}
	sort(result.begin(), result.end());
	result.erase(unique(result.begin(), result.end()), result.end());
	return result;
}

擴展2:3Sum Closest

題目:給定一個整型數組,找出和最接近指定數值的三個數,返回三個數的和 
原題:Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).     
分析:先排序,然後左右夾逼,複雜度O(n2)

int threeSumClosest(vector<int>& num, int target) {
	int result = 0;
	int min_gap = INT_MAX;
	sort(num.begin(), num.end());
	vector<int>::iterator last = num.end();
	for (vector<int>::iterator a = num.begin(); a != last; ++a) {
		vector<int>::iterator b = a+1;
		vector<int>::iterator c = last-1;
		while (b < c) {
			const int sum = *a + *b + *c;
			const int gap = abs(sum - target);
			if (gap < min_gap) {
				result = sum;
				min_gap = gap;
			}
			if (sum < target) ++b;
			else --c;
		}
	}
	return result;
}

擴展3: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)            
分析:
方法一:
先排序,然後左右夾逼,時間複雜度O(n^3),空間複雜度O(1)

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; ++a) 
	{
		for (vector<int>::iterator b = a+1; b < last; ++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 
				{
					vector<int> tmp;  
					tmp.push_back(*a);  
					tmp.push_back(*b);  
					tmp.push_back(*c);  
					tmp.push_back(*d);
					result.push_back(tmp);
					++c;
					--d;
				}
			}
		}
	}
	sort(result.begin(), result.end());
	result.erase(unique(result.begin(), result.end()), result.end());
	return result;
}

方法二:map 做緩存。用一個hashmap 先緩存兩個數的和時間複雜度,平均O(n^2),最壞O(n^4),空間複雜度O(n^2)

vector<vector<int> > fourSum1(vector<int> &num, int target) {
	vector<vector<int> > result;
	if (num.size() < 4) return result;
	sort(num.begin(), num.end());
	hash_map<int, vector<pair<int, int> > > cache;
	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) {
			const int key = target - num[c] - num[d];
			if (cache.find(key) == cache.end()) continue;
			const vector<pair<int, int> >& vec = cache[key];
			for (size_t k = 0; k < vec.size(); ++k) {
				if (c <= vec[k].second)
					continue; // 有重疊
				vector<int> tmp;  
				tmp.push_back(num[vec[k].first]);  
				tmp.push_back(num[vec[k].second]);  
				tmp.push_back(num[c]);  
				tmp.push_back(num[d]); 
				result.push_back(tmp);
			}
		}
	}
	sort(result.begin(), result.end());
	result.erase(unique(result.begin(), result.end()), result.end());
	return result;
}


                                                      


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章