算法学习笔记----判断集合S中是否存在有两个其和等于x的元素(二)

2014-11-24 08:19:01 · 作者: · 浏览: 1
move repeat elements */
for (i = 1; i < len; ++i) {
if (a[last] == a[i]) {
if ((a[last] << 1) == x) {
/* Found */
return 0;
}
continue;
}
a[++last] = a[i];
}
++last;
/* Form tmp set */
for (i = 0; i < last; ++i) {
tmp[i] = x - a[i];
}
i = 0;
j = last - 1;
k = 0;
/* Merge */
while ((i < last) && (j >= 0)) {
if (a[i] < tmp[j]) {
collection[k++] = a[i++];
} else {
collection[k++] = tmp[j--];
}
}
while (i < last) {
collection[k++] = a[i++];
}
while (j >= 0) {
collection[k++] = tmp[j--];
}
repeats = 0;
/* Check the number of repeat elements */
for (i = 1, j = 0; i < k; ++i, ++j) {
if (collection[i] == collection[j]) {
++repeats;
}
if (repeats >= 2) {
return 0;
}
}
return -1;
}
int main(void)
{
int source[] = { 7, 5, 2, 4, 6, 1, 5, 3};
int ret;
int x = 13;
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;
}
第二种是使用排序+二分查找,具体步骤如下:
1)对集合S进行排序
2)从集合S中选择一个元素S(i),计算x与S(i)的差值y=x-S(i)。在集合S中查找除S(i)之外的元素中是否存在y,如果存在,则返回。
3)检查是否全部元素已遍历,如果没有跳到第2步。
接下来确定该思路的复杂度。第1步使用归并排序来排序,时间复杂度为Θ(nlg(n));二分查找的时间复杂度为Θ(lg(n)),第2、3步需要遍历的次数为n,因此第2、3步的时间复杂度为Θ(nlg(n)),因此总的时间复杂度为Θ(nlg(n)),符合题目的要求。
代码实现如下所示:
[cpp]
#include
#include
#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