题目:已知一个有序递增的数组array和一个数s,请找出两个数字之和等于s的两个数。如果右多个这样的组合,则只需要输出一个就行。
例如,如果数组array={1,2,4,7,11,15},数s=15,请输出4和11,因为4+11=15
分析:首先我们会想到肯定要遍历这个数组,我们都知道不管你利用那种算法遍历,最坏情况下最好的时间复杂度都是O(n)。也就是遍历一次数组。那么我们如何才能做到最坏情况只需要遍历一次数组就能得出那两个数呢。先不去凭空想了,我们先来简单的算一算,看看会不会有什么点子出来。
首先我们将前两个元素想加,1+2<15,我们发现它小于15,怎么办,那肯定是向右移,1+3<15,how?依然像右移动。这时就发现了一个规律,当你发现和小于15时你就会讲元素右移,因为数组是有序的,但是单纯一个元素向一个方向移动的话也不能做到最坏情况只需遍历一次,因为另外一个元素是不动的,可能这个不动元素不是那两个数中的一个,那么你白白遍历了一次。
此时我们就会想到两个元素同时移动,于是很容易就会想到两个元素向中间靠拢的方法,如果两个数的和小了,则左边元素右移,大了则右边元素左移。如图
Step | Num1 | Num2 | Sum | Comparing with s | Operation |
1 | 1 | 15 | 16 | Greater | Select the previous number of Num2 |
2 | 1 | 11 | 12 | Less | Select the next number of Num1 |
3 | 2 | 11 | 13 | Less | Select the next number of Num1 |
4 | 4 | 11 | 15 | Equal |
代码实现:
public class TwoSum{
public static void main(String args[]){
int[] array = {1,2,4,7,11,15} ;
int s = 15 ;
fun(array,s) ;
}
public static void fun(int[] array,int s){
int n = array.length ;
int i = 0 ;
int j = n-1 ;
while(i<j){
if((array[i]+array[j])<s)
i++;
else if((array[i]+array[j])>s)
j--;
else{
System.out.println(array[i]+"+" + array[n-i-1]+"="+s) ;
i=j ; //跳出while循环
}
}
}
}
总结:此题的妙点在于两边同时开始遍历。