进阶之路

首页 新随笔 管理

 3Sum

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)

 解析:分三步: a.排序.       b. 任取一个没取过的数,余下右边的序列中求 2Sum.       c. 取2Sum的过程中,应保证没有重复。

// O(n^2 + nlogn) // no set used! 
class Solution { 
public: 
	vector<vector<int> > threeSum(vector<int> &num) { 
		vector<vector<int> > vec; 
		vector<int> vec2(3, 0); 
		int n = num.size(); 
		if(n < 3) return vec; 
		sort(num.begin(), num.end());
		/*  promise not occur again  */
		int preValue = num[0] + 1; 
		for(int i = 0; i < n-2; ++i){ 
			if(num[i] == preValue) continue; 
			else preValue = num[i]; 
			/*      2Sum     */
			int j = i + 1, k = n-1; 
			while(j < k ){ 
				int sum = num[j] + num[k] + num[i]; 
				if(sum== 0){ 
					vec2[0] = num[i]; vec2[1] = num[j]; vec2[2] = num[k]; 
					while(j < k && num[j] == num[j+1]) ++j; // promise not occur again
					while(j < k && num[k] == num[k-1]) --k; 
					vec.push_back(vec2); 
					++j,--k; 
				}else if(sum < 0){ 
					++j; 
				} else --k; 
			} 
		} 
		return vec; 
	} 
}; 

  

 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)

 解析:3Sum 之上加一层循环。

 1 class Solution {
 2 public:
 3     vector<vector<int> > fourSum(vector<int> &num, int target) {
 4         vector<vector<int> > vec;
 5         vector<int> ans(4, 0); // record one answer
 6         int n = num.size();
 7         if(n < 4) return vec;
 8         sort(num.begin(), num.end());
 9         int preVal4 = num[0] ^ 0x1;
10         for(int i = 0; i < n - 3; ++i){
11             if(num[i] == preVal4) continue;
12             else preVal4 = num[i];
13             int preVal3 = num[i+1] ^ 0x1;
14             for(int j = i+1; j < n - 2; ++j){
15                 if(num[j] == preVal3) continue;
16                 else preVal3 = num[j];
17                 int s = j + 1, t = n - 1, target2 = target - num[i] - num[j];
18                 while(s < t){
19                     int sum = num[s] + num[t];
20                     if(sum == target2){
21                         ans[0] = num[i]; ans[1] = num[j]; ans[2] = num[s]; ans[3] = num[t];
22                         while(s < t && num[s] == num[s+1]) ++s;
23                         while(s < t && num[t] == num[t-1]) --t;
24                         vec.push_back(ans);
25                         ++s, --t;
26                     }else if(sum < target2) {
27                         ++s;
28                     }else --t;
29                 }
30             }
31         }
32         return vec;
33     }
34 };
Code

 

kSum(刷题模版)

class Solution {
 public:
     vector<vector<int> > kSum(vector<int> &num,int k, int target) {
        vector<vector<int> > vec;
        vector<int> vec2;
        if(num.size() < k) return vec;
        sort(num.begin(), num.end());
        getSum(vec, vec2, num, 0, k, target);
        return vec;
     }
 
     void getSum(vector<vector<int> > &vec, vector<int> &vec2, vector<int> &num, int begin, int k, int target){
        if(k == 2){
            int len = num.size(), s = begin, t = len - 1;
            while(s < t){
                int sum = num[s] + num[t];
                if(sum == target){
                    vec2.push_back(num[s]); vec2.push_back(num[t]);
                    while(s < t && num[s] == num[s+1]) ++s;
                    while(s < t && num[t] == num[t-1]) --t;
                    vec.push_back(vec2); 
                    vec2.pop_back(); vec2.pop_back(); // key 
                    ++s, --t;
                }else if(sum < target) {
                    ++s;
                }else --t;
            }    
            
        }else { 
            int len = num.size();
            int preValue = num[begin] ^ 0x1;
            for(int start = begin; start < len-k+1; ++start){
                if(num[start] == preValue) continue;
                else preValue = num[start];
                vec2.push_back(num[start]);
                getSum(vec, vec2, num, start + 1, k - 1, target - num[start]);
                vec2.pop_back();
            }
        }
     }
 };

 

算法复杂度分析:

k-SUM can be solved more quickly as follows.

  • For even k: Compute a sorted list S of all sums of k/2 input elements. Check whether S contains both some number x and its negation x. The algorithm runs in O(nk/2logn) time.

  • For odd k: Compute the sorted list S of all sums of (k1)/2 input elements. For each input element a, check whether S contains both x and ax, for some number x. (The second step is essentially the O(n2)-time algorithm for 3SUM.) The algorithm runs in O(n(k+1)/2) time.

Both algorithms are optimal (except possibly for the log factor when k is even and bigger than 2) for any constant k in a certain weak but natural restriction of the linear decision tree model of computation.

 

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).
class Solution {
public:
	int threeSumClosest(vector<int> &num, int target) {
		int len = num.size();
		if(len < 3){
			printf("Number of elements is less than 3.\n");
			return 0;
		}
		sort(num.begin(), num.end());
	    int minDiff = 0x7fffffff;   // note: a = 0x80000000; abs(a) == -2147483648;
		int preValue3 = num[0] + 1; // jump the number appeared again.
		for(int i = 0; i < len - 2; ++i){
			if(num[i] == preValue3) continue;
			else preValue3 = num[i];

			int s = i + 1, t = len - 1, temVal = num[i] - target;
			while(s < t){
				int curDiff = temVal + num[s] + num[t];
				if(curDiff == 0) return target;
				else if(curDiff < 0) ++s;
				else --t;

				if(abs(curDiff) < abs(minDiff)) minDiff = curDiff;
			}
		}
		return target + minDiff;
	}
};

 

 

 

posted on 2014-04-26 21:49  进阶之路  阅读(329)  评论(0编辑  收藏  举报