【剑指offer】面试题57:和为S的两个数字/和为S的连续正数序列【C++版本】

40 篇文章 1 订阅
26 篇文章 1 订阅

总结的部分题目思路与代码,待完善。
【剑指offer-第二版】部分题目与解答【C++版本】

题目一:

和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

解题思路:

1.使用hash表能够实现O(n)的时间复杂度,但是额外需要O(n)的空间,所以不是特别好。
2.应该抓住这里数组是一个递增数组的特点来解决问题,使用两个指针分别指向数组头尾,首先相加这两个数,如果所得的和小于目标数字s,那么把左边的指针向数组后面移动,使两数的和增加,反之就把右边的指针向数组前面移动,使两数的和减少。

可以AC的解法【C++版本】

#include <vector>
#include <iostream>
#include <unordered_map>

using namespace std;

vector<int> FindNumbersWithSum(vector<int> array, int sum);

//测试程序
int main() {
    vector<int> data{ 1,2,3,4,5,6,7,8,9,10 };

    vector<int> resu = FindNumbersWithSum(data, 13);

    for (auto a : resu) {
        cout << a << endl;
    }

    system("pause");
    return 0;
}

//解法
vector<int> FindNumbersWithSum(vector<int> array, int sum) {
    if (array.size() <= 1)
        throw new std::exception("invaild input data.");

    vector<int> resu;
    int low = 0, high = array.size() - 1;
    //临界条件
    while (low < high) {
        if (array[low] + array[high] == sum) {
            resu.push_back(array[low]);
            resu.push_back(array[high]);
            break;
        }
        else if (array[low] + array[high] < sum) {
            low++;
        }
        else {
            high--;
        }
    }

    return resu;
}

可以AC的解法二:使用hash表【C++版本】

//解法二
//使用hash表,时间复杂度O(N)但是也有O(N)的空间复杂度
vector<int> FindNumbersWithSum(vector<int> array, int sum) {
    unordered_map<int, bool> hashmap;
    vector<int> resu;
    int min = INT_MAX;

    for (auto a : array) {
        int tmp = sum - a;
        if (hashmap[tmp]) {
            //注意这里要求结果是积最小的那一对数(多种结果的情况),方法一自动实现了这一约束
            if (tmp*a < min) {
                resu.clear();
                resu.push_back(tmp);
                resu.push_back(a);
            }
        }
        else {
            hashmap[a] = true;
        }
    }

    return resu;
}

题目二:

和为s的连续正数序列

输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,则可以打印出序列{1,2,3,4,5}、{4,5,6}、{7,8}。

解题思路:

1.还是选择low、high两个指针,但一开始low指向1,high指向2,把[low,high]区间的所有数都相加,如果结果比s小就增大high(增大[low,high]区间之和),如果结果比s大就增大low(变相减少和)。

可以AC的解法【C++版本】

#include <vector>
#include <iostream>
#include <unordered_map>

using namespace std;

vector<vector<int> > FindContinuousSequence(int sum);

//测试
int main() {
    vector<vector<int>> matrix = FindContinuousSequence(9);

    system("pause");
    return 0;
}

//
vector<vector<int> > FindContinuousSequence(int sum) {
    vector<vector<int>> resu;
    vector<int> midResu;

    int low = 1, high = 2, mid = (1 + sum) >> 1;
    int s = low + high;
    //因为low,high必有两个数,所以low必须小于上位中位数(这里可以使用low<high作为临界条件,但是会多出计算量)
    while (low < mid) {
        if (sum == s) {
            midResu.clear();
            for (int i = low; i <= high; i++) {
                midResu.push_back(i);
            }
            resu.push_back(midResu);
            high++;
            s += high;
        }
        else if (s < sum) {
            high++;
            s += high;
        }
        else {
            s -= low;
            low++;
        }
    }

    return resu;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值