总结的部分题目思路与代码,待完善。
【剑指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;
}