三数之和

文章目录


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

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

示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:

[
  	[-1, 0, 1],
	[-1, -1, 2]
]

本题返回数组中的数字,所以打乱索引没关系

排序+双指针

先进行排序,便于确定双指针移动的方向

每次遍历时:

  1. 下标 i 表示此时遍历到的数组下标,**固定arr[**i],让其他两个数凑 它
  2. 下标L, R:进行双指针移动,L从i+1开始,R从数组最后开始
    ( i, j 要定义在遍历循环的里面,所以每次遍历进行重新定义 )

指针移动时进行去重:

  1. 要凑的当前数 arr[i],i 移动时要跳过相同的:比较(i > 0 && nums[i] == nums[i - 1] ; (只有第一个数nums[o]不考虑去重)
  2. 指针L, R的移动也要去重
    中途指针发生移动,需要限制条件L<R,因为外面while的管不住这里
    移动while (L < R && nums[L] == nums[L + 1]) L++;
    例如 :-1,-1,-1,0,1 ,经过去重左指针从第一个-1 到达第三个-1,与后面的数0不重复,但-1已经参加运算,所以还要++
    再次移动 L++;

时间复杂度:O(n²)

遍历i一波:
	L,R移动一波

在这里插入图片描述

        class Solution {
            public List<List<Integer>> threeSum(int[] nums) {
                List<List<Integer>> list = new ArrayList();
                int len = nums.length;
                if (nums == null || len < 3)
                    return list;
                Arrays.sort(nums);
                // int i=1, j=nums.length-1; 考察i所在数,遍历时,右边两个数的位置是根据每次i位置设定的

                for (int i = 0; i < len; i++) {
                    if (nums[i] > 0) break; //若当期数字nums[i]>0, 与右边两个数的和>0
                    //只有第一个数nums[o]不考虑去重
                    if (i > 0 && nums[i] == nums[i - 1]) continue;
                    int L = i + 1;
                    int R = len - 1;
                    while (L < R) {
                        int twoSum = nums[L] + nums[R];//右边两数之和
                        if (twoSum < -nums[i]) {
                            L++;
                        } else if (twoSum > -nums[i]) {
                            R--;
                        } else {
                            //  list.add(new List[nums[k],nums[i],nums[j]]);
                            list.add(Arrays.asList(nums[i], nums[L], nums[R]));
                            //左右指针的移动也要去重
                            //中途指针发生移动,需要限制条件L<R,外面while的管不住这里
                            while (L < R && nums[L] == nums[L + 1]) L++;
                            // -1,-1,0,1 此时左指针从第一个-1 到达第二个-1,与后面的数不重复,但-1已经参加运算,所以还要++
                            L++;
                            while (L < R && nums[R] == nums[R - 1]) R--;
                            R--;
                        }
                    }
                }
                return list;
            }
        }

注:
忘记去重
[-1,-1,-1,0,1,1]:[-1,0,1],[-1,0,1]
Arrays.asList

  list.add(Arrays.asList(nums[i], nums[L], nums[R]));

在java语言中,把数组转换成List集合,有个很方便的方法就是 List list = Arrays.asList(“a”,“b”,“c”);

但这样得到的List它的长度是不能改变的。当你向这个List添加或删除一个元素时(例如 list.add(“d”);)程序就会抛出异常(java.lang.UnsupportedOperationException)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值