和为S的连续正数序列
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
采用滑动窗口原理,双指针记录滑动窗口的边界,当总和小于sum,扩大窗口,大指针继续+。当总和小于sum,缩小窗口,小指针+.
这种解法其实可以理解为双重for循环的剪枝后优化版。low相当于外循环的i,high相当于内循环的j。
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> allRes = new ArrayList<ArrayList<Integer>>();
int high = 2,low = 1;
while(high > low){
int cur_sum = (high + low) * (high - low + 1) / 2;
if(cur_sum < sum) high++;
else if(cur_sum > sum) low++;
else {
ArrayList<Integer> res = new ArrayList<Integer>();
for(int i = low; i <= high; i++)
res.add(i);
allRes.add(res);
low++;
}
}
return allRes;
}
}
和为S的两个数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
传统做法:
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> arr_sum = new ArrayList<Integer>();
int min = 10000;
int mlow = 0, mhigh = 0;
for(int i = 0; i < array.length; i++){
for(int j = i; j < array.length; j++){
if(array[i] + array[j] == sum){
if(min > array[i] * array[j]){
min = array[i] * array[j];
mlow = array[i];
mhigh = array[j];
}
}
}
}
if(mlow == 0 && mhigh == 0) return arr_sum;
arr_sum.add(mlow);
arr_sum.add(mhigh);
return arr_sum;
}
}
优化后的做法:
跟上一题的解法及其相似,双指针记录滑动窗口的边界。如果当前和 > sum,则high--,否则,low++.
为什么在第一次找到i,j时可以输出呢,因为越往中间走成积越大。
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> arr = new ArrayList<Integer>();
int i = 0, j = array.length -1;
while(i < j){
if(array[i] + array[j] == sum){
arr.add(array[i]);
arr.add(array[j]);
break;
}
while(i < j && array[i] + array[j] > sum) --j;
while(i < j && array[i] + array[j] < sum) ++i;
}
return arr;
}
}
对于这两题的总结:
看了第一题的思路还是做不出第二题,原因在于low和high的位置放错了,一开始把low和high放在了array[0],而high++和low++都会导致零时和array[i] + array[j]的增大,即不管怎么改变high和low都只会导致和比原来的小。反观第一题,high++导致临时的连续和增大,low++会导致临时的连续和减小,是双向的。故第二题应该把high和low放在数组的两端,low++会导致临时和增大,high--会导致临时和减小。