2

I have a large array. I have some Java code for identifying indices for start and end points for a subset/slice of that large array. The only information items that I need to retrieve from the selected subsection of the array are the indices and values of the local maximum and minimum. What is the fastest (and least memory intensive) way that I can find a max and min within the specified range?

Here is a start of what I need in terms of code:

// Step One: declare new array and populate it
pts = new double[5000];
for (int i = 0; i < 5000; i++){ pts[i] = (value assigned by extraneous process);}
// Step Two: slice out section between indices 3600 and 3750
    // what code do I write here?
// Step Three: find max value in the sliced section and return its index
    // what code to I write here?
Mark Elliot
  • 75,278
  • 22
  • 140
  • 160
CodeMed
  • 9,527
  • 70
  • 212
  • 364

4 Answers4

4

Just iterate over the desired range and record maximum and minimum seen values:

double max = Double.NEGATIVE_INFINITY;
double min = Double.POSITIVE_INFINITY;
int minIndex = -1;
int maxIndex = -1;
for(int k = 3600; k < 3750; k++){
    if(max < pts[k]){
        max = pts[k];
        maxIndex = k;
    }else if(min > pts[k]){
        min = pts[k];
        minIndex = k;
    }
}
Mark Elliot
  • 75,278
  • 22
  • 140
  • 160
3

If it's not necessary to create a copy of the array for your slice, you can essentially do steps 2 and 3 in one fell swoop:

double max = pts[3600]; //the value of the first element in the slice
int maxIndex = 3600; //keep track of the index as you go. Assume at first
                     //that it is the first index of the slice
for(int i=3601; i<=3750; i++){
  if(pts[i] > max){  //you have encountered a larger element. Update the maxes
    max = pts[i];
    maxIndex = i;
  }
}
System.out.println("The max is " + max + " and occurred at index " + maxIndex);

(sorry for any syntax errors, I've been messing around with Scala and the grammar is a little different)

Dylan
  • 13,645
  • 3
  • 40
  • 67
  • how are you defining max? You declare it in the first line as an array with 3600 elements, but then you use it as a single value in lines 4 and 5. – CodeMed Jul 07 '11 at 02:06
  • No, in the first line, I am declaring max, and setting it to the value at index 3600 of the pts array. I could also have set it to Double.MIN_VALUE and it probably wouldn't have any effect on the overall code. – Dylan Jul 07 '11 at 02:07
  • 1
    @Dylan: Double.MIN_VALUE is not the *lowest* value a double can represent, but rather the smallest (as in closest-to-zero) value, if you want the *lowest* value, that's negative infinity: `Double.NEGATIVE_INFINITY` (many a programmer has been tripped up by this small but hazardous error) – Mark Elliot Jul 07 '11 at 02:15
  • @Mark: Thanks for the tip. I guess I'm too used to using the Integer version – Dylan Jul 07 '11 at 02:17
1

Have a loop that goes over the selected subsection once.

In the loop, adjust the values of four variables maxValue, maxIndex, minValue, minIndex as you find new maxima or minima.

After the loop, you will have the maximum and minimum and their positions.

No extra memory needed, linear performance (just one pass over the selected part of the array).

Thilo
  • 257,207
  • 101
  • 511
  • 656
1

If you're going to do this a lot, you could increase performance by keeping track of the maxima / minima at different scales.

For instance if you keep a list for every 20 rows, and you want to check the range 55 - 184, you'd only need to check 5 values (55-59), then 6 values from 60-179, then 4 values from 180 - 184, so that's 15 checks rather than 130, a 20x speed increase.

Of course, you'd need to mark your buckets as changed when the array changes and periodically update them.

Luigi Plinge
  • 50,650
  • 20
  • 113
  • 180