15.三数之和Leetcode

一、题意
给定一个包含 n 个整数的数组 S,是否存在属于 S 的三个元素 a,b,c 使得 a + b + c = 0 ?找出所有不重复的三个元素组合使三个数的和为零。

注意:结果不能包括重复的三个数的组合。

例如, 给定数组 S = [-1, 0, 1, 2, -1, -4],

一个结果集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

第一种解法(超时)双指针法

思路:

class Solution{ 
    public List<List<Integer>> threeSum(int[] nums) {

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

         if (nums.length < 3) return res;

          Arrays.sort(nums);

          final int target = 0;

        for (int i = 0; i < nums.length - 2; ++i) {

             if(i > 0 && nums[i] == nums[i-1]){//写个具体的例子,为了减小复杂度
                 continue;
             }

            int j = i+1;
            int k = nums.length-1;

            while(j < k){
                int sum = nums[i] + nums[j] + nums[k];
                if(sum < 0){
                    j++;
                }else if(sum > 0){
                    k--;
                }else{
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[j]);
                    list.add(nums[k]);
                    if(!res.contains(list)){
                          res.add(list);
                    }
                }
            }
         }
        return res;
    }
}

超时的原因是:对是否有重复的判断使用了

if(!res.contains(list)){
                          res.add(list);
                    }

使用它的话,

第二种解法(未超时)重新写了判断重复的方法

  • 这里用到了三个指针i,j,k。i从第一个数到倒数第三个数依次遍历,初始化时j指向i后面一个数,k指向最后一个数。判断i,j,k位置上的数和0的关系,如果大于0,则k–,如果小于0,则j++。
  • 题目中要求不能有重复的数字出现,这里举几个例子。
    1. -6,-3,-3,-3,-3,0,1,2,2,3,3,在这个例子中,当i走到-3这里时,会出现很多重复的现象,所以就有了

if(i > 0 && nums[i] == nums[i-1]){ //如果上一个i位置的数和当前i位置的数相同,则跳到下一次循环
continue;
}

同理j的位置和k的位置出现相同的数字也会有很多重复现象的发生

class Solution{ 
    public List<List<Integer>> threeSum(int[] nums) {

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

         if (nums.length < 3) return res;

          Arrays.sort(nums);

          final int target = 0;

        for (int i = 0; i < nums.length - 2; ++i) {

             if(i > 0 && nums[i] == nums[i-1]){//在博客里写个具体的例子,为了减小复杂度
                 continue;
             }

            int j = i+1;
            int k = nums.length-1;

            while(j < k){
                int sum = nums[i] + nums[j] + nums[k];
                if(sum < 0){
                    j++;
                    while(nums[j] == nums[j-1] && j < k) ++j;
                }else if(sum > 0){
                    k--;
                    while(nums[k] == nums[k+1] && j < k) --k;
                }else{
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[j]);
                    list.add(nums[k]);
                    res.add(list);
                    ++j;
                    --k;
                     while(nums[j] == nums[j-1] && j < k) ++j;
                     while(nums[k] == nums[k+1] && j < k) --k;
                }
            }
         }
        return res;
    }
}

参考这篇博客

转为两数之和来解

猜你喜欢

转载自blog.csdn.net/qq_32682177/article/details/81912104