三数之和(剑指 Offer II 007. 数组中和为 0 的三个数 && 15. 三数之和)

题目:

思路:

【1】基于正常思维便是暴力破解,但是这种时间复杂度为O(N^3),基本很容易超时。而且还要去重【这里由于是无序的,所以又要用到排序】。

【2】那么既然是要排序的何不一开始就将无序的数组变为有序呢,一旦变为了有序,那么问题处理起来就会变得简单起来:

如数组[-4,-1, -1, 0, 1, 2] 
先遍历数组,如果i=0,先取-4,那么
第一个指针a指向下标为1的-1
第二个指针b指向下标为4的2
首先面对双指针,若a+b+i < 0,那么说明数需要加大
则指向最小的a,需要右移加大
若a+b+i > 0,那么说明数需要减少
则指向最大的b,需要左移减小
若a+b+i == 0,则需要纳入结果元组中

而这些过程中 a<b ,因为这样才会保证数据还没遍历完,还会有其他的
如果出现了a>=b,则说明数据重复使用或者重复遍历的过程,都是不需要的

代码展示:

暴力破解的做法:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        for (int k0 = 0; k0 < nums.length - 2;k0++){
            for (int k1 = k0+1; k1 < nums.length - 1;k1++){
                for (int k2 = k1+1; k2 < nums.length;k2++){
                    if (nums[k0]+nums[k1]+nums[k2] == 0){
                        ArrayList<Integer> objects = new ArrayList<>(Arrays.asList(nums[k0],nums[k1],nums[k2]));
                        result.add(objects);
                    }
                }
            }
        }
        //排序
        for (int i = 0;i<result.size();i++){
            Collections.sort(result.get(i));
        }
        //去重
        HashSet<List<Integer>> set = new HashSet<>(result);
        result.clear();
        result.addAll(set);
        return result;
    }   
}

 基于先排序然后采用双指针的方式进行处理:

//执行用时:43 ms, 在所有 Java 提交中击败了12.68%的用户
//内存消耗:48 MB, 在所有 Java 提交中击败了5.01%的用户
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> result = new ArrayList<>();
        int a,b,sum;
        for (int i = 0; i < nums.length - 2;i++){
            //如果最小值都是大于0的情况下,那么就没有必要继续遍历下去
            if (nums[i] > 0){
                break;
            }
            //在这里进行去重,如[-1, -1, 0, 1, 2],当第一个-1已经处理过了,那么第二个就没有必要了,元组已经被包含了
            if (i>0&&(nums[i] == nums[i-1])){
                continue;
            }
            a = i+1;
            b = nums.length-1;
            //采用双指针的方式,这样就能将暴力破解里面时间复杂度为O(N^2)部分转化为O(N)
            while (a<b){
                sum = nums[i] + nums[a] + nums[b];
                if (sum>0){
                    //这里采用了循环的特性进行去重处理
                    while (a < b && nums[b] == nums[--b]) ;
                }else if (sum<0){
                    while (a < b && nums[a] == nums[++a]) ;
                }else {
                    result.add(new ArrayList<>(Arrays.asList(nums[i], nums[a], nums[b])));
                    while (a < b && nums[b] == nums[--b]) ;
                    while (a < b && nums[a] == nums[++a]) ;
                }
            }
        }
        return result;
    }   
}

 

posted @ 2023-01-11 20:48  忧愁的chafry  阅读(21)  评论(0编辑  收藏  举报