1. 找出数组中和为sum的 2个数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出任意一对。
如输入{1,2,4,7,11,15} 和 S = 15。由于4+11 == 15,因此输出 {4,11}
解析:
最直观的思路是:
将数组插入hash-table,固定一个数number,然后在hash-table中找 (sum - number),如果找到,则是一对。时间复杂度O(n),空间复杂度O(n);如果此题扩展为找出所有的数对,还会产生重复的问题。
我们发现上述思路没有用到有序的条件。
我们定义2个指针,分别指向数组的头和尾,
- 如果2个指针指向数字的当前和等于sum,则找到;
- 如果当前和小于sum,为了增大当前和,则将第一个指针后移一位;
- 如果当前和大于sum,为了减小当前和,将第二个指针前移一位;
时间复杂度O(n),空间复杂度O(1),而且比较容易扩展到找出全部数对。
#include <iostream>
using namespace std;
bool FindTwoNumsWithSum(int nums[], int length, int sum, int &firstNum, int &secondNum) {
if (nums == NULL || length < 2)
return false;
long long currentSum = 0; //对于中间结果一定要考虑溢出问题
int i = 0, j = length-1;
while (i < j) {
currentSum = nums[i]+nums[j];
if (currentSum == sum) {
firstNum = nums[i];
secondNum = nums[j];
return true;
}
else if (currentSum < sum) {
i++;
} else {
j--; // cureetSum > sum
}
}
return false;
}
int main() {
int nums[] = {1,2,4,7,11,15};
int firstNum, secondNum;
int sum = 15;
if (FindTwoNumsWithSum(nums, sizeof(nums)/sizeof(nums[0]), sum, firstNum, secondNum))
cout << "firstNum: " << firstNum << endl <<"secondNum: " << secondNum << endl;
}
2. 找出和为sum的连续正整数序列
输入一个正整数s,打印所有和为 s 的连续正整数序列(至少含有两个数)。
例如输入 9,由于 2+3+4 = 9 ; 4+5 = 9,所以输出 {{2,3,4}, {4,5}}
知识前移:有了上题的经验,可以设置正整数序列的最小值和最大值:small, big
当前和 = small + (small+1) + … + big;
- 如果当前和等于sum:打印(small, big) 序列,big++ 后继续扫描
- 如果当前和小于sum:big++;currentSum+big
- 如果当前和大于sum:currentSum-small;small–
终止条件的计算;
由于最少2个数,
big=small+1
则
2∗small+1<=sum
得出
small<=(sum−1)/2
; 同理,
big<=(sum+1)/2
#include <iostream>
using namespace std;
void PrintSequence(int start, int end);
void FindContinuousNumsWithSum(int sum) {
if (sum <= 0)
return;
int small = 1;
int big = 2;
int currentSum = small + big;
while (small < big && small <= (sum-1)/2 && big <= (sum+1)/2) {
if (currentSum <= sum) {
if (currentSum == sum)
PrintSequence(small, big);
big++;
currentSum += big;
} else {
// if (currentSum > sum)
currentSum -= small;
small++;
}
}
}
void PrintSequence(int start, int end) {
if (start <= 0 || end <= 0 || start >= end)
return;
for (int i = start; i <= end; i++)
cout << i << " ";
cout << endl;
}
int main() {
int sum = 15;
FindContinuousNumsWithSum(sum);
}