lettcode 15: 三数之和

/**
 * @Class ThreeSum
 * @Description
 * 给你一个包含 n 个整数的数组 nums,
 * 判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?
 * 请你找出所有满足条件且不重复的三元组。
 *
 * 注意:答案中不可以包含重复的三元组。
 *
 * 给定数组 nums = [-1, 0, 1, 2, -1, -4],
 *
 * 满足要求的三元组集合为:
 * [
 *   [-1, 0, 1],
 *   [-1, -1, 2]
 * ]
 *
 * @Author 10256137
 * @Date 2020/6/12
 **/
public class ThreeSum {
}
/**
 * 解法2:穷举法,利用排序去重,再逐个穷举
 * 时间复杂度:O(n^3)
 * 空间复杂度:O(n)
 */
public List<List<Integer>> threeSum(int[] nums) {

	Arrays.sort(nums);

	if(nums== null || nums.length==0){
		return new ArrayList<>();
	}

	List<List<Integer>> res = new ArrayList<>();
	for (int i = 0; i < nums.length; i++) {
		if(i>0 && nums[i]== nums[i-1]) continue;  // 去重
		for (int j = i+1; j <nums.length ; j++) {
			if(j>i+1 && nums[j]== nums[j-1]) continue;
			for (int k = j+1; k < nums.length; k++) {
				if(k>j+1 && nums[k] == nums[k-1]) continue;
				if(nums[i] + nums[j] + nums[k] == 0){
					 List<Integer> integers = new ArrayList<>();
					 integers.add(nums[i]);
					 integers.add(nums[j]);
					 integers.add(nums[k]);
					 res.add(integers);
				}
			}
		}
	}
	return res;
}
/**
*  解法2:先排序,目的是为了去重,
*  利用键值记录可以直接判断第三个数是否已存在,这样的话就不需要再对剩余的数据逐个判断,少了一个计算量级
*  时间复杂度:O(n^2)
*  空间复杂度:O(n)
*/
public List<List<Integer>> threeSum(int[] nums) {
	if(nums== null || nums.length==0){
		return new ArrayList<>();
	}
	Arrays.sort(nums);
	Map<Integer,Integer> map = new HashMap<>();
	for (int i = 0; i < nums.length; i++) {
		map.put(nums[i], i);
	}

	List<List<Integer>> res = new ArrayList<>();
	for (int i = 0; i < nums.length; i++) {
		if(i>0 && nums[i]== nums[i-1]) continue;  // 排序后对比是为了去重
		for (int j = i+1; j <nums.length ; j++) {
			if(j>i+1 && nums[j]== nums[j-1]) continue;
			int a = nums[i];
			int b = nums[j];
			int c = -a-b;

			if(map.containsKey(c) && map.get(c) > j){       // > j目的是去重
				List<Integer> integers = new ArrayList<>();
				integers.add(a);
				integers.add(b);
				integers.add(c);
				res.add(integers);
			}
		}
	}
	return res;
}
/**
 * 解法3: 先对元素进行排序(快排)固定某元素num[i],在其后面的一组元素中从两端选择两个元素,
 * 如果元素num[i]大于0,则其后的所有元素都>0,不可能存在一组3个元素之和等于0
 * 如果num[i]和选择的两个元素num[L],num[R] 之和小于0,则L++
 * 如果num[i]和选择的两个元素num[L],num[R] 之和大于0,则R--
 */
public List<List<Integer>> threeSum(int[] nums) {
	if(nums== null || nums.length==0){
		return new ArrayList<>();
	}
	// 底层用的快排
	Arrays.sort(nums);
	Map<Integer,Integer> map = new HashMap<>();
	for (int i = 0; i < nums.length; i++) {
		map.put(nums[i], i);
	}
	List<List<Integer>> res = new ArrayList<>();
	int len = nums.length;

	for (int i = 0; i < len; i++) {

		if(nums[i]>0) break;
		if((i>0) && (nums[i]== nums[i-1])) continue;    // 去重
		int L = i+1,R = len-1;
		while (L < R){
			int count = nums[i] + nums[L] + nums[R];
			if(count == 0){
				List<Integer> integers = new ArrayList<>();
				integers.add(nums[i]);
				integers.add(nums[L]);
				integers.add(nums[R]);
				res.add(integers);

				// 去重复
                while (L < R && nums[L] == nums[L + 1]) L++;
                while (L < R && nums[R] == nums[R - 1]) R--;
				L++;
				R--;
			}
			if(count < 0) L++;
			if(count > 0) R--;
		}
	}

	return res;
}
原文地址:https://www.cnblogs.com/fyusac/p/13121069.html