题目描述
给定一个数组和一个目标和,从数组中找两个数字相加等于目标和,输出这两个数字的下标。
例如:Given nums=[2,7,11,15], target=9; Because nums[0]+nums[1]=9,return [0,1];
解题方法
方法一(暴力解法)
暴力解法,是新手(本人无疑了)常用的操作,因为对各种知识还不够熟悉,所以联想不到其它解法。暴力解法是很容易接受的,但其缺点:时间和空间开销较大。
本题的暴力解法:用两层for循环,遍历所有情况看相加是否等于目标和,如果符合,直接输出。(所有代码都会用Java代码实现)。
代码一:
public int[] twoSum(int[] nums,int target){
int[] res= new int[2];
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
res[0]=nums[i];
res[1]=nums[j];
return res;
}
}
}
return res;
}
空间复杂度:
注:方法一的做法,几乎是每个人都能够做出来,因此是简单题,但是,在面试时,面试官为了筛选出能力突出的打工人,当然希望你有更好的解决方法。
方法二(hash table)
关于hash表一系列的知识,可以浏览link。
细看解法一中的第二个for循环:
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
可以将其换成这样来理解:
for(int j=i+1;j<nums.length;j++){
sub=target-nums[i]
if(sub==nums[j]){
}
,有没有一种方法不用遍历就能够找到sub元素呢?答案是:当然有,用 hash table 就能够实现。只需要将每个元素保存为hash的key,每个元素的下标存为value。
注:还需要判断找到的元素是不是当前元素,因为一个元素只能使用一次。
public int[] twoSum(int[] nums,int target){
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;i++){
map.put(nums[i],i);
}
for(int i=0;i<nums.length;i++){
int sub=target-nums[i];
if(map.containsKey(sub)&&map.get(sub)!=i){
return new int[]{i,map.get(sub)};
}
}
throw new IllegalArgumentException("No two sum solution");
}
上面的代码还可以继续简洁一下,因为两个for循环大小相同,就直接合起来就行,唯一的变化是不需要判断是不是当前元素,因为当前元素还没有加进去。
public int[] twoSum(int[] nums,int target){
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;i++){
int sub=target-nums[i];
if(map.containsKey(sub)){
return new int[]{i,map.get(sub)};
}
map.put(nums[i],i);
}
throw new IllegalArgumentException("No two sum solution");
}
总结
刚开始做这种题目时,还不太适应,因为接触太少了,还有基础知识把握不太牢固,因此在刷题的同时还需要去增强自己的专业知识。