<LeetCode>三数之和----利用哈希表和两数之和解题

题目

三数之和

在这里插入图片描述

思路

1、将三数之和转化为两数之和,取其中一个数转化为两数之和的值
如-1,则寻找除了这个数之外,任意两个数的和为1(即-1的绝对值)

2、创建一个函数实现两数之和,找到后将三个数传入llist中保存,函数的参数为数组,数值及数值的位置,要数值的位置是为了防止求两数之和下标重复

3、利用HashMap来快速找到合适的数

代码

/*

x1+x2+x3=0
-x3=x1+x2
传入-x3,x2=-x3-x1
1、将三数之和转化为两数之和,取其中一个数转化为两数之和的值
如-1,则寻找除了这个数之外,任意两个数的和为1

2、创建一个函数实现两数之和,找到后将三个数传入llist中保存,函数的参数为数组,数值及数值的位置,要数值
的位置是为了防止求两数之和下标重复

3、利用HashMap来快速找到合适的数
*/

class Solution {
    List<List<Integer>> llist=new ArrayList<>();
    public List<List<Integer>> threeSum(int[] nums) {
        

        Arrays.sort(nums);
        if(nums.length<3)
            return llist;
        

        for(int i=0;i<nums.length;i++)
        {
            if(nums[i]>0)
                break;
            else if(i>0 && nums[i-1]==nums[i])
                continue;
            twoSum(nums,-1*nums[i],i);
        }

        return llist;
    }

    public void twoSum(int nums[],int num,int p)
    {
        HashMap<Integer,Integer> hashmap=new HashMap<>();

        for(int i=p+1;i<nums.length;i++)
        {

            if(!hashmap.containsKey(nums[i]))
                hashmap.put(num-nums[i],nums[i]);
            else
            {
                List<Integer> list=new ArrayList<>();
                list.add(-1*num);
                list.add(hashmap.get(nums[i]));
                list.add(nums[i]);
                int j=0;
                for(;j<llist.size();j++)
                {
                    if(list.get(0).equals(llist.get(j).get(0))
                        && list.get(1).equals(llist.get(j).get(1)))
                        {
                          break;  
                        }
                }
                if(llist.size()==0 || j==llist.size())
                    llist.add(list);

            }
            
        }
    }
}

在这里插入图片描述

缺点就是由于使用了HashMap,因此使用containsKey()时及其耗时,并且去重设计的是循环结构,当数据量极大的时候就导致时间开销很大。

他人的解法(传送

思路

在这里插入图片描述

代码

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

    List<List<Integer>> llist=new ArrayList<>();
    int len=nums.length;
    if(len<3)
        return llist;

    Arrays.sort(nums);
    for(int i=0;i<len;i++)
    {
        //如果当前数字大于0,则三数之和一定大于0,结束循环
        if(nums[i]>0)
            break;

        if(i>0 && nums[i-1]==nums[i])
        {
            //防止产生重复解
            continue;
        }
        int L=i+1;
        int R=len-1;

        while(L<R)
        {
            int sum=nums[i]+nums[L]+nums[R];
            if(sum==0)
            {
                List<Integer> list=new ArrayList<>();
                list.add(nums[i]);
                list.add(nums[L]);
                list.add(nums[R]);
                llist.add(list);
                while(L<R && nums[L]==nums[L+1])
                {
                    L++;  //去重
                }
                while(L<R && nums[R-1]==nums[R])
                {
                    R--;  //去重
                }

                L++;
                R--;
            }
            else if(sum<0) 
            {
                L++;
            }
            else
            {
                R--;
            }
        }

    }
            return llist;
    }
}

实际上就是从两层循环,外层循环数组nums,内层循环找nums[i]的解。
外层循环碰到相同的数则跳过,免得有重复的数生成
内层循环则是看sum的值来移动L,R指针
sum=0,添加到结果
sum<0,说明L太小了,需要增大,于是L++
sum>0,说明R太大了,需要减小,于是R–

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值