Leetcode15:三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

解法1 暴力法

三重循环,但需要注意去重

    //1.暴力法
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>>ret = new ArrayList<>();

        int length = nums.length;
	for (int i = 0; i < length; i++) {
	    for (int j = i+1; j < length; j++) {
		for (int k = j+1; k < length; k++) {
		    if (nums[i] + nums[j] + nums[k] == 0) {
		        List<Integer> temp = new ArrayList<>();
			temp.add(nums[i]);
			temp.add(nums[j]);
			temp.add(nums[k]);
			if (!contains(ret,temp)){
			    ret.add(temp);
			}
		    }
		}
	    }
	}
	return ret;
    }

    //判断ret中是否包含temp
    private boolean contains(List<List<Integer>> ret, List<Integer> temp) {

	for (List<Integer> list : ret) {
	    if (isSame(list,temp)){
	        return true;
	    }
	}
	return false;
    }

    //判断两个list是否相同
    private boolean isSame(List<Integer> list, List<Integer> temp) {
        if (list.size()!=temp.size()){
            return false;
	}
	Collections.sort(list);
        Collections.sort(temp);
	for (int i = 0; i < list.size(); i++) {
	    if (!list.get(i).equals(temp.get(i))){
	        return false;
	    }
	}
	return true;
    }

提交leetcode 时间超时了

解法2

尝试用Set解决list重复的问题

    //2.用set解决重复的问题
    public List<List<Integer>> threeSum2(int[] nums){
	List<List<Integer>>ret = new ArrayList<>();
	Set<List<Integer>> set = new HashSet<>();
	int length = nums.length;
	for (int i = 0; i < length; i++) {
	    for (int j = i+1; j < length; j++) {
		for (int k = j+1; k < length; k++) {
		    if (nums[i] + nums[j] + nums[k] == 0) {
			List<Integer> temp = new ArrayList<>();
			temp.add(nums[i]);
			temp.add(nums[j]);
			temp.add(nums[k]);
			Collections.sort(temp);
			if (!set.contains(temp)){
			    set.add(temp);
			    ret.add(temp);
			}
		    }
		}
	    }
	}
	return ret;
    }

此方法依然超时

解法3

先将数组排序,然后用O(n)的时间遍历每个元素a,此时问题便转化成了寻找two sum = 0-a的问题
前面我们已经做过用对撞指针的方法求two sum的问题,时间复杂度为O(n),因此总体的复杂度就变成了O(n^2)

如何保证结果不重复?
由于我们的数组已经有序,所以我们只需要保证当前遍历的元素a不等于其前一个元素就可以了

//解法3
    public List<List<Integer>> threeSum3(int[] nums) {

	List<List<Integer>> ret = new ArrayList<>();

        Arrays.sort(nums);
	for (int i = 0; i < nums.length; i++) {
	    if (i == 0 || nums[i] != nums[i - 1]) {
	        int left = i+1 ;
	        int right = nums.length-1;
	        int sum = 0-nums[i];
	        while (left<right){
	            if (nums[left]+nums[right]==sum){
			ret.add(Arrays.asList(nums[i], nums[left], nums[right]));
			while (left<right && nums[left+1]==nums[left]){
			    left++;
			}
			while (left<right && nums[right-1]==nums[right]){
			    right--;
			}
			left++;
			right--;
		    }else if (nums[left]+nums[right]<sum){
	                left++;
		    }else {
	                right--;
		    }
		}
	    }
	}
	return ret;
    }

猜你喜欢

转载自blog.csdn.net/qq_24094489/article/details/88808765