0

So I'm trying to write a recursive algorithm which finds the min and max of an array. It basically splits the array into two n/2 pieces and finds the min and max recursively. Here's what I have right now:

class MinMax{
    public static Pair mmA(int lb, int ub, int[] a){
        int min;
        int max;
        int mid;
        if (ub == lb){
            return mmA(lb, ub, a);
        } else {
            mid = (lb + ub)/2;
            mmA (lb, mid, a);
            max = mid;
            mmA (mid+1, ub, a);
            min = mid;

            if (a[max] > a[min]){
                return mmA(lb, max, a);
            } else 
                return mmA(min, ub, a);
        }
    }

    public static void main(String[]args){
        int[] a = {4, 3, 5, 6, 7, 9, 1};
        mmA(0, 6, a);
    }
}

The problem is the method is not an int method so I can't just say max = mmA(lb, mid, a) because mmA is a Pair method while max is an int. I also can't just make Max and Min pair objects because then you wouldn't be able to compare them at the end. Here's the pair class:

class Pair {
   int alpha;   // the smaller one 
   int omega; // the bigger one 
   Pair ( int a, int o ) { alpha = a; omega = o; }
}

So how can I use this pair class along with my method to find the min and max.

Brian Risk
  • 1,244
  • 13
  • 23
Josh Susa
  • 173
  • 1
  • 7
  • 15
  • If you don't mind me asking, why do you wanna do that when you can get the min and max in O(n)? – abma Jan 29 '16 at 19:06
  • Possible duplicate of [Finding the max/min value in an array of primitives using Java](http://stackoverflow.com/questions/1484347/finding-the-max-min-value-in-an-array-of-primitives-using-java) – Emily Mabrey Jan 29 '16 at 19:07
  • Is that related (part) of a Bucket Sort algorithm ? – Rafael Jan 29 '16 at 19:08
  • Updated the answer. Please take a look – Msp Jan 29 '16 at 19:50

4 Answers4

1

You can't. Because, this function will end up in an end-less loop.

if (ub == lb){
    return mmA(lb, ub, a);
}

Let's say ub = lb = 5. It will call mmA(5, 5, a) again. Which will in-turn call the same. And so on..

EDIT:

This should help,

public class Main {
    public static Pair mmA(int lb, int ub, int[] a) {
        int min, max, mid;
        Pair p1, p2;

        if (ub == lb) {
            return new Pair(a[lb], a[ub]);
        } else {
            mid = (lb + ub) / 2;
            p1 = mmA(lb, mid, a);
            p2 = mmA(mid + 1, ub, a);

            max = Math.max(p1.omega, p2.omega);
            min = Math.min(p1.alpha, p2.alpha);

            return new Pair(min, max);
        }
    }


    public static void main(String[] args) {
        int[] a = {4, 3, 5, 6, 7, 9, 1};
        Pair pair = mmA(0, 6, a);
        System.out.println("Max = " + pair.omega + " & Min = " + pair.alpha);
    }
}


class Pair {
    public int alpha;
    public int omega;

    Pair(int a, int o) {
        alpha = a;
        omega = o;
    }
}
Msp
  • 2,493
  • 2
  • 20
  • 34
  • Not an actual answer to the question, but a *very* good observation. +1 – Andreas Jan 29 '16 at 19:18
  • I would argue against your solution (rev. 2). If the input is empty, what should return value be? `Collections.min()` will throw `NoSuchElementException`. Or your could return `null`. Or use the new `Optional`. But returning a *bad* pair is not right, in my opinion. – Andreas Jan 29 '16 at 19:25
  • @Andreas : Made the changes – Msp Jan 29 '16 at 19:49
  • That seems to work quite well. The only thing I don't understand is the purpose of the class Pair. – Josh Susa Jan 29 '16 at 22:38
  • Because, since we are calculating both min and max in a single function, we need a container to store temporary values – Msp Jan 29 '16 at 22:40
  • Don't forget to upvote and accept the answer if it's fixes the problem – Msp Jan 29 '16 at 22:41
1

Since this seems to be an exercise in recursion, let me try to guide you under that pretext.

Your recursive method returns a pair, being the min and max values. You call it twice, by splitting the array in two. All good so far.

Now that you have two pairs (assuming you change code to actually assign return value to a variable), you just need to combine them. Let's say your Pair class is immutable, then you could add a method to Pair like this:

public Pair combine(Pair other) {
    int newAlpha = Math.min(this.alpha, other.alpha);
    int newOmega = Math.max(this.omega, other.omega);
    return new Pair(newAlpha, newOmega);
}

NOTE: Be aware that your recursion stop logic doesn't work, as described in answer by Msp.

Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • All the method is supposed to do is split the array into n/2 and n/2 parts and then find the min and max recursively. The first p[roblem I'm having with this is I don't know what I'm supposed to return in my mmA method. We also have to assume that the Pair class cannot be modified in any way. – Josh Susa Jan 29 '16 at 19:19
  • @JoshSusa You can do the combining logic outside of `Pair`, it would just make more sense, if you could add it to the class, but if not, just do the logic in your code. – Andreas Jan 29 '16 at 19:21
1

You need getters for the Pair class (or make alpha and omega attributes public):

class Pair {
   int alpha;   // the smaller one 
   int omega; // the bigger one 
   Pair ( int a, int o ) { alpha = a; omega = o; }
   getAlpha () { return alpha; }
   getOmega () { return omega; }
}

And you have to stop the recursion returning a Pair in the base case (lb = ub)

class MinMax{
    public static Pair mmA(int lb, int ub, int[] a){
        int min;
        int max;
        int mid;
        Pair pair1;
        Pair pair2;

        if (ub == lb){
            // Just one item, so min and max are the same
            return Pair(a[lb],a[ub]);
        } else {
            mid = (lb + ub)/2;
            pair1 = mmA (lb, mid, a);                
            pair2 = mmA (mid+1, ub, a);

            min = Math.min(pair1.getOmega(), pair2.getOmega());
            max = Math.max(pair1.getAlpha(), pair2.getAlpha());

            return new Pair(min, max);
        }
    }

    public static void main(String[]args){
        int[] a = {4, 3, 5, 6, 7, 9, 1};
        mmA(0, 6, a);
    }
}
ednincer
  • 931
  • 8
  • 15
0

The problem appears that you were never really returning anything and, as @Andreas said, you then aren't combining the results of what you returned.

Here I had to add an extra condition for when the upper index and lower index are adjacent (i.e. upper - lower = 1) or else an infinite loop would occur. Also, I changed your variable names to be more descriptive. I was finding myself getting lost reading it.

public class MinMax {

    public static void main(String[] args){
        int[] array = {4, 3, 5, 6, 7, 9, 1};
        Pair result = mmA(0, array.length - 1, array);
        System.out.println("min: " + result.alpha + ", max: " + result.omega);
    }

    public static Pair mmA(int lowerBound, int upperBound, int[] array){
        if (upperBound == lowerBound){
            return new Pair(array[lowerBound], array[upperBound]);
        }
        else if (upperBound - lowerBound == 1) {
            int localAlpha = Math.min(array[lowerBound], array[upperBound]);
            int localOmega= Math.max(array[lowerBound], array[upperBound]);
            return new Pair(localAlpha, localOmega);
        }
        else {
            int midIndex = (lowerBound + upperBound)/2;
            Pair pairA = mmA(lowerBound, midIndex, array);
            Pair pairB = mmA(midIndex, upperBound, array);
            int localAlpha = Math.min(pairA.alpha, pairB.alpha);
            int localOmega= Math.max(pairA.omega, pairB.omega);
            return new Pair(localAlpha, localOmega);
        }
    }

}

class Pair {
    int alpha;   // the smaller one
    int omega; // the bigger one
    Pair ( int alpha, int omega ) {
        this.alpha = alpha;
        this.omega = omega;
    }
}
Brian Risk
  • 1,244
  • 13
  • 23