TwoSum
描述
给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。你需要输出这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 0 到 n-1。
你可以假设数组递增有序。
输入
第一行:N个整数,作为数组的元素,空格分开
第二行:target
输出
两个下标,空格隔开。如有多组满足要求,输出靠前的一组。
样例输入
4
2 7 11 15
9
样例输出
0 1
解法1:
for循环嵌套,复杂度O(n^2)
解法2:
从头开始遍历数组,假如当前遍历到的数字为x那么我们可以将问题转化为寻找target - x的位置。既然这是个有序数组,那么就可以用二分法查找target - x。
(例如在数组[1,3,5,7,9,…,29]中,target是30。遍历到0索引时,target - x = 30 - arr[0] = 29,然后用二分法查找29的位置即可。)
复杂度O(nlg(n))
import java.util.Scanner;
public class TwoSum_02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i] = sc.nextInt();
}
int t = sc.nextInt();
// O(nlg(n))
for (int i = 0; i < arr.length; i++) {
int j = binarySearch(arr, t - arr[i]);
if (j != -1) {
System.out.println(i + " " + j);
break;
}
}
}
}
private static int binarySearch(int[] arr, int n) {
int begin = 0;
int end = arr.length - 1;
while (begin <= end) {
int mid = (begin + end) / 2;
if (arr[mid] > n) {
end = mid - 1;
} else if (arr[mid] < n) {
begin = mid + 1;
} else {
return mid;
}
}
return -1;
}
}
解法3:
定义两个指针,Scanner01和Scanner02。由两个指针求sum,两个指针向中间逼近。
复杂度O(n)。
import java.util.Scanner;
public class TwoSum_03 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i] = sc.nextInt();
}
int t = sc.nextInt();
// 1,3,6,a,9,12,17,28,b,35,46
int scannerPosition01 = 0;// 由前至后扫描
int scannerPosition02 = arr.length - 1;// 由后至前扫描
while (scannerPosition01 < scannerPosition02) {
int sum = arr[scannerPosition01] + arr[scannerPosition02];
if (sum < t) {
scannerPosition01++;
} else if (sum > t) {
scannerPosition02--;
} else {
System.out.println(scannerPosition01 + " " + scannerPosition02);
break;
}
}
}
}
}