题目
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。
示例
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解法
方法1
直接双重循环遍历数组,查找和值为 target 的两个元素
时间复杂度o(n2)
方法2
用Map集合把作为参数的数组存起来,数组中元素的值作为键Key,而对应的元素下标作为值Value。遍历一次数组(找出一个元素),并同时在Map集合中找另一个,Map集合查找的时间复杂度是o(1),这样整体的时间复杂度就降到了 o(n) 线性阶,最后将数组中找到的其中一个元素的下标,和Map集合中另一个元素(键)作为集合 get() 方法的参数得到的值即元素在原数组中的位置存在数组中返回
代码实现
方法1
public int[] twoSum(int[] nums, int target) {
int[] arr = 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) {
arr[0] = i;
arr[1] = j;
return arr;
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
注:方法中返回数组的语句可以直接写成:
return new int[] { i, j };
这样将原来的四句代码变为了一句
时间复杂度:o(n2)
空间复杂度:o(1)
方法2
第一段: 先存再找
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);//先遍历一遍数组,将数组全部放入Map集合中
}
for (int i = 0; i < nums.length; i++) {//开始找了,先遍历数组
if (map.containsKey(target - nums[i]) && map.get(target - nums[i]) != i) {
//直接在集合中找符合条件的元素
return new int[] { i, map.get(target - nums[i]) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
第二段: 边存边找
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {//只遍历一次数组
if (map.containsKey(target - nums[i])) {//在集合中找符合条件的元素
return new int[] { map.get(target - nums[i]), i };
}
map.put(nums[i], i);//将数组中的元素存入集合
}
throw new IllegalArgumentException("No two sum solution");
}
时间复杂度:o(n)
空间复杂度:o(n)
对比两种方法,要不浪费空间只好牺牲速度,而要提高效率就会牺牲空间