【刷题笔记】
Github仓库地址:https://github.com/Damaer/codeSolution
编程笔记地址:https://damaer.github.io/codeSolution/
题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
返回值描述:
对应每个测试案例,输出两个数,小的先输出。
输入
[1,2,4,7,11,15],15
返回值
[4,11]
暴力遍历
直接遍历每两个数,查看其和是否符合等于sum
,再计算其乘积,是否小于之前的乘积,如果小于,则更新。
import java.util.ArrayList;
public ArrayList<Integer> FindNumbersWithSum(int[] array, int sum) {
ArrayList<Integer> results = new ArrayList<>();
long mutip = 999999999;
if (array != null && array.length > 2) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] + array[j] == sum && array[i] * array[j] < mutip) {
results.clear();
results.add(array[i]);
results.add(array[j]);
mutip = array[i] * array[j];
} else if (array[i] + array[j] > sum) {
break;
}
}
}
}
return results;
}
使用hashSet
针对每一个数字a
,都查看hashset
中是否存在sum-a
,同时把该数字添加到set
中。如果存在则计算其乘积,更新乘积最小值。
public ArrayList<Integer> FindNumbersWithSum1(int[] array, int sum) {
ArrayList<Integer> results = new ArrayList<>();
long mutip = 999999999;
HashSet<Integer> set = new HashSet<>();
if (array != null && array.length > 2) {
for (int i = 0; i < array.length; i++) {
if (set.contains(sum - array[i]) && array[i]*(sum - array[i]) < mutip) {
results.clear();
results.add(sum-array[i]);
results.add(array[i]);
mutip = array[i] * (sum - array[i]);
}
set.add(array[i]);
}
}
return results;
}
时间复杂度:O(n)
空间复杂度:O(n)
双指针法
前面讲解的是暴力破解和hash法,这里讲解的是双指针法。
由于数组nums[]
是有序的,也就是第一个数字是最小的,第二个数字是最大的,那么我们使用一个指针i
指向数组第一个元素,一个指针j
指向数组最后一个元素。
i
指针往右边移动,j
指针往左边移动,直到两者相撞(相等)。
- 如果
nums[i]+nums[j]==sum
,那么说明这个是可能存在的解,需要计算两者的乘积,如果比保存的乘积还小,则更新结果。同时左边指针i
往右边移动一位,右边指针j
往左边移动一位。 - 如果
nums[i] + nums[j] > sum
,则说明和太大了,比sum
还要大,则右边的指针j需要左移一步,即是j--
。 - 如果
nums[i] + nums[j] < sum
,则说明和太小了,比sum
还要小,则左边的指针i需要左移一步,即是i++
。
public ArrayList<Integer> FindNumbersWithSum2(int[] array, int sum) {
ArrayList<Integer> results = new ArrayList<>();
long mutip = 999999999;
if (array != null && array.length > 2) {
int left = 0,right = array.length-1;
while(left<right){
if(array[left]+array[right]==sum){
if(array[left]*array[right]<mutip){
mutip = array[left]*array[right];
results.clear();
results.add(array[left]);
results.add(array[right]);
}
left++;
right--;
}else if(array[left]+array[right]>sum){
right--;
}else{
left++;
}
}
}
return results;
}
由于左右指针加起来最多是将数组遍历一遍,所以时间复杂度为O(n)。
【作者简介】:
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。个人写作方向:Java源码解析,JDBC,Mybatis,Spring,redis,分布式,剑指Offer,LeetCode等,认真写好每一篇文章,不喜欢标题党,不喜欢花里胡哨,大多写系列文章,不能保证我写的都完全正确,但是我保证所写的均经过实践或者查找资料。遗漏或者错误之处,还望指正。
平日时间宝贵,只能使用晚上以及周末时间学习写作,关注我,我们一起成长吧~