题目描述
给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:
输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
分析
采用双指针思想
一个指针指向值较小的元素,一个指针指向值较大的元素。指向值较小元素的指针从有序数组的头向尾移动,指向值较大的元素的指针从有序数组的尾向头移动。因为数组为有序数组,所以采用双指针的思想一定能在某一时刻找到唯一解。
- 如果两指针指向的元素和sum == target,找到唯一解,算法结束
- 如果sum < target,移动指向值较小元素的指针
- 如果sum > target,移动指向值较大元素的指针
时间复杂度:O(n),每个元素最多被访问一次,共n个元素
空间复杂度:O(1),只使用两个指针
代码
public class TwoSumII {
public int[] twoSum(int[] numbers, int target) {
if(numbers == null) //考虑数组为空的情况
return null;
int p = 0, q = numbers.length-1;
while(p < q) {
int sum = numbers[p] + numbers[q];
if(sum == target) {
return new int[]{p+1, q+1};
}
if(sum < target) {
p++;
}
else {
q--;
}
}
return null;
}
public static void main(String[] args) {
//输入数组,不限数组长度
Scanner sc = new Scanner(System.in);
String str = sc.next().toString();
String[] arr = str.split(","); //输入的元素由“,”分开
int[] numbers = new int[arr.length];
for(int i = 0; i < numbers.length; i++) {
numbers[i] = Integer.parseInt(arr[i]); //将String类型的元素转为int型
}
//输入目标值
Scanner sc1 = new Scanner(System.in);
int target = sc1.nextInt();
TwoSumII ts = new TwoSumII();
int[] ans = ts.twoSum(numbers, target);
System.out.println(ans[0] +","+ ans[1]);
}
}
运行结果
总结
1.双指针主要用于遍历数组,两个指针指向不同的元素,协同完成工作。
2.parseInt() 方法用于将字符串参数作为有符号的十进制整数进行解析。如果方法有两个参数, 使用第二个参数指定的基数,将字符串参数解析为有符号的整数。
语法:
static int parseInt(String s)
static int parseInt(String s, int radix)
参数:
s是十进制表示的字符串
radix是指定的基数,可以是10、2、8、16等
返回值:
一个形参:返回十进制的字符串参数表示的整数
两个形参:返回指定基数的字符串参数表示的整数
3.用Java键盘输入不限长度的数组
Scanner sc = new Scanner(System.in);
String str = sc.next().toString();
String[] arr = str.split(","); //输入的元素由“,”分开
int[] numbers = new int[arr.length];
for(int i = 0; i < numbers.length; i++) {
numbers[i] = Integer.parseInt(arr[i]); //将String类型的元素转为int型
}
4.一定要处理数组为空的情况