算法学习笔记----判断集合S中是否存在有两个其和等于x的元素
题目:请给出一个运行时间为Θ(nlgn)的算法,使之能在给定一个由n个整数构成的集合S和另一个整数x时,判断出S中是否存在有两个其和等于x的元素。
解题思路:其代码实现如下所示:
#include <stdio.h>#include <errno.h>#ifndef INT_MAX#define INT_MAX((int)(~0U>>1))#endif#define ARRAY_SIZE(__s) (sizeof(__s) / sizeof(__s[0]))static void merge(int *a, int start, int mid, int end){ int nl = mid - start + 1; int nr = end - mid; int sentinel = INT_MAX; int left[nl + 1], right[nr + 1]; int i, j, k = start; for (i = 0; i < nl; ++i) { left[i] = a[k++]; } /* Set sentinel */ left[i] = sentinel; for (j = 0; j < nr; ++j) { right[j] = a[k++]; } /* Set sentinel */ right[j] = sentinel; i = j = 0; for (k = start; k <= end; ++k) { if (left[i] <= right[j]) { a[k] = left[i++]; } else { a[k] = right[j++]; } }}static void merge_sort(int *a, int start, int end){ int mid; if ((start >= 0) && (start < end)) { mid = (start + end) /2 ; merge_sort(a, start, mid); merge_sort(a, mid + 1, end); merge(a, start, mid, end); }}static int binary_search(int *a, int len, int expect, int target){ int left = 0, right = len - 1, mid; do { if (left == expect) { ++left; } if (right == expect) { --right; } mid = (left + right) / 2; if ((mid != expect) && (a[mid] == target)) { return 0; } else if (a[mid] > target) { right = --mid; } else { left = ++mid; } } while (left <= right); return -1;}static int check_exist_x(int *a, int len, int x){ int i; if (!a || len < 2) { fprintf(stderr, "Too few elements.\n"); return -1; } merge_sort(a, 0, len - 1); for (i = 0; i < len; ++i) { if (!binary_search(a, len, i, x - a[i])) { return 0; } } return -1;}int main(void){ int source[] = { 7, 5, 2, 4, 6, 1, 5, 3}; int x = 13; int ret; ret = check_exist_x(source, ARRAY_SIZE(source), x); printf("If there are two elements whose sum equals to x? %s.\n", ret < 0 ? "No" : "Yes"); return 0;}