question(题意):
Describe a O(n lg(n))-time algorithm that, given a set S of n integers and another integer x, determines whether or not there exist two elements in S whose sum is exactly x.
设计一个O(n lg(n))时间复杂度的算法,给定一个n个数字的集合,和一个数字x, 问,是否能在这个集合中找到两个数字,他们的和恰好为x.
Solution(解法):
在一个数组里面找某个数,O(n lg(n)),很容易想到用排序+二分,算法导论刚刚讲了归并排序,正好是O(n lg(n))的排序算法,可是这个题是找两个数的和为x, 那么该如何做呢,我们可以在排序后的数组里面,从小到大一次枚举第一个数(该数字必须满足<=x/2,原因自己想),然后在后面查找是否有另外一个数即可,下面是代码:
Code(代码):
//算法导论 习题2.3-7 #include <iostream> using namespace std; void merge(int* A, int p, int q, int r) { int n1 = q - p +1, n2 = r - q; int L[n1], R[n2]; for (int i = 0; i < n1; i++) L[i] = A[p+i]; for (int i = 0; i < n2; i++) R[i] = A[q+i+1]; int i = 0, j = 0, k = p; while (k <= r) { if (i >= n1) { while (j < n2) { A[k++] = R[j++]; } } else if(j >= n2) { while (i < n1) { A[k++] = L[i++]; } } else if(L[i] <= R[j]) { A[k++] = L[i++]; } else { A[k++] = R[j++]; } } } void merge_sort(int* A, int p, int r) { if (p < r) { int q = (p + r) / 2; merge_sort(A, p, q); merge_sort(A, q+1, r); merge(A, p, q, r); } } bool bSearch(int* A, int L, int R, int v) { while (L <= R) { int M = (L + R) / 2; if (A[M] < v) { L = M+1; } else if (A[M] > v) { R = M-1; } else { return true; } } return false; } bool Find(int* A, int n, int x) { merge_sort(A, 0, n-1); for (int i = 0; i < n; i++) { if (A[i] <= x / 2) { if (bSearch(A, i+1, n-1, x-A[i])) { return true; } } else { return false; } } return false; } int main() { int A[10] = {2, 3, 1, 5, 3, 2, 9, 3, 0, 7}, x; while (cin >> x) { if (Find(A, 10, x)) { cout << "find two numbers whose sum is " << x << endl; } else { cout << "Not find two numbers whose sum is "<< x << endl; } } return 0; }
原文地址:http://blog.csdn.net/myhelperisme/article/details/42089635