题目内容
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
分析过程
-
题目归类:
数组,遍历,hashmap -
题目分析:
上一篇博客采用hashmap解决了two sum的问题。类似的本题可以采用two sum的方式完成,固定第一个值x,此时另外两个值的和为 0-x; -
边界分析:
- 空值分析
nums为空返回空 - 循环边界分析
循环变量不可以大于nums.length;
- 空值分析
-
方法分析:
- 数据结构分析
hashmap,hashmap 的key保存具体数值,value保存index。
在比较的时候需要设立一个变量保存index,相同的数值,不同index才能使用。
补充:根据two sum 的方法,当出现两个相同的数和一个其他数相加为0时,会出现重复的情况。例如:[-1,1,0],[-1,-1,2],[0,-1,1]。用这种方法需要去重,
去重方法;使用hashset就可以判断重复的情况,之前以为hashset中的arraylist是保存的数据的引用,所以new新的arraylist就无法去重。现在看来hashset中equals是通过判断每一个list中的hashcode。
public int hashCode() { int hashCode = 1; for (E e : this)//E 为List<E>,this为需要添加的对象(String/ArrayList) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); return hashCode; }
- 状态机
- 状态转移方程
- 最优解
- 数据结构分析
-
测试用例构建
[1,2,3,-1,-2,-3,0],
[]
代码实现
import java.util.*;
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
HashSet<List<Integer>> set = new HashSet<List<Integer>>();
List<Integer> tmpList ;
for(int i = 0;i < nums.length; i++){
HashMap<Integer,Integer> map = new HashMap<>();
int target = 0 - nums[i];
for(int j = i+1; j < nums.length;j++){
int value = target - nums[j];
if(map.containsKey(value)){
tmpList = new ArrayList<Integer>();
tmpList.add(nums[i]);
tmpList.add(nums[j]);
tmpList.add(value);
Collections.sort(tmpList);
set.add(tmpList);
}else{
map.put(nums[j],j);
}
}
}
return new ArrayList<List<Integer>>(set);
}
}
效率提高
由图可知效率不高。
学习到另外一种方式可以有效的降低时间复杂度。
首先先排序。
设置一个i,j,k,分别为不同的下标。i的值不能大于nums.length-2; j 的值不能大于nums.length-1, k的值不小于等于j
和之前一样,先固定i的值。之后nums[i],nums[j],nums[k]之和如果大于0,k--,反之j++,当j>=k时break;
import java.util.*;
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
HashSet<List<Integer>> set = new HashSet<List<Integer>>();
Arrays.sort(nums);
for(int i = 0; i < nums.length-2;i++){
int j = i+1;
int k = nums.length-1;
while(j<k){
int sum =nums[i]+nums[j]+nums[k];
if(sum==0)
set.add(Arrays.asList(nums[i],nums[j++],nums[k--]));
else if(sum>0)
k--;
else if(sum<0)
j++;
}
}
return new ArrayList<List<Integer>>(set);
}
}
效率依旧不高,但是使用的方法可以借鉴。
拓展问题
3Sum Closest
4Sum
3Sum Smaller