15.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:[ [-1, 0, 1], [-1, -1, 2]]
1.暴力求解
thinking:通过三层loop 这里如果使用ArrryList 是有序 可重复,不能避免元素重复问题。但是使用
LikedHashSet就可以避免元素重复问题。
时间复杂度:O(n^3)
public List<List<Integer>> threeSum(int[] nums) {
if(nums == null || nums.length <=2){
return Collections.emptyList();
}
Arrays.sort(nums);
Set<List<Integer>> result = new LinkedHashSet<>();
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
for(int k = j+1;k<nums.length;k++){
if(nums[i]+nums[j]+nums[k] == 0){
List<Integer> list = Arrays.asList(nums[i],nums[j],nums[k]);
result.add(list);
}
}
}
}
return new ArrayList(result);
}
2.哈希表
/**
* hash slow
* 1406 ms 46 MB
*
* @param nums
* @return
*/
private List<List<Integer>> hashSolution(int[] nums) {
if (nums == null || nums.length <= 2) {
return Collections.emptyList();
}
Set<List<Integer>> result = new LinkedHashSet<>();
for (int i = 0; i < nums.length - 2; i++) {
int target = -nums[i];
Map<Integer, Integer> hashMap = new HashMap<>(nums.length - i);
for (int j = i + 1; j < nums.length; j++) {
int v = target - nums[j];
Integer exist = hashMap.get(v);
if (exist != null) {
List<Integer> list = Arrays.asList(nums[i], exist, nums[j]);
list.sort(Comparator.naturalOrder());
result.add(list);
} else {
hashMap.put(nums[j], nums[j]);
}
}
}
return new ArrayList<>(result);
}
3.夹逼法
thingking:左右夹逼,三数求和 a+b+c = 0 等价于 a+b=c 将数组进行排序,将c固定 a设置到c的下一个问题,也就是head b设置到最后一个位置 tail位置。
第一次遍历c固定 head 和tail 分别向中间移动,判断如果-sum < target 说明值大 因为是负数。所以tail 左移动,否则就是head右移动。如此一轮后 如果找不到,接着c++ head 和tail接着判断。
就可以找到。时间复杂度相对于上面两种是比较低的。
时间复杂度:O(n)
public List<List<Integer>> threeSum(int[] nums) {
if (nums.length == 0 || nums.length <=2){
return Collections.emptyList();
}
//元素去重
Set<List<Integer>> result = new LinkedHashSet<>();
//排序
Arrays.sort(nums);
for (int i = 0; i < nums.length-2; i++) {
int head = i+1;//左端
int tail = nums.length-1;//右端
while (head<tail){
int sum = -(nums[head]+nums[tail]);//取负值
if (sum == nums[i]){
List<Integer> list = Arrays.asList(nums[i],nums[head],nums[tail]);
result.add(list);
}
if(sum<=nums[i]){
tail--;
}else {
head++;
}
}
}
return new ArrayList<>(result);
}