1.题目描述
英文版:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
中文版:
在一个整型数组中,返回该数组中两个相加起来等于某个特定值的元素。
假设每一次输入都有唯一特定的结果,并且你不能使用同一个元素两次。
例如:
数组: nums = [2,7,11,15],target = 9,
因为 nums[0] + nums[1] = 2 + 7 = 9, 所以 return [0,1]
2.解法
2.1 解法1
思路:
第一次做LeetCode题目,看完这个题目之后。第一个想法就是使用暴力破解法,就是使用双重循环把每个数都分别进行两两相加,如果相加结果等于target时,则退出循环,返回结果。但是这种解法时间复杂度很高,接近O(n x n)。
/**
* 方式1:两层遍历
*/
public static int[] towSum1(int[] arr,int target){
int[] res = new int[2];
ok : for(int i = 0;i < arr.length;i++){
for(int j = i + 1;j < arr.length;j++){
if(arr[i] + arr[j] == target){
res[0] = i;
res[1] = j;
break ok;
}
}
}
return res;
}
在LeetCode上运行的结果:
2.2 解法2
思路
看了网上很多大神的博客和公众号之后,发现可以使用HashMap进行处理。
第一遍循环先把数组存到HashMap中,第二次循环再通过map.get(map.get(target - nums[i]))看能不能拿到相应的角标值,并且拿到的角标值不能等于i。
如果符合这两个条件,则说明角标为i和map.get(target - nums[i])对应的元素正是相加起来等于tartget的两个元素。这里也用到了两次循环,但是不是双重循环,是两个单层循环。
并且在不考虑hash冲突的情况下,HashMap取值的时间复杂度约等于O(1),所以整个算法的时间复杂度约为O(n)。
/**
* 方式2:两个单层循环,使用map缓存辅助
*/
public static int[] towSum2(int[] arr,int target){
int[] res = new int[2];
Map<Integer,Integer> map = new HashMap<>();
//第一层循环
// 将数组循环放入map中,key对应数组的值,value对应数组的角标
for(int i = 0;i < arr.length;i++){
map.put(arr[i],i);
}
//第二层循环
//循环将数据中的数拿出来,与map中的数进行匹配
for(int j = 0;j < arr.length;j++){
//如果map中存在target - arr[j]的数,则说明找到两个目标值的下标:j和map.get(target - arr[j])
//但是需要注意的是,map.get(target - arr[j])的值不能是j本身
if(map.get(target - arr[j]) != null
&& map.get(target - arr[j]) != j){
res[0] = j;
res[1] = map.get(target - arr[j]);
break;
}
}
return res;
}
在LeetCode上运行的结果:
2.3 解法3
思路:
解法3是在解法2的基础上进行相应的优化,即可以把两个循环简化成为一个循环,一边循环比较,一边把元素put到HashMap中。
但是这里需要注意的是,put元素需在比较之后执行,否则会有问题。
/**
* 方式3:单层循环,使用map缓存辅助
*/
public static int[] towSum3(int[] arr,int target){
int[] res = new int[2];
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i < arr.length;i++){
if(map.get(target - arr[i]) != null){
res[0] = i;
res[1] = map.get(target - arr[i]);
break;
}
map.put(arr[i],i);
}
return res;
}
在LeetCode上运行的结果:
3.测试
在本地,我只是简单写了一个main函数来对它进行测试。但这些代码都已经在LeetCode上运行通过。
public static void main(String[] args) {
int[] nums = {3,3};
int target = 6;
int [] result = twoSum3(nums,target);
System.out.println(result[0]+"---"+result[1]);
}