• [算法]K-SUM problem


    一、Two Sum

    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.

    For example:

    Input: numbers={2, 7, 11, 15}, target=9
    Output: index1=1, index2=2

    Naive Approach

    This problem is pretty straightforward. We can simply examine every possible pair of numbers in this integer array.

    Time complexity in worst case: O(n^2).

      1: public static int[] twoSum(int[] numbers, int target) {
    
      2:   int[] ret = new int[2];
    
      3:   for (int i = 0; i < numbers.length; i++) {
    
      4:     for (int j = i + 1; j < numbers.length; j++) {
    
      5:       if (numbers[i] + numbers[j] == target) {
    
      6:         ret[0] = i + 1;
    
      7:         ret[1] = j + 1;
    
      8:       }
    
      9:     }
    
     10:   }
    
     11:   return ret;
    
     12: }
     

    Better Solution

    Use HashMap to store the target value.

      1: public class Solution {
    
      2:     public int[] twoSum(int[] numbers, int target) {
    
      3: 	HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
    
      4: 	int[] result = new int[2];
    
      5: 	for (int i = 0; i < numbers.length; i++) {
    
      6: 		if (map.containsKey(numbers[i])) {
    
      7: 			int index = map.get(numbers[i]);
    
      8: 			result[0] = index+1 ;
    
      9: 			result[1] = i+1;
    
     10: 			break;
    
     11: 		} else {
    
     12: 			map.put(target - numbers[i], i);
    
     13: 		}
    
     14: 	}
    
     15: 	return result;
    
     16:     }
    
     17: }

    Time complexity depends on the put and get operations of HashMap which is normally O(1).

    Time complexity of this solution is O(n).


    二、Two Sum  II– Input array is sorted

    This problem is similar to Two Sum.But the input array is sorted.
    To solve this problem, we can use two points to scan the array from both sides. See
    Java solution below:

      1: public int[] twoSum(int[] numbers, int target) {
    
      2: 	if (numbers == null || numbers.length == 0)
    
      3: 		return null;
    
      4:  
    
      5: 	int i = 0;
    
      6: 	int j = numbers.length - 1;
    
      7:  
    
      8: 	while (i < j) {
    
      9: 		int x = numbers[i] + numbers[j];
    
     10: 		if (x < target) {
    
     11: 			++i;
    
     12: 		} else if (x > target) {
    
     13: 			j--;
    
     14: 		} else {
    
     15: 			return new int[] { i + 1, j + 1 };
    
     16: 		}
    
     17: 	}
    
     18:  
    
     19: 	return null;
    
     20: }

    三、Two Sum III - Data structure design

    Design and implement a TwoSum class. It should support the following operations: add and find.

    add - Add the number to an internal data structure.
    find - Find if there exists any pair of numbers which sum is equal to the value.

    For example,

    add(1); 
    add(3); 
    add(5);
    find(4) -> true
    find(7) –> false
     

    Java Solution

    Since the desired class need add and get operations, HashMap is a good option for this purpose.

      1: public class TwoSum {
    
      2: 	private HashMap<Integer, Integer> elements = new HashMap<Integer, Integer>();
    
      3:  
    
      4: 	public void add(int number) {
    
      5: 		if (elements.containsKey(number)) {
    
      6: 			elements.put(number, elements.get(number) + 1);
    
      7: 		} else {
    
      8: 			elements.put(number, 1);
    
      9: 		}
    
     10: 	}
    
     11:  
    
     12: 	public boolean find(int value) {
    
     13: 		for (Integer i : elements.keySet()) {
    
     14: 			int target = value - i;
    
     15: 			if (elements.containsKey(target)) {
    
     16: 				if (i == target && elements.get(target) < 2) {
    
     17: 					continue;
    
     18: 				}
    
     19: 				return true;
    
     20: 			}
    
     21: 		}
    
     22: 		return false;
    
     23: 	}
    
     24: }
     

    四、3Sum

    Problem:

    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)
    

    1. Naive Solution

    Naive solution is 3 loops, and this gives time complexity O(n^3). Apparently this is not an acceptable solution, but a discussion can start from here.

      1: public class Solution {
    
      2:     public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
    
      3:         //sort array
    
      4:         Arrays.sort(num);
    
      5:  
    
      6:         ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
    
      7:         ArrayList<Integer> each = new ArrayList<Integer>();
    
      8:         for(int i=0; i<num.length; i++){
    
      9:             if(num[i] > 0) break;
    
     10:  
    
     11:             for(int j=i+1; j<num.length; j++){
    
     12:                 if(num[i] + num[j] > 0 && num[j] > 0) break;
    
     13:  
    
     14:                 for(int k=j+1; k<num.length; k++){
    
     15:                   if(num[i] + num[j] + num[k] == 0) {
    
     16:  
    
     17:                       each.add(num[i]);
    
     18:                       each.add(num[j]);
    
     19:                       each.add(num[k]);
    
     20:                       result.add(each);
    
     21:                       each.clear();
    
     22:                   }
    
     23:                 }
    
     24:             }
    
     25:         }
    
     26:  
    
     27:         return result;
    
     28:     }
    
     29: }

    * The solution also does not handle duplicates. Therefore, it is not only time inefficient, but also incorrect.

    Result:

    Submission Result: Output Limit Exceeded
     

    2. Better Solution

    A better solution is using two pointers instead of one. This makes time complexity of O(n^2).

    To avoid duplicate, we can take advantage of sorted arrays, i.e., move pointers by >1 to use same element only once.

      1: public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
    
      2: 	ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
    
      3:  
    
      4: 	if (num.length < 3)
    
      5: 		return result;
    
      6:  
    
      7: 	// sort array
    
      8: 	Arrays.sort(num);
    
      9:  
    
     10: 	for (int i = 0; i < num.length - 2; i++) {
    
     11: 		 //avoid duplicate solutions
    
     12: 		if (i == 0 || num[i] > num[i - 1]) {
    
     13:  
    
     14: 			int negate = -num[i];
    
     15:  
    
     16: 			int start = i + 1;
    
     17: 			int end = num.length - 1;
    
     18:  
    
     19: 			while (start < end) {
    
     20: 				//case 1
    
     21: 				if (num[start] + num[end] == negate) {
    
     22: 					ArrayList<Integer> temp = new ArrayList<Integer>();
    
     23: 					temp.add(num[i]);
    
     24: 					temp.add(num[start]);
    
     25: 					temp.add(num[end]);
    
     26:  
    
     27: 					result.add(temp);
    
     28: 					start++;
    
     29: 					end--;
    
     30: 					//avoid duplicate solutions
    
     31: 					while (start < end && num[end] == num[end + 1])
    
     32: 						end--;
    
     33:  
    
     34: 					while (start < end && num[start] == num[start - 1])
    
     35: 						start++;
    
     36: 				//case 2
    
     37: 				} else if (num[start] + num[end] < negate) {
    
     38: 					start++;
    
     39: 				//case 3
    
     40: 				} else {
    
     41: 					end--;
    
     42: 				}
    
     43: 			}
    
     44:  
    
     45: 		}
    
     46: 	}
    
     47:  
    
     48: 	return result;
    
     49: }
     

    五、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)
    

    Thoughts

    A typical k-sum problem. Time is N to the power of (k-1).

    Java Solution

      1: public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
    
      2: 	Arrays.sort(num);
    
      3:  
    
      4: 	HashSet<ArrayList<Integer>> hashSet = new HashSet<ArrayList<Integer>>();
    
      5: 	ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
    
      6:  
    
      7: 	for (int i = 0; i < num.length; i++) {
    
      8: 		for (int j = i + 1; j < num.length; j++) {
    
      9: 			int k = j + 1;
    
     10: 			int l = num.length - 1;
    
     11:  
    
     12: 			while (k < l) {
    
     13: 				int sum = num[i] + num[j] + num[k] + num[l];
    
     14:  
    
     15: 				if (sum > target) {
    
     16: 					l--;
    
     17: 				} else if (sum < target) {
    
     18: 					k++;
    
     19: 				} else if (sum == target) {
    
     20: 					ArrayList<Integer> temp = new ArrayList<Integer>();
    
     21: 					temp.add(num[i]);
    
     22: 					temp.add(num[j]);
    
     23: 					temp.add(num[k]);
    
     24: 					temp.add(num[l]);
    
     25:  
    
     26: 					if (!hashSet.contains(temp)) {
    
     27: 						hashSet.add(temp);
    
     28: 						result.add(temp);
    
     29: 					}
    
     30:  
    
     31: 					k++;
    
     32: 					l--;
    
     33: 				}
    
     34: 			}
    
     35: 		}
    
     36: 	}
    
     37:  
    
     38: 	return result;
    
     39: }

    Here is the hashCode method of ArrayList. It makes sure that if all elements of two lists are the same, then the hash code of the two lists will be the same. Since each element in the ArrayList is Integer, same integer has same hash code.

      1: int hashCode = 1;
    
      2: Iterator<E> i = list.iterator();
    
      3: while (i.hasNext()) {
    
      4:       E obj = i.next();
    
      5:       hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
    
      6: }

    六、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).
    

    Analysis

    This problem is similar to 2 Sum. This kind of problem can be solved by using a similar approach, i.e., two pointers from both left and right.

    Java Solution

      1: public int threeSumClosest(int[] nums, int target) {
    
      2:     int min = Integer.MAX_VALUE;
    
      3: 	int result = 0;
    
      4: 	Arrays.sort(nums);
    
      5: 	for (int i = 0; i < nums.length; i++) {
    
      6: 		int j = i + 1;
    
      7: 		int k = nums.length - 1;
    
      8: 		while (j < k) {
    
      9: 			int sum = nums[i] + nums[j] + nums[k];
    
     10: 			int diff = Math.abs(sum - target);
    
     11: 			if(diff == 0) return sum;
    
     12: 			if (diff < min) {
    
     13: 				min = diff;
    
     14: 				result = sum;
    
     15: 			}
    
     16: 			if (sum <= target) {
    
     17: 				j++;
    
     18: 			} else {
    
     19: 				k--;
    
     20: 			}
    
     21: 		}
    
     22: 	}
    
     23: 
    
     24: 	return result;
    
     25: }

    Time Complexity is O(n^2).

  • 相关阅读:
    MFC学习笔记2添加资源
    汇编语言基础教程数据类型
    MFC学习笔记3引用资源
    asp.net MVC留言本示例
    汇编语言学习笔记按指定的字体输出文本
    C#(winform)项目中自制alert提示窗体并引用系统图标资源
    报表打印(rdlc)
    在内存中序列化,反序列化对象实体 来完成对象实体的深拷贝
    Hibernate中ORA01502错误的解 ...
    NHibernate的调试技巧和Log4Net配置
  • 原文地址:https://www.cnblogs.com/xiaomoxian/p/5187304.html
Copyright © 2020-2023  润新知