zoukankan      html  css  js  c++  java
  • 6.3Sum && 4Sum [ && K sum ] && 3Sum Closest

     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.
    ");
    			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;
    	}
    };
    
  • 相关阅读:
    正则表达式学习1
    SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
    (转)DBUS基础知识
    WakeLock的使用
    观察者模式
    Notification的使用
    Head First 设计模式之入门
    (转)Android WebView总结
    书架也是一根筋
    PendingIntent分析
  • 原文地址:https://www.cnblogs.com/liyangguang1988/p/3692540.html
Copyright © 2011-2022 走看看