题目
思路
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–