标签:哈希表 出现 组合 etc get 元素 -- add 重复
三数之和题目入口
方法一:暴力法,三重for循环,枚举所有的三数组合,时间复杂度为O(\(n^3\)),因为时间复杂度过高,已经TLE了,所以对结果集不作去重处理了,此方法不可以通过
public List<List<Integer>> threeSum(int[] nums) {
int len = nums.length;
//提前定义结果列表
ArrayList<List<Integer>> result = new ArrayList<>();
for(int i = 0; i < len - 2; i++){
for(int j = i + 1; j < len - 1; j++){
for(int k = j + 1; k < len; k++){
if(nums[i] + nums[j] + nums[k] == 0){
result.add(Arrays.asList(nums[i] , nums[j] , nums[k]));
}
}
}
}
return result;
}
方法二:用哈希表保存结果,时间复杂度为O(\(n^2\)),用到的数据结构过于复杂,去重和保存不同两数和的问题也没有解决,此方法不可以通过
public List<List<Integer>> threeSum(int[] nums) {
int len = nums.length;
//提前定义结果列表
ArrayList<List<Integer>> result = new ArrayList<>();
//定义一个哈希表
HashMap<Integer, List<Integer>> hashMap = new HashMap<>();
for(int i = 0; i < len; i++){
int thatNum = 0 - nums[i];
if(hashMap.containsKey(thatNum)){
//如果已经存在thatNum,则找到了一组解
ArrayList<Integer> tempList = new ArrayList<>(hashMap.get(thatNum));
tempList.add(nums[i]);
result.add(tempList);
}
//把当前数对应的两数组合保存到map里
for(int j = 0; j < i; j++){
//以两数之和作为当前的关键字
int newKey = nums[i] + nums[j];
//如果key不存在,就直接添加进去
if(!hashMap.containsKey(newKey)){
ArrayList<Integer> tempList = new ArrayList<>();
tempList.add(nums[i]);
tempList.add(nums[j]);
hashMap.put(newKey , tempList);
}
}
}
return result;
}
方法三:双指针法,时间复杂度为O(\(n^2\)),此方法可以通过
(1)对nums数组进行排序,数字求和跟每个数的大小是有关系的,如果先对数组排序,那后面就会容易很多,这一步的时间复杂度为O(\(nlogn\)),"-1 0 1 2 -1 4"排序后的结果为"-4 -1 -1 0 1 2";
(2)然后定义左右指针L喝R,并以指针i遍历数组元素,固定3个指针中最左的指针i,双指针L,R分别在数组索引(i,len(nums))两端,所以初始值i=0,L=i+1,R=nums.length-1
令sum=nums[i]+nums[L]+nums[R],如果sum<0,L++并跳过所有重复的nums[L],如果L一直右移,直到跟R重合,那么i++,换一个数考虑,总而言之,L和R只要撞在一起,就i++。
public List<List<Integer>> threeSum(int[] nums) {
int len = nums.length;
//提前定义结果列表
ArrayList<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
//1.遍历每一个数,作为当前三元组最小的那一个数
for(int i = 0; i < len; i++){
//如果当前数已经大于0,直接退出循环
if(nums[i] > 0) break;
//如果当前数据已经出现过,直接跳过
if(i > 0 && nums[i] == nums[i - 1] ) continue;
//常规情况,以当前情况作为最小数,定义L,R指针
int L = i + 1;
int R = len - 1;
//只要两个指针不相撞,就继续移动指针
while(L < R){
int sum = nums[i] + nums[L] + nums[R];
//判断sum,与0作大小对比
if(sum == 0){
//找到了一组解,然后继续进行匹配
result.add(Arrays.asList(nums[i] , nums[L] , nums[R]));
L++;
R--;
//如果移动之后的元素相同,直接跳过
while(L < R && nums[L] == nums[L - 1]) L++;
while(L < R && nums[R] == nums[R + 1]) R--;
}else if(sum < 0){//较小的数增大,左指针右移
L++;
}else{//较大的数减小,右指针左移
R--;
}
}
}
return result;
}
标签:哈希表 出现 组合 etc get 元素 -- add 重复
原文地址:https://www.cnblogs.com/xbdcjs/p/14861134.html