Determine whether or not there exist two elements in Set S whose sum is exactly x - correct solution?

后端 未结 8 2028
醉梦人生
醉梦人生 2020-12-04 19:48

Taken from Introduction to Algorithms

Describe a Θ(n lg n)-time algorithm that, given a set S of n integers and another integer x, determines whet

相关标签:
8条回答
  • 2020-12-04 20:00

    Your analysis is correct, and yes you must sort the array or else binary search does not work.

    0 讨论(0)
  • 2020-12-04 20:02

    A simple solution is, after sorting, move pointers down from both ends of the array, looking for pairs that sum to x. If the sum is too high, decrement the right pointer. If too low, increment the left one. If the pointers cross, the answer is no.

    0 讨论(0)
  • 2020-12-04 20:03

    There's another very fast solution: Imagine you have to solve this problem in Java for about 1 billions integers. You know that in Java integers go from -2**31+1 to +2**31.

    Create an array with 2**32 billion bit (500 MB, trivial to do on today's hardware).

    Iterate over your set: if you have an integer, set corresponding bit to 1.

    O(n) so far.

    Iterate again over your set: for each value, check if you have a bit set at "current val - x".

    If you have one, you return true.

    Granted, it needs 500 MB of memory.

    But this shall run around any other O(n log n) solution if you have, say, to solve that problem with 1 billion integers.

    O(n).

    0 讨论(0)
  • 2020-12-04 20:08

    Here's is an alternate solution, by adding few more conditions into mergesort.

    public static void divide(int array[], int start, int end, int sum) {
    
        if (array.length < 2 || (start >= end)) {
            return;
        }
        int mid = (start + end) >> 1; //[p+r/2]
        //divide
        if (start < end) {
            divide(array, start, mid, sum);
            divide(array, mid + 1, end, sum);
            checkSum(array, start, mid, end, sum);
        }
    }
    
    private static void checkSum(int[] array, int str, int mid, int end, int sum) {
    
        int lsize = mid - str + 1;
        int rsize = end - mid;
        int[] l = new int[lsize]; //init
        int[] r = new int[rsize]; //init
    
        //copy L
        for (int i = str; i <= mid; ++i) {
            l[i-str] = array[i];
        }
        //copy R
        for (int j = mid + 1; j <= end; ++j) {
            r[j - mid - 1] = array[j];
        }
        //SORT MERGE
        int i = 0, j = 0, k=str;
        while ((i < l.length) && (j < r.length) && (k <= end)) {
        //sum-x-in-Set modification
        if(sum == l[i] + r[j]){
            System.out.println("THE SUM CAN BE OBTAINED with the values" + l[i] + " " + r[j]);            
        }
         if (l[i] < r[j]) {
                array[k++] = l[i++];
            } else {
                array[k++] = r[j++];
            }
        }
        //left over
        while (i < l.length && k <= end) {
            array[k++] = l[i++];
              //sum-x-in-Set modification
            for(int x=i+1; x < l.length; ++x){
                if(sum == l[i] + l[x]){
                    System.out.println("THE SUM CAN BE OBTAINED with the values" + l[i] + " " + l[x]);
                }
            }
        }
        while (j < r.length && k <= end) {
            array[k++] = r[j++];
              //sum-x-in-Set modification
            for(int x=j+1; x < r.length; ++x){
                if(sum == r[j] + r[x]){
                    System.out.println("THE SUM CAN BE OBTAINED with the values" + r[j] + " " + r[x]);
                }
            }
        }
    }
    

    But the complexity of this algorithm is still not equal to THETA(nlogn)

    0 讨论(0)
  • 2020-12-04 20:11

    Here's an O(n) solution using a hash-set:

      public static boolean test(int[] a, int val) {
          Set<Integer> set = new HashSet<Integer>();
    
          // Look for val/2 in the array
          int c = 0;
          for(int n : a) {
            if(n*2 == val)
              ++c
          }
          if(c >= 2)
             return true; // Yes! - Found more than one
    
          // Now look pairs not including val/2
          set.addAll(Arrays.asList(a));
          for (int n : a) {
             if(n*2 == val)
                continue;
             if(set.contains(val - n))
                return true;
          }
    
          return false;
       }
    
    0 讨论(0)
  • 2020-12-04 20:13

    Your solution seems fine. Yes you need to sort because its a pre requisite for binary search. You can make a slight modification to your logic as follows:

    public static boolean test(int[] a, int val) 
    {
        Arrays.sort(a);
    
        int i = 0;            // index of first element.
        int j = a.length - 1; // index of last element. 
    
        while(i<j)
        {
            // check if the sum of elements at index i and j equals val, if yes we are done.
            if(a[i]+a[j] == val)
                return true;
            // else if sum if more than val, decrease the sum.
            else if(a[i]+a[j] > val)
                j--;
            // else if sum is less than val, increase the sum.
            else
                i++;
        }
        // failed to find any such pair..return false. 
        return false;
    }
    
    0 讨论(0)
提交回复
热议问题