问题:输入一个有序数组和一个数字sum,在数组中查找两个数,使得它们的和恰好是sum。如果有多对数字满足条件,输出任意一对即可。
例如输入数组{1、2、4、7、11、15}和数字15,。由于4+11=15,所以输出4和11。
1.蛮力法——时间复杂度为O(n^2),空间复杂度为O(1)
//遍历数组中的每个元素Array[i],然后依次判断后面的某个数是否是sum-array[i]
bool findNumersWithSumByExhaustion(int* array, int length, int sum,
int& firstNumber, int& secondNumber) {
bool isFound = false;
if (NULL == array || 0 >= length) {
return isFound;
}
for (int i = 0; i < length; ++i) {
firstNumber = array[i];
secondNumber = sum - firstNumber;
for (int j = i + 1; j < length; ++j) {
if (secondNumber == array[j]) {
isFound = true;
return isFound;;
}
}
}
return isFound;
}
2.利用二分查找法——时间复杂度为O(n*logn),空间复杂度为O(1).
//遍历数组中的每个元素Array[i],然后二分查找值为sum-Array[i]的数
bool findNumersWithSumByBinarySearch(int* array, int length, int sum, int& firstNumber,
int& secondNumber) {
bool isFound = false;
if (NULL == array || 0 >= length) {
return isFound;
}
for (int i = 0; i < length; ++i) {
firstNumber = array[i];
secondNumber = sum - firstNumber;
//利用二分法查找另外一个数sum-array[i]
int left = i + 1, right = length - 1;
int middle = left + (right - left) / 2;
while (left <= right) {
middle = (left + right) >> 1;
if (array[middle] < secondNumber) {
left = middle + 1;
} else if (array[middle] > secondNumber) {
right = middle - 1;
} else {
isFound = true;
return isFound;
}
}
}
return isFound;
}
3.使用两个指针查找——时间复杂度为O(n),空间复杂度为O(1).
//利用两个分别指向数组两端的指针,根据两个指针所指的数字之和来移动指针,如果两个数的和大于指定值,则指向较大
//数的指针向数字递减的方向移动,反之另外一个指针向数字递增的方向移动
bool findNumersWithSumByPoints(int* array, int length, int sum,
int& firstNumber, int& secondNumber) {
bool isFound = false;
if (NULL == array || 0 >= length) {
return isFound;
}
int left = 0, right = length - 1;
while (left < right) {
if (array[left] + array[right] > sum) {
--right;
} else if (array[left] + array[right] < sum) {
++left;
} else {
firstNumber = array[left];
secondNumber = array[right];
isFound = true;
return isFound;
}
}
return isFound;
}
测试代码:
/*
*
* Created on: 2014-4-6 23:35:05
* Author: danDingCongRong
*/
#include<iostream>
using namespace std;
//输入各个数组元素
void inputArray(int* array, int length) {
for (int i = 0; i < length; ++i) {
cin >> array[i];
}
}
//如果找到这两个数则输出,否则显示未找到
void showResult(bool isFound, int firstNumber, int secondNumber) {
if (isFound) {
cout << "firstNumber=" << firstNumber << endl;
cout << "secondNumber=" << secondNumber << endl;
} else {
cout << "未找到满足条件的两个数." << endl;
}
}
int main() {
int sum = 0, length = 0;
cout << "请输入数组的长度:" << endl;
cin >> length;
cout << "然后输入这" << length << "个数字:" << endl;
int* x = new int[length];
inputArray(x, length);
cout << "请输入两个数字之和:" << endl;
while (cin >> sum) {
bool isFound = false;
int firstNumber = 0, secondNumber = 0;
isFound = findNumersWithSumByExhaustion(x, length, sum, firstNumber,
secondNumber);
showResult(isFound, firstNumber, secondNumber);
isFound = false;
firstNumber = 0, secondNumber = 0;
isFound = findNumersWithSumByBinarySearch(x, length, sum, firstNumber,
secondNumber);
showResult(isFound, firstNumber, secondNumber);
isFound = false;
firstNumber = 0, secondNumber = 0;
isFound = findNumersWithSumByPoints(x, length, sum, firstNumber,
secondNumber);
showResult(isFound, firstNumber, secondNumber);
cout << "请输入两个数字之和:" << endl;
}
return 0;
}
体会:利用两个指针来查找指定数字的方法在别的题目中也大量使用,并且效率很高,应该掌握这种方法。
注:部分算法参考自编程之美和剑指offer