本题要求时间复杂度控制在o(nlgn),有两种想法:
1、先采取归并排序法排序,复杂度o(nlgn),然后再对x中出现的每一个元素list[i]在list中用二分查找x-list[i],由于二分查找复杂度为o(lgn),所以此操作复杂度为o(nlgn),符合要求,为了防止出现2list[i] = x这种情况加了排除找到位置和自身相等的情况。
代码如下:
/*************************************************************************
> File Name: binary_sum_x.cpp
> Author sangoly
> Mail: sangoly@aliyun.com
> Created Time: 2014年07月01日 星期二 19时00分28秒
************************************************************************/
#include<iostream>
#include<limits>
using namespace std;
void merge(int list[], int start, int middle, int end) {
int llen = middle - start + 1;
int rlen = end - middle;
int* larr = new int[llen + 1];
int* rarr = new int[rlen + 1];
int i, j;
for (i = 0; i < llen; i++) {
larr[i] = list[start + i];
}
for (j = 0; j < rlen; j++) {
rarr[j] = list[middle + 1 + j];
}
// Add the guard
larr[llen] = numeric_limits<int>::max();
rarr[rlen] = numeric_limits<int>::max();
i = j = 0;
for (int k = start; k <= end; k++) {
if (larr[i] <= rarr[j])
list[k] = larr[i++];
else
list[k] = rarr[j++];
}
delete [] larr;
delete [] rarr;
}
void merge_sort(int list[], int start, int end) {
if (start >= end)
return;
int middle = (start + end) / 2;
merge_sort(list, start, middle);
merge_sort(list, middle + 1, end);
merge(list, start, middle, end);
}
int binary_search(int list[], int start, int end, int target) {
if (start > end)
return -1;
int middle = (start + end) / 2;
if (list[middle] == target)
return middle;
else if (list[middle] > target)
return binary_search(list, start, middle - 1, target);
else
return binary_search(list, middle + 1, end, target);
}
int main() {
bool find_it = false;
int* list = new int[15]{10, 4, 3, 5, 20, 36, 7, 8, 14, 6, 9, 12, 43, 56, 2};
merge_sort(list, 0, 14);
int x = 92;
for (int i = 0; i < 15; i++) {
int target = list[i];
int index = binary_search(list, 0, 14, x - target);
if (index > 0 && index != i) {
find_it = true;
break;
}
}
if (find_it)
cout<<"Find it"<<endl;
else
cout<<"Did't find"<<endl;
delete [] list;
return 0;
}
下面再写一个利用c++标准库的版本
/*************************************************************************
> File Name: std_sum_x.cpp
> Author sangoly
> Mail: sangoly@aliyun.com
> Created Time: 2014年07月01日 星期二 19时30分24秒
************************************************************************/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool find_x(vector<int> &ivec, int x) {
sort(ivec.begin(), ivec.end());
for (vector<int>::iterator ct = ivec.begin(); ct != ivec.end(); ct++) {
int target = x - *ct;
vector<int>::iterator rt = find(ivec.begin(), ivec.end(), target);
if (rt != ivec.end())
return true;
}
cout<<endl;
return false;
}
int main() {
int element[] = {10, 4, 3, 5, 20, 36, 7, 8, 14, 6, 9, 12, 43, 56, 2};
size_t count = sizeof(element) / sizeof(int);
vector<int> ivec(element, element + count);
if (find_x(ivec, 11))
cout<<"Find it"<<endl;
else
cout<<"Did't find it"<<endl;
return 0;
}
第二种,先用归并法进行排序(o(nlgn)),然后从两侧向中间搜寻(o(n)),总体复杂度为o(nlgn)。代码如下
/*************************************************************************
> File Name: linear_sum_x.cpp
> Author sangoly
> Mail: sangoly@aliyun.com
> Created Time: 2014年07月01日 星期二 20时01分19秒
************************************************************************/
#include<iostream>
#include<limits>
using namespace std;
void merge(int list[], int start, int middle, int end) {
int llen = middle - start + 1;
int rlen = end - middle;
int* larr = new int[llen + 1];
int* rarr = new int[rlen + 1];
int i, j;
for (i = 0; i < llen; i++) {
larr[i] = list[start + i];
}
for (j = 0; j < rlen; j++) {
rarr[j] = list[middle + 1 + j];
}
// Add the guard
larr[llen] = numeric_limits<int>::max();
rarr[rlen] = numeric_limits<int>::max();
i = j = 0;
for (int k = start; k <= end; k++) {
if (larr[i] <= rarr[j])
list[k] = larr[i++];
else
list[k] = rarr[j++];
}
delete [] larr;
delete [] rarr;
}
void merge_sort(int list[], int start, int end) {
if (start >= end)
return;
int middle = (start + end) / 2;
merge_sort(list, start, middle);
merge_sort(list, middle + 1, end);
merge(list, start, middle, end);
}
bool linear_search(int list[], int len, int target) {
int start = 0, end = len - 1;
merge_sort(list, start, end);
while (start < end) {
int tmp_sum = list[start] + list[end];
if (tmp_sum == target)
return true;
if (tmp_sum > target)
end--;
else
start++;
}
return false;
}
int main() {
int list[] = {10, 4, 3, 5, 20, 36, 7, 8, 14, 6, 9, 12, 43, 56, 2};
size_t count = sizeof(list) / sizeof(int);
if (linear_search(list, count, 21))
cout<<"Find it"<<endl;
else
cout<<"Did't find it"<<endl;
return 0;
}