剑指offer——和为S的两个数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
自己的解法:
非常的麻烦
先把array的数组放入一个Map(Map中的数字范围中要小于sum)中,键即为该数字,然后利用迭代器遍历map,事先准备一个长度为array的数组res,存在两数之和相加为sum时,就把这一对数放入事先准备的数组res中,再利用迭代器把相关数删除。
最后遍历res数组,把相应的乘积最小的两个数输出。
import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import java.util.Iterator; public class Solution { public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) { ArrayList<Integer> arrayList = new ArrayList<Integer>(); if(array.length == 0) { return arrayList; } int min = 0; int i = 0, j = array.length - 1; while(j >= 0 && array[j] > sum) j--; Map<Integer, Integer> map = new HashMap<>(); int [] res = new int[array.length]; while(i <= j){ map.put(array[i++], 1); } i = 0; Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator(); while(it.hasNext()){ Map.Entry<Integer, Integer> entry = it.next(); int key = entry.getKey(); if(map.get(sum - key) != null){ res[i++] = key; res[i++] = sum - key; it.remove(); } } if(i < 1) return arrayList; int res1 = 0, res2 = 0; if(i >= 1){ min = res[0] * res[1]; res1 = res[0]; res2 = res[1]; } for(j = 2; j < i; j += 2){ int num = res[j] * res[j + 1]; if(min > num){ System.out.println(min); min = num; res1 = res[j]; res2 = res[j + 1]; } } res1 = res1 < res2 ? res1 : res2; res2 = sum - res1; arrayList.add(res1); arrayList.add(res2); return arrayList; } }
别人的解法:
从两头夹逼,i从低到高,j从高到低,然后判断num = array[i] + array[j] 和sum的大小
1,num = array[i] + array[j] == sum 即可返回,这个即是乘积最小的
2,num = array[i] + array[j] > sum 此时证明两数之和大了,j--
3,num = array[i] + array[j] < sum 此时证明两数之和小了,i++
import java.util.ArrayList; public class Solution { public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) { ArrayList<Integer> arrayList = new ArrayList<>(); if(array.length == 0) return arrayList; int i = 0, j = array.length - 1; while(i <= j){ int s = array[i] + array[j]; if(s == sum){ arrayList.add(array[i]); arrayList.add(array[j]); break; }else if(s < sum){ i++; }else{ j--; } } return arrayList; } }