1 问题描述
2 问题分析
首先两数之和,拿到题目之后大致上有三种思路可以想到。
1⃣️全局排序+双指针夹逼。
2⃣️使用hash结构,key存储值,value存储对应下标位置。一次循环中将全部元素插入hash结构,二次循环进行寻找符合i+j=target
的i
和j
的对应下标并返回。
3⃣️还是hash结构,在第一次循环中就开始一边插入元素,一遍进行寻找符合条件的值。
2.1 方法选择
方法1⃣️在这道题中全局排序后会影响原始数据的下标,所以会新增一些操作步骤。这里不太适合。
方法2⃣️和方法3⃣️基本是一致的,不会破坏原数组结构,并且只需要O(n)的时间复杂度便可以完成题目。
2.2 细节剖析
选择了方法2⃣️或者方法3⃣️需要面对一个问题,就是key=值,不能排除数组中出现重复的值,这就可能带来重复key的问题,到底是存储第一个值,还是存储重复值的第二个下标。
题目中描述,输入一个target
,只有出现一个答案。那么就可以分析出来;
如果数组中出现了重复值,这个值记作i
1)如果满足i+j=target
,此时i可以取多个下标的值。这就违反了题目描述,出现了多个i
和一个j
的多个结果【结论:重复值不可能和其他值进行组合得到 i+j=target
】;
2)如果重复值*2 = target
,满足题目描述。【结论:如果重复值在答案中,那么一定是i+i = target
】
所以,如果我们遇到了重复值,只需要判断是否满足i*2=target
,满足则返回结果,如果不满足那么覆盖不覆盖下标都可,因为i
肯定不是答案。
3 代码实现
class Solution {
public int[] twoSum(int[] nums, int target) {
/**
1.全局排序后,使用双指针夹逼法 【排序的时间复杂度 + O(n)】
2.一次循环存入hash结构,二次循环来寻找hash结构中是否存在【tartget-curValue】的值【复杂度=O(n)】
3.一次循环中,同时存入hash结构,并且同时判断是否有对应的值
但是这道题需要返回对应的元素的下标,所以方法1不符合。这里使用方法二或者方法三都可。
*/
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(nums[i])){
if(nums[i]*2==target){
return new int[]{map.get(nums[i]),i};
}
}
int tmp = target - nums[i];
if(map.containsKey(tmp)){
return new int[]{i,map.get(tmp)};
}else{
map.put(nums[i],i);
}
}
return new int[]{};
}
}
3.1 代码分析
时间复杂度:因为只是循环了一次,所以时间复杂度 O(n)
空间复杂度:开辟了一个hashmap结构,空间复杂度O(n)