3Sum 数组找3数之和为0 @LeetCode

148 篇文章 69 订阅
27 篇文章 0 订阅

思路1:

排序,二分法查找,前后双指针O(n2*logn)

思路2:

排序,一次外循环+前后指针 O(n2)

package Level3;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 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) 
 *
 */
public class S15 {

	public static void main(String[] args) {
		// int[] num = {-1,0,1,2,-1,-4};
		// int[] num = {0,0,0,0};
		int[] num = { -2, 0, 1, 1, 2 };
		ArrayList<ArrayList<Integer>> ret = threeSum(num);
		System.out.println(ret.toString());
	}

	// 非递归解法
	public static ArrayList<ArrayList<Integer>> threeSum(int[] num) {
		Set<ArrayList<Integer>> ret = new HashSet<ArrayList<Integer>>();
		Arrays.sort(num);

		for (int i = 0; i < num.length - 1; i++) {		// 前指针向后
			for (int j = num.length - 1; j > i; j--) {	// 后指针向前
				int remain = 0 - (num[i] + num[j]);
				int third = Arrays.binarySearch(num, i + 1, j, remain);
				if (third >= 0) {
					ArrayList<Integer> list = new ArrayList<Integer>();
					list.add(num[i]);
					list.add(num[third]);
					list.add(num[j]);
					ret.add(list);
				}
			}
		}

		return new ArrayList<ArrayList<Integer>>(ret);
	}

	// 递归解法,超时!
	public static ArrayList<ArrayList<Integer>> threeSum1(int[] num) {
		Set<ArrayList<Integer>> ret = new HashSet<ArrayList<Integer>>();
		Arrays.sort(num);
		rec(num, 0, num.length - 1, ret);
		return new ArrayList<ArrayList<Integer>>(ret);
	}

	public static void rec(int[] num, int low, int high, Set<ArrayList<Integer>> ret) {
		if (low >= high) {
			return;
		}

		int remain = 0 - (num[low] + num[high]);
		int third = Arrays.binarySearch(num, low + 1, high, remain);
		if (third >= 0) {
			ArrayList<Integer> list = new ArrayList<Integer>();
			list.add(num[low]);
			list.add(num[third]);
			list.add(num[high]);
			ret.add(list);
			rec(num, low + 1, high, ret);
			rec(num, low, high - 1, ret);
		} else {
			if (remain > 0) {
				rec(num, low + 1, high, ret);
			} else {
				rec(num, low, high - 1, ret);
			}
		}
	}

}



/*
	 * 3 sum
	 */
	public static void find3Numbers(int[] A, int sum) {
		Arrays.sort(A);
		int len = A.length;
		for (int i = 0; i < len; i++) {
			int l = i + 1;
			int r = len - 1;
			while (l < r) {
				if (A[i] + A[l] + A[r] == sum) {
					System.out.println(A[i] + ", " + A[l] + ", " + A[r]);
					return;
				} else if (A[i] + A[l] + A[r] < sum) {
					l++;
				} else {
					r--;
				}
			}
		}
		System.out.println("Not found!");
	}


Try again:

public static ArrayList<ArrayList<Integer>> threeSum(int[] num) {
		ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
		if(num.length < 3){
			return ret;
		}
		
		Arrays.sort(num);
		for(int i=0; i<num.length-2 && num[i]<=0; i++){
			// Remove duplicates
			if(i>0 && num[i]==num[i-1]){
				continue;
			}
			// use two pointer to find b+c=-a
			int start = i+1, end=num.length-1;
			while(start < end){
				int sum = num[i] + num[start] + num[end];
				if(sum < 0){
					start++;
				}else if(sum > 0){
					end--;
				}else{		// find one
					ArrayList<Integer> al = new ArrayList<Integer>();
					al.add(num[i]);
					al.add(num[start]);
					al.add(num[end]);
					ret.add(al);
					// move left pointer to right and skip duplicates
					do{
						start++;
					}while(start<end && num[start]==num[start-1]);
					do{
						end--;
					}while(start<end && num[end]==num[end+1]);
				}
			}
		}
		return ret;
	}


注意如何跳过重复元素

public class Solution {
    public List<List<Integer>> threeSum(int[] num) {
        Arrays.sort(num);
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        int len = num.length;
        
        int i = 0;
        while(i <= len-3) {
            while(i-1 >= 0 && i <= len-3 && num[i] == num[i-1]) {
            	i++;
                continue;
            }
            int left = i+1, right = len-1;
            while(left < right) {
                int sum = num[i] + num[left] + num[right];
                if(sum == 0) {
                    List<Integer> al = new ArrayList<Integer>();
                    al.add(num[i]);
                    al.add(num[left]);
                    al.add(num[right]);
                    ret.add(al);
                    do {
                        left++;
                    } while(left<right && num[left]==num[left-1]);
                    do{
                        right--;
                    } while(left<right && num[right] == num[right+1]);
                } else if(sum < 0) {
                    left++;
                } else {
                    right--;
                }
            }
            i++;
        }
        
        return ret;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值