题目一
输出有序数组a中,和为S的两个数。如有多个,输出乘积最小的两个。
思路:将两个指针分别指向首尾,如果和与指定值相等,则返回;如和大于指定值,则右指针向左移动;如和小于指定值,则左指针向右移动。
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
List<Integer> list = new ArrayList<Integer>();
if(array==null||array.length==0) return list;
int i = 0,j = array.length-1;
while(i<j){
if(array[i]+array[j]==sum){
list.add(array[i]);
list.add(array[j]);
break;
}else if(array[i]+array[j]>sum){
j--;
}else{
i++;
}
}
return list;
}
总结:这时时间复杂度为O(n)
扩展:
1)如果数组是无序的,需要先排序,时间复杂度为O(N);
2)如果是3个数的和为sum,则转化为2-sum问题,即两个数的和,为sum-ni。时间复杂度为O(N*N);
3)和为sum的n个数(这个涉及到树的深度遍历,放在树那一部分总结)
题目二:
和为sum的连续正整数序列
思路:可以借鉴前面的思想,用small和big分别表示最小值和最大值。如果从small到big的和大于sum,则去掉较小的值,即small++;如果和小于sum,则增大big的值。因为至少是两个值,所以small最大为(sum+1)/2;
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
if(sum<3) return list;
int small = 1,big = 2;
int mid = (1+sum)/2;
int curSum = small+big;
while(small<mid){
ArrayList<Integer> l = new ArrayList<Integer>();
if(curSum==sum) add(l,small,big);
while(curSum>sum&&small<mid){
curSum-=small;
small++;
if(curSum==sum){
add(l,small,big);
}
}
big++;
curSum+=big;
if(l!=null&&l.size()>0) list.add(l);
}
return list;
}
private void add(ArrayList<Integer> l,int small,int big){
for(int i = small;i<=big;i++){
l.add(i);
}
}