Question: Please give an algorithm with the running time of week (nlgn) so that it can be given when a set of S and another integer x composed of n integers, determine whether there are two elements in S whose sum is equal to or equal to x. Solution: the intuitive method is to directly calculate the sum of two elements in the set, and then determine whether x exists, but the time complexity is round (n ^ 2), which does not meet the requirements of the question, it is not a good solution to the problem. The following two methods are better: the first is the idea provided in the instructor's manual of Introduction to algorithms, which builds an auxiliary set of s ', you can determine whether there are repeated elements in the collection of the Secondary Set S and the original set after merging. The specific steps are as follows: 1) sort the set S. 2) construct the auxiliary set S', s' = {z: z = x-y, y, S}, that is, the element in s' is x minus the element in the set S. 3) sort the 'S' of the set. 4) Remove the repeated elements in the 'S' of the set and keep only one element, that is, make the elements in the 's' of the set unique. Perform the same processing on the set S. 5) Merge set S and S '6) if and only when the merged set has the same value at a continuous position, the sum of the two numbers in set S is x. (Basic literal translation) This problem-solving idea is problematic, and if it is simply understood literally, it is wrong, and in some cases it is incorrect. The following lists the problems with this idea:. after the secondary set S' is generated, only one repeated element in the Set S is removed and retained. In this way, the same repeating element exists in the s, why not do it before the generation of the auxiliary combination of S? If you do this after step 2, the elements in S are also unique, reducing repetitive work B. step 1 is completely unnecessary because S has already sorted the order in step 2, so the generated s' set is also sorted, but the sorting method is different. If the set S is in ascending order, the set S is in descending order. So there is no need to sort the set S', and you just need to process it a little while merging it. C. the original description in step 6th is "There exist two elements in S whose sum is exactly x if and only if the same value appears in consecutive positions in the merged output", if it is understood literally, it means that as long as there are repeated elements in the merged set, the sum of two numbers in the combined S is proved to be x. However, if you understand this, it is wrong. For example, if the set S = {2, 3, 5, 6}, x = 4, then S '= {2, 1,-1, -2}, the merged set is {-2,-1, 1, 2, 2, 3, 5, 6 }, duplicate elements {2, 2} exist in the merged combination. The position is continuous and the sum is x, but the sum of the two numbers in the Set S is x. Therefore, there is a problem with the expression in step 1, either it is true or wrong, or there is a problem with the understanding of speech differences. So how can we make a correct decision? Only when there must be at least two repeated elements in the merged set can we be sure that the sum of two numbers in the Set S is x. It can be proved that, for example, if w, S, and y, S also exists in the Set S, therefore, the merged set contains two duplicate elements w and y. If there are multiple pairs of solutions, there will be more repeated elements. D. in step 2, duplicate elements are uniquely identified. What if the sum of repeated elements is exactly x? At this moment, isn't it just self-defeating? For example, if the set S = {2, 2, 5, 6}, x = 4 is used to remove repeated elements, the opportunity to find the sum of two numbers and x is missing, in addition, there is no need for two elements for the sum of x to be repeated. Note that this idea is only used to determine whether the sum of two elements in the Set S is x. You do not need to determine which two elements are x. So I personally think the correct idea should be like this: 1) sort the set S; 2) check whether there are repeated elements in the Set S, if yes, determine whether the repeated element is x multiplied by 2 (that is, the two are added together). If yes, It is found, and no subsequent processing is required; otherwise, remove the repeated element, unique element in set S. 3) construct the auxiliary set S', s' = {z: z = x-y, y, and S}, that is, the element in s' is x minus the element in set S to generate 4) merge sets S and S' 5) when the merged set contains two or more repeated elements, the sum of the two elements in the Set S is x. Next, determine the algorithm complexity of the above ideas. In step 1, Merge Sorting is used. The time complexity is merge (nlg (n), and the time complexity of steps 1st, 3, 4, and 5 is merge (n ), merge to nlg (n )). Meets the requirements of the question. The code implementation is as follows: [cpp] # 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 (, mid + 1, end); merge (a, start, mid, end) ;}} static int check_exist_x (int * a, int len, Int x) {int I, j, k; int last;/* Just for test, shoshould avoid */int tmp [len]; int collection [2 * len]; int repeats; if (len <1) {fprintf (stderr, "Too few elements. \ n "); return-EINVAL;} merge_sort (a, 0, len-1); last = 0;/* Remove 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;} the second method is sorting + binary search. The specific steps are as follows: 1) sort the set S. 2) select an element S (I) from the set S, and calculate the difference between x and S (I), y = x-S (I ). In the set S, find whether y exists in the element except S (I). If y exists, return. 3) check whether all elements have been traversed. If not, skip step 1. Next, determine the complexity of this idea. In step 2, merge and sort are used for sorting. the time complexity is nlg (n); the time complexity of binary search is lg (n )), steps 2nd and 3 need to traverse n times. Therefore, the time complexity of steps 2nd and 3 is linear (nlg (n )), therefore, the total time complexity is attention (nlg (n), which meets the requirements of the subject. The code implementation is as follows: [cpp] # 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 (, mid + 1, end); merge (a, start, mid, end) ;}} static int binary_search (int * a, int len, Int secondary CT, int target) {int left = 0, right = len-1, mid; do {if (left = secondary CT) {++ left ;} if (right = normal CT) {-- right;} mid = (left + right)/2; if (mid! = Until CT) & (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; www.2cto.com 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 ;}