题目描述
输入一个递增排序的数组和一个数字s,在数组中查找两个数,是的它们的和正好是s。如果有多对数字的和等于s。输入任意一对即可。
分析
直接思路:遍历数组,去一个数字与该数字后面进行求和比较,如果和等于s则找到这两个数字,在有n个数字的数组中,时间复杂度为O(n2)。
推荐解法:由于数组已经递增排序,借鉴“前后指针”的思想,使用“前后索引”,前索引初始指向0,后索引初始指向数组最后的元素,将两个索引位置的数字求和。根据数组递增排序的特性,如果和等于s,则找到这两个数字;如果和小于s,则将前索引向后移动一位(求和将会增大);如果和大于s,则将后索引向前移动一位(求和将会减小)。循环判断即可,循环进行的条件是前索引必须小于后索引。扫描一遍就可以找出所有满足条件的数字,输出第一对即可,时间复杂度为O(n)。
代码:
package com.problem;
public class TwoNumSum {
public static void main(String[] args) {
TwoNumSum twoNumSum = new TwoNumSum();
int[] arr = {1, 2, 4, 7, 11, 15};
int s = 15;
int[] num1 = new int[1];
int[] num2 = new int[1];
System.out.println(twoNumSum.findNumsWithSum(arr, s, num1, num2));
System.out.println(num1[0] + ", " + num2[0]);
}
public boolean findNumsWithSum(int[] arr, int s, int[] num1, int[] num2) {
if(arr == null || arr.length <= 1)
return false;
boolean isFound = false;
int length = arr.length;
int leftIndex = 0; // 左索引初始指向0
int rightIndex = length - 1; // 右索引初始指向最后一个元素
while(leftIndex < rightIndex) {
int leftNum = arr[leftIndex];
int rightNum = arr[rightIndex];
int sum = leftNum + rightNum;
if(sum == s) { // 前后索引所指的元素和刚好为s,则找到
num1[0] = leftNum;
num2[0] = rightNum;
isFound = true;
break;
} else if(sum < s) { // 元素和小于s,则前索引向后移动一位(值增加)
leftIndex++;
} else if(sum > s){ // 元素和大于s,则后索引向前移动一位(值减少)
rightIndex--;
}
}
return isFound;
}
}
参考
1. 何海涛,剑指offer名企面试官精讲典型编程题(纪念版),电子工业出版社