题目地址:https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
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
本想着这个题目难度不大,没想到做了一下,又死在了超时这个鬼界限上。
双层循环,既然有效,如果两个循环变量对应的数组元素的加和小于target
,那么继续循环,如果等于,那么返回,如果大于,重新遍历。
public class TwoSumInputArrayIsSorted {
public static int[] twoSum(int[] numbers, int target) {
if (numbers.length <= 1)
return new int[0];
int index1 = 0;
int index2 = 1;
if (numbers[index1] + numbers[index2] > target)
return new int[0];
boolean breakloop = false;
for (index1 = 0; index1 < numbers.length; index1++) {
for (index2 = index1 + 1; index2 < numbers.length; index2++) {
if (numbers[index1] + numbers[index2] < target)
continue;
else if (numbers[index1] + numbers[index2] == target) {
breakloop = true;
break;
} else
break;
}
if (breakloop == true)
break;
}
return new int[]{index1 + 1, index2 + 1};
}
public static void main(String[] args) {
int[] nums = {2, 3, 4};
int[] res = twoSum(nums, 6);
return;
}
}
时间复杂度为 O(n2) ,如果数据量比较大的时候,那不行了。
既然有序,那我们在上面想法的基础上试试二分查询看看行不:
public class TwoSumInputArrayIsSorted {
public static int[] twoSum(int[] numbers, int target) {
if (numbers.length <= 1)
return new int[0];
int index1 = 0;
int index2 = 1;
if (numbers[index1] + numbers[index2] > target)
return new int[0];
for (int i = 0; i < numbers.length; i++) {
int index = binarySearch(numbers, 0, numbers.length - 1, target - numbers[i]);
if (i != index) {
if ( i < index)
return new int[]{i + 1, index + 1};
else
return new int[]{index + 1, i + 1};
}
}
return new int[]{index1 + 1, index2 + 1};
}
public static int binarySearch(int[] nums, int low, int high, int target){
if (low == high && nums[low] != target)
return -1;
int mid = low + high / 2;
if (target == nums[mid])
return mid;
else if (target < nums[mid])
return binarySearch(nums, low, mid - 1, target);
else
return binarySearch(nums, mid + 1, high, target);
}
public static void main(String[] args) {
int[] nums = {2, 3, 4};
int[] res = twoSum(nums, 6);
return;
}
}
这么搞会报栈溢出的错误。因为上面代码的二分查找用的是递归,所以可能是递归太深,那么把递归换成非递归又怎样?
public static int binarySearch(int[] nums, int low, int high, int target){
while (low < high) {
int mid = low + high / 2;
if (target < nums[mid])
high = mid - 1;
else if (nums[mid] == target)
return mid;
else
low = mid + 1;
}
if (low == high && target == nums[low])
return low;
return -1;
}
还是超时,啥也别说了。彻底换方法吧,我们能否遍历数组一次,就能找到答案,当然可以,假设两个指针分别指向数组的首位元素,两个元素和大于target了,尾部指针往前调整,两个元素和小于target了,首部指针往后调整:
public class TwoSumInputArrayIsSorted {
public static int[] twoSum(int[] numbers, int target) {
if (numbers.length <= 1)
return new int[0];
int index1 = 0;
int index2 = numbers.length - 1;
while (index1 < index2) {
if (numbers[index1] + numbers[index2] > target)
index2--;
else if (numbers[index1] + numbers[index2] == target)
return new int[]{index1 + 1, index2 + 1};
else
index1++;
}
return new int[]{};
}
}
这回就快多了,时间复杂度为:O(n)。