现在的位置: 首页 > 综合 > 正文

leetcode: 2Sum/3Sum/3SumClosest/4Sum系列问题

2013年09月02日 ⁄ 综合 ⁄ 共 3790字 ⁄ 字号 评论关闭

leetcode(http://leetcode.com/onlinejudge)上有好几道关于数组中几个数据和为target的题目。恰好正在看剑指offer中“和为s的两个数组这章”,据此思想,leetcode上的三道题目都被我解决了。总结一下。

1.twoSum:输入一个递增数组和一个数字s,在数组中查找两个数使得它们的和正好是s。

既然题目中已经提到了“递增数组”,那么肯定不会暴力了。因此肯定有<O(n*n)的办法了。

算法:最初我们找到数组的第一个数字和最后一个数字。当两个数字的和大于输入的数字时,把较大的数字往前移动;当两个数字的和小于数字时,把较小的数字往后移动;当相等时,打完收工。这样扫描的顺序是从数组的两端向数组的中间扫描。

链接:http://zhedahht.blog.163.com/blog/static/2541117420072143251809/

2.threeSum: Given an array S of n integers,
are there elements 
abc 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.
有了twoSum的启发,threeSum所有做的事,只需加上排序,和一层循环。经测试AC。
import java.util.ArrayList;
import java.util.Arrays;

public class ThreeSumSolution2 {
	private ArrayList<ArrayList<Integer>> list;
    
	public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
		list = new ArrayList<ArrayList<Integer>>();
		Arrays.sort(num);
		
		int i = 0;
		for (i = 0; i <= num.length - 3; i++) {
			if (i != 0 && num[i] == num[i - 1]) {
				continue;
			}
			judgeAndPut(num, i, i + 1, num.length - 1);
		}
       
		return list;
	}

	private void judgeAndPut(int[] num, int i, int p, int q) {
		while (p < q) {
			if (num[p] + num[q] < -num[i]) {
				p++;
			} else if (num[p] + num[q] > -num[i]){
				q--;
			} else if (num[p] + num[q] == -num[i]) {
				ArrayList<Integer> tmpList = new ArrayList<Integer>();
				tmpList.add(num[i]);
				tmpList.add(num[p]);
				tmpList.add(num[q]);
				list.add(tmpList);
				p++;
				q--;
				while (p < q && num[p] == num[p - 1]) {
					p++;
				}
				while (p < q && num[q] == num[q + 1]) {
					q--;
				}
			}
		}
	}
	
	public static void main(String[] args) {
		int num[] = {-1,0,1,2,-1,-4};
		System.out.println(new ThreeSumSolution2().threeSum(num));
	}
}

3. threeSumClosest: Given
an array 
S of n integers,
find three integers in 
S such
tha
t 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.

思路和threeSum几乎一样,只是查找条件有所变化而已。代码更简洁了。
import java.util.Arrays;

public class ThreeSumClosest {
    private int closest;
    private boolean needInit;
    
    public int threeSumClosest(int[] num, int target) {
    	closest = 0;
    	needInit = true;
		Arrays.sort(num);
		
		int i = 0;
		for (i = 0; i <= num.length - 3; i++) {
			if (i != 0 && num[i] == num[i - 1]) {
				continue;
			}
			judgeAndPut(num, i, i + 1, num.length - 1, target);
		}
        return closest;
    }

	private void judgeAndPut(int[] num, int i, int p, int q, int target) {
		
		while (p < q) {
			int sum = num[i] + num[p] + num[q];
			if (needInit || Math.abs(sum - target) < Math.abs(closest - target)) {
				closest = sum;
			}
			needInit = false;
			
			if (sum <= target) {
				p++;
				while (p < q && num[p] == num[p - 1]) {
					p++;
				}
			} else if (sum > target){
				q--;
				while (p < q && num[q] == num[q + 1]) {
					q--;
				}
			}
		}
		
	}
	
	public static void main(String[] args) {
		int num[] = {0,1,2};
		System.out.println(new ThreeSumClosest().threeSumClosest(num, 3));
	}
}

4. fourSum: 

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.
再多两层循环,此时已经是n立方的时间效率了,尝试了一下,居然也AC了。不知道还有没有更高效的算法。
import java.util.ArrayList;
import java.util.Arrays;

public class FourSum {
	private ArrayList<ArrayList<Integer>> list;
	
	public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
		list = new ArrayList<ArrayList<Integer>>();
		Arrays.sort(num);
		
		int i = 0;
		int j = 0;
		for (i = 0; i <= num.length - 4; i++) {
			if (i != 0 && num[i] == num[i - 1]) {
				continue;
			}
			
			for (j = i + 1; j <= num.length - 3; j++) {
				if (j != i + 1 && num[j] == num[j - 1]) {
					continue;
				}
				judgeAndPut(num, i, j, j + 1, num.length - 1, target);
			}
			
		}
       
		return list;	        
	}

	private void judgeAndPut(int[] num, int i, int j, int p, int q, int target) {
		while (p < q) {
			int sum = num[i] + num[j] + num[p] + num[q];
			if (sum < target) {
				p++;
			} else if (sum > target){
				q--;
			} else if (sum == target) {
				ArrayList<Integer> tmpList = new ArrayList<Integer>();
				tmpList.add(num[i]);
				tmpList.add(num[j]);
				tmpList.add(num[p]);
				tmpList.add(num[q]);
				list.add(tmpList);
				p++;
				q--;
				while (p < q && num[p] == num[p - 1]) {
					p++;
				}
				while (p < q && num[q] == num[q + 1]) {
					q--;
				}
			}
		}
		
	}
	
	public static void main(String[] args) {
		int num[] = {-1,0,1,0,-2,2};
		System.out.println(new FourSum().fourSum(num, 0));

	}

}

抱歉!评论已关闭.