1. 两数之和 Two Sum
Given an array of integers nums
and an integer target
, return indices of the two numbers such that they add up to target
.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].
方法一:
暴力法。
以 [2,7,11,15]为例,先固定第一个元素2,然后查找之后的元素 7,11,15. 如果存在和9,则输出,如果不存在,则固定第二个元素7,查找之后的元素11,15.
这样就是两层循环,第一层i从0到长度-2,第二层j从i+1到长度-1。
int [] twoSum(int [] nums, int target){ for (int i = 0 ; i < nums.length-1; i++){ for( int j = i + 1; j < nums.length; j++){ if(nums[i] + nums[j] == target){ return new int []{ i, j}; } } } return new int []{ -1, -1}; }
时间复杂度为O(n^2)
方法二:
对于A+B=C,如果已知A和C,就可以求出B来。
先将数组里的所有的数和位置放到hash map字典里。
这样对于第一层的元素i查找配对的元素时,不是进入第二层遍历查找,而是到hash map字典里查找。
int [] two_sum_test(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++){ if(map.containsKey(target-nums[i])){ return new int []{i, map.get(target-nums[i])}; } } return new int[]{-1, -1}; }
时间复杂度为O(n)
方法三:
对于A+B=C,如果已知A和C,就可以求出B来。
我们可以在第一层遍历数据的时,可以把历史数据存到一个hash map里。
这样,对于第一层的元素i查找配对的元素时,不是进入第二层遍历查找,而是到历史hash map里查找有没有配对数据。
int [] twoSum_sample(int [] nums,int target){ Map<Integer,Integer> map=new HashMap<>(); for (int i = 0; i < nums.length; i++){ if(map.containsKey(nums[i])){ return new int[]{map.get(nums[i]), i}; }else{ map.put(target - nums[i], i); } } return new int[]{-1, -1}; }
时间复杂度为O(n)
方法四:
将原数组赋值给新数组并对新数组排序,然后用双指针法查找位置。
查找方法如下:令i =0, j = nums.length. 如果nums[i]+nums[j]>target, j--;如果nums[i]+nums[j]<target, i++;否则,找到i,j
然后查找i,j在原数组中的位置。
int [] two_sum_sort(int [] nums, int target){ int [] sort_nums = new int[nums.length]; for (int i = 0; i < nums.length; i++){ sort_nums[i] = nums[i]; } Arrays.sort(sort_nums,0,nums.length); int i = 0, j = sort_nums.length - 1; while(i < j){ if(sort_nums[i] + sort_nums[j] > target) { j--; }else if (sort_nums[i] + sort_nums[j] < target){ i++; }else{ break; } } if(i >= j) { return new int[]{-1, -1}; } int real_i = 0, real_j = 0; for (int real_pos = 0; real_pos < nums.length; real_pos++){ if(nums[real_pos] == sort_nums[i]){ real_i = real_pos; } if(nums[real_pos] == sort_nums[j]){ real_j = real_pos; } } return new int[]{real_i, real_j}; }
数组排序O(nlogn),双指针法遍历一遍O(n),总的时间复杂度O(nlogn)
参考链接
https://leetcode.com/problems/two-sum/solution/
https://leetcode-cn.com/problems/two-sum/