K-SUM

K-Sum问题解析
K-SUM

一个典型的k个数的和相等的问题,所耗时间的N^(k-1),N为给出的数组中元素个数

1、2-sum

给出一个整形数组,从中找出两个元素的值的和等于给定的数
要求:定义的函数twoSum应该返回两个明确的元素,他们的和等于给出的值,并且元素1的下标小于元素2的下标

如:
输入: numbers={2, 7, 11, 15}, target=9
输出: index1=0, index2=1


提示:解决这个方法应该用一个HashMap来实现,每一个数组里的元素,他们的下标索引存储在这个HashMap中

public int[] twoSum(int[] nums, int target) {
    if(nums==null || nums.length<2)
        return new int[]{0,0};
 
    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
    for(int i=0; i<nums.length; i++){
        if(map.containsKey(nums[i])){
            return new int[]{map.get(nums[i]), i};
        }else{
            map.put(target-nums[i], i);
        }
    }
 
    return new int[]{0,0};
}

时间复杂度是 O(n).

2、4-sum

给定一个有n个元素的数组,找出所有的4个元素使得他们的和等于给定的数
要求:给出的4个元素必须以非递减的形式呈现(如 a ≤ b ≤ c ≤ d),同时给出的解中的4个元素不能完全一样

如, S = {1 0 -1 0 -2 2}, target = 0.

解集是:
(-1,  0, 0, 1)
(-2, -1, 1, 2)
(-2,  0, 0, 2)

public List<List<Integer>> fourSum(int[] nums, int target) {
    List<List<Integer>> result = new ArrayList<List<Integer>>();
 
    if(nums==null|| nums.length<4)
        return result;
 
    Arrays.sort(nums);
 
    for(int i=0; i<nums.length-3; i++){
        if(i!=0 && nums[i]==nums[i-1])
            continue;
        for(int j=i+1; j<nums.length-2; j++){
            if(j!=i+1 && nums[j]==nums[j-1])
                continue;
            int k=j+1;
            int l=nums.length-1;
            while(k<l){
                if(nums[i]+nums[j]+nums[k]+nums[l]<target){
                    k++;
                }else if(nums[i]+nums[j]+nums[k]+nums[l]>target){
                    l--;
                }else{
                    List<Integer> t = new ArrayList<Integer>();
                    t.add(nums[i]);
                    t.add(nums[j]);
                    t.add(nums[k]);
                    t.add(nums[l]);
                    result.add(t);
					
                    k++;
                    l--;
 
                    while(k<l &&nums[l]==nums[l+1] ){
                        l--;
                    }
 
                    while(k<l &&nums[k]==nums[k-1]){
                        k++;
                    }
                }
 
 
            }
        }
    }
 
    return result;
}


3、3-sum

给定一个有n个元素的数组,找出3个元素使得他们的和最接近于给定的目标数。返回这3个数的和。

如, S = {-1 2 1 -4}, and target = 1. 
最接近这个目标数的值为 2. (-1 + 2 + 1 = 2).

分析:这个问题类似于2-sum,所以可以用类似的方法解决,如从头和尾用两个指针

public int threeSumClosest(int[] nums, int target) {
    int min = Integer.MAX_VALUE;
	int result = 0;
 
	Arrays.sort(nums);
 
	for (int i = 0; i < nums.length; i++) {
		int j = i + 1;
		int k = nums.length - 1;
		while (j < k) {
			int sum = nums[i] + nums[j] + nums[k];
			int diff = Math.abs(sum - target);
 
			if(diff == 0) return sum;
 
			if (diff < min) {
				min = diff;
				result = sum;
			}
			if (sum <= target) {
				j++;
			} else {
				k--;
			}
		}
	}
 
	return result;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值