Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ algorithm to find 'maximal difference' in an array

I am asking for your ideas regarding this problem:

I have one array A, with N elements of type double (or alternatively integer). I would like to find an algorithm with complexity less than O(N2) to find:

    max A[i] - A[j]

For 1 < j <= i < n. Please notice that there is no abs(). I thought of:

  • dynamic programming
  • dichotomic method, divide and conquer
  • some treatment after a sort keeping track of indices

Would you have some comments or ideas? Could you point at some good ref to train or make progress to solve such algorithm questions?

like image 647
kiriloff Avatar asked Dec 13 '22 01:12

kiriloff


2 Answers

Make three sweeps through the array. First from j=2 up, filling an auxiliary array a with minimal element so far. Then, do the sweep from the top i=n-1 down, filling (also from the top down) another auxiliary array, b, with maximal element so far (from the top). Now do the sweep of the both auxiliary arrays, looking for a maximal difference of b[i]-a[i].

That will be the answer. O(n) in total. You could say it's a dynamic programming algorithm.

edit: As an optimization, you can eliminate the third sweep and the second array, and find the answer in the second sweep by maintaining two loop variables, max-so-far-from-the-top and max-difference.

As for "pointers" about how to solve such problems in general, you usually try some general methods just like you wrote - divide and conquer, memoization/dynamic programming, etc. First of all look closely at your problem and concepts involved. Here, it's maximum/minimum. Take these concepts apart and see how these parts combine in the context of the problem, possibly changing order in which they're calculated. Another one is looking for hidden order/symmetries in your problem.

Specifically, fixing an arbitrary inner point k along the list, this problem is reduced to finding the difference between the minimal element among all js such that 1<j<=k, and the maximal element among is: k<=i<n. You see divide-and-conquer here, as well as taking apart the concepts of max/min (i.e. their progressive calculation), and the interaction between the parts. The hidden order is revealed (k goes along the array), and memoization helps save the interim results for max/min values.

The fixing of arbitrary point k could be seen as solving a smaller sub-problem first ("for a given k..."), and seeing whether there is anything special about it and it can be abolished - generalized - abstracted over.

There is a technique of trying to formulate and solve a bigger problem first, such that an original problem is a part of this bigger one. Here, we think of find all the differences for each k, and then finding the maximal one from them.

The double use for interim results (used both in comparison for specific k point, and in calculating the next interim result each in its direction) usually mean some considerable savings. So,

  • divide-and-conquer
  • memoization / dynamic programing
  • hidden order / symmetries
  • taking concepts apart - seeing how the parts combine
  • double use - find parts with double use and memoize them
  • solving a bigger problem
  • trying arbitrary sub-problem and abstracting over it
like image 184
Will Ness Avatar answered Dec 31 '22 03:12

Will Ness


This should be possible in a single iteration. max(a[i] - a[j]) for 1 < j <= i should be the same as max[i=2..n](a[i] - min[j=2..i](a[j])), right? So you'd have to keep track of the smallest a[j] while iterating over the array, looking for the largest a[i] - min(a[j]). That way you only have one iteration and j will be less than or equal to i.

like image 42
Wormbo Avatar answered Dec 31 '22 03:12

Wormbo