41 - 找出数组中和为sum的 2个数字 | 找出和为sum的连续正整数序列

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 2small+1<=sum 得出 small<=(sum1)/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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值