给定一个整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 0 开始计数 ,所以答案数组应当满足 0 <= answer[0] < answer[1] < numbers.length 。
假设数组中存在且只存在一对符合条件的数字,同时一个数字不能使用两次。
这个题首先最直接的思路就是采用双重循环,在数组中从前到后进行求和直到找到最后的答案
class Solution {
public int[] twoSum(int[] numbers, int target) {
for(int i=0;i<nums.length;i++){
for(int j=0;j<nums.length;j++){
if(numbers[i]+numbers[j]==target){
return new int[]{i,j};
}
}
}
}
}
在计算的时候我们可以发现对于任何一个i来说,他的前后项都会被加一遍,但是其实i前面的项是已经被加过的,所以就可以初步优化这段代码为
class Solution {
public int[] twoSum(int[] numbers, int target) {
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(numbers[i]+numbers[j]==target){
return new int[]{i,j};
}
}
}
}
}
这样优化之后,所有i的前项就不会再重复计算。但是这样做的话时间复杂度是O(n²),最差的情况会把整个数组读完。那么我们换个思路,假设数组中x+y=target,我们只需要检查数组中是否存在target-x的值,那么可以创建一个map,检查map中是否有target-x,如果没有那么就把数组的这一项放进map里,如果有就可以返回下标。
class Solution {
public int[] twoSum(int[] numbers, int target) {
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i=0;i<numbers.length;i++){
if(map.containsKey(target-numbers[i])){
return new int[]{map.get(target-numbers[i]),i};
}
map.put(numbers[i],i);
}
return new int[0];
}
}
这样子做的话我们的时间复杂度就可以缩小到O(n),最坏的情况就是遍历一边数组。