Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2 返回的是下标加1
这里已经是有序的数组,所以不需要像无序一样使用hashmap了。这里直接可以从两端向中间移。见代码
class Solution { public int[] twoSum(int[] numbers, int target) { if(numbers==null||numbers.length==0) return null; int[] re=new int[2]; //从前后一起向中间遍历,因为有序,可以这样做 for(int i=0,j=numbers.length-1;i<j;){ if(numbers[i]+numbers[j]==target){ re[0]=i+1; re[1]=j+1; return re; }else if(numbers[i]+numbers[j]>target){ j--; //因为有序,当两者相加大于target,说明需要减小,右边的左移 }else{ i++; } } return re; } }
当然,因为有序,也可以使用二分查找。从头开始遍历每个元素,在该元素右边的数组中二分查找target-该元素,没有就遍历下一个元素。二分查找不用管该元素的左边元素,因为是从左边开始遍历的,在右边找不到对应的,所以遍历到右边时,左边肯定是没有对应元素的。
见代码,这是c++代码,原理是一样的,看关键步骤。。这个运行时间大于上面的代码,这里主要掌握思路,也是一种解法
vector<int> twoSum(vector<int> &numbers, int target) { if(numbers.empty()) return {}; for(int i=0; i<numbers.size()-1; i++) {//遍历所有元素 int start=i+1, end=numbers.size()-1, gap=target-numbers[i]; while(start <= end) { //在右边的元素中使用二分查找与该元素对应的元素。 int m = start+(end-start)/2; if(numbers[m] == gap) return {i+1,m+1}; else if(numbers[m] > gap) end=m-1; else start=m+1; } } }