三数之和-java-三指针

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

题解

如果是不去重的情况,可以用哈希表解决:先遍历两遍个数组,将两个数组的和作为key,和出现的次数作为value,然后再遍历一遍数组看需要的值是否在map里面出现。

当要考虑去重的情况时,先给数组排序,然后用双指针的方法:先固定 i,然后left=i+1,right=nums.length-1,左边和右边不断移动,求出此时三数的和,如果大了,right–,小了则right ++,直到三数之和为0,此时将三个数放到列表里面。

注意

  • 怎么给i 去重

    如果当前这个数和前一个数相等,说明这个数已经使用过了,continue跳过。必须是i和i-1相比,因为left=i+1;

  • 怎么给left 和right 去重

    当和已经为0 时,如果 nums[right] 和nums[right-1]相等,此时跳过,left同理。

  • while 循环条件 left 为什么不能等于 right

    因为题目要求的是三数之和,如果left==right ,那此时两个指针指向同一个数,就变成两数之和了。

  • asList的使用方法

    将对象型(Integer)数组值转化为列表

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length;i++){
            //排序之后的值大于0 ,之后的和相加都只能大于0
            if(nums[i]>0) return res;
            //对a去重  **注意**
            if(i>0 && nums[i]==nums[i-1]){
                continue;
                }  
            int left=i+1;
            int right=nums.length-1;
            //left 不能等于right **
            while(left<right){
                int sum=nums[i]+nums[left]+nums[right];
                if(sum>0){
                    right--;
                }else if(sum<0){
                    left++;
                }else{
                    res.add(Arrays.asList(nums[i],nums[left],nums[right]));
                    while(right>left && nums[right]==nums[right-1]) right--;  //right去
                    while(right>left && nums[left]==nums[left+1]) left++;  //left去重
                    right--;
                    left++;
                }
            }
           
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值