Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find all differences in sorted array

I have a sorted (ascending) array of real values, call it a (duplicates possible). I wish to find, given a range of values [x, y], all indices of values (i) for which an index j exists such that: j>i and x <= a[j]-a[i] <= y Or simply put, find values in which exists a “forward difference” within a given range.

The output is a Boolean array of length a.Length. Since the array is sorted all forward differences, x and y are positive.

The best I’ve managed to do is start from each index looking at the subarray in front of it and perform a binary search for x+a[i] and check if a[j]<=y+a[i]. I think this is O(n log n). Is there a better approach? Or something I can do to speed things up.

I should note that eventually I want to perform the search for many such ranges [x,y] over the same array a, but the number of ranges is very much smaller than the length of the array (4-6 orders of magnitude smaller) - therefore I’m far more concerned with the complexity of the search.

Example:

a= 0, 1, 46, 100, 185, 216, 285

with range x,y=[99,101] should return:

[true, true, false, false, true, false, false]

For only values 0,1 and 185 have a forward difference within the range.

Code from memory, might have some bugs:

int bin_search_closesmaller(int arr[], int key, int low, int high)
{
    if (low > high) return high;
    int mid = (high - low)/2;
    if (arr[mid] > key) return bin_search_closesmaller(arr, key, low, mid - 1);
    if (arr[mid] < key) return bin_search_closesmaller(arr, key, mid + 1, high);
    return mid;
}

bool[] findDiffs(int[] a, int x, int y)
{
    bool[] result = new bool[a.Length];
    for(int i=0; i<a.Length-1;i++)
    {
        int idx=bin_search_closesmaller(a, y+a[i], i+1, a.Length-1);
        if (idx==-1) continue;
        if (a[idx]-a[i] >= x) result[i]=true;
    }
}

Thanks!

like image 935
AsaridBeck91 Avatar asked Feb 18 '18 09:02

AsaridBeck91


People also ask

How do you find the difference between all elements in an array?

Represent the array contents by an array of size n+1 with element i set to 1 where there is a value i in the array. Then use FFT to convolve the array with itself - there is a difference Ai - Aj = k where the kth element of the convolution is non-zero.

How do you find the maximum difference in sorted arrays?

Approach used in the below program is as follows Start the loop, from the second element till last element index of array. If the calculated difference between Arr[i+1]-Arr[i]>MaxD, update MaxD . Continue this till we reach the second last element index. Print the result MaxD as maximum adjacent element difference.


2 Answers

Make two indexes left and right and walk through array. Right index moves until it goes out of range for current left one, then check whether previous element is in range. Indexes move only forward, so algorithm is linear

 right=2
 for left = 0 to n-1:
    while A[right] < A[left] + MaxRangeValue
       right++
    Result[left] =  (A[right - 1] <= A[left] + MinRangeValue)

Another point of view on this algorithm:
-while difference is too low, increment right
-while difference is too high, increment left

like image 57
MBo Avatar answered Oct 16 '22 22:10

MBo


As long as the input array is sorted, there is a linear solution to the problem. The key is to use two indexes to traverse of the array a.

bool[] findDiffs(int[] a, int x, int y)
{
  bool[] result = new boolean[a.Length];
  int j = 0;

  for (int i = 0; i < a.Length; ++i) {
    while (j < a.Length && a[j] - a[i] < x) {
      ++j;
    }
    if (j < a.Length) {
      result[i] = a[j] - a[i] <= y;
    }
  }

  return result;
}

With a = [0,100,1000,1100] and (x,y) = (99,100):

i = 0, j = 0 => a[j] - a[i] = 0 < x=99     => ++j
i = 0, j = 1 => a[j] - a[i] = 100 <= y=100 => result[i] = true; ++i
i = 1, j = 1 => a[j] - a[i] = 0 < x=99     => ++j
i = 1, j = 2 => a[j] - a[i] = 900 > y=100  => result[i] = false; ++i
i = 2, j = 2 => a[j] - a[i] = 0 <= x=99    => ++j
i = 2, j = 3 => a[j] - a[i] = 100 <= y=100 => result[i] = true; ++i
i = 3, j = 3 => a[j] - a[i] = 0 <= x=99    => exit loop
like image 42
Alexandre Dupriez Avatar answered Oct 16 '22 21:10

Alexandre Dupriez