stefple
stefple

Reputation: 558

2D Peak finding algorithm JAVA, found one example, but cant code it

I am trying to rebuild this algorithm:
http://courses.csail.mit.edu/6.006/fall10/lectures/lec02.pdf
(Page 14 "Algorithm II")
(found this with google, unfortunatly i am not at MIT :) and this is not homework)

Which is:

•Pick middle column (j=m/2)
•Find global maximum a=A[i,m/2]in that column
    (and quit if m=1)
•Compare a to b=A[i,m/2-1]and c=A[i,m/2+1]
•If b>a   then recurse on left columns
•Else, if c>a   then recurse on right columns
•Else a is a 2D peak!  

What i have is this:

trimmed is a vector which holds my frequencies of size (blockSizeSmall-minBlockSize).

So its a 2D Matrix with trimmed.size() columns and (blockSizeSmall-minBlockSize) rows.

For simpliciticy i save the peaks in 2 int vectors vector<int> peaksrow and peakscolumn.

Whats wrong there ?
I dont get what

"Find global maximum a=A[i,m/2]in that column (and quit if m=1)"

should result in.

    public void findPeaks() {
        for (int column = trimmed.size() / 2; column < trimmed.size();) {
            int globalmax = 0;
            for (int row = 0; row < (blockSizeSmall - minBlockSize); row++) {
                if (trimmed.elementAt(column).reducedFreqs[row] > globalmax) {
                    globalmax = row; 
                    //find globalmax in row
                }
            }
            if (globalmax == 0) {
                break; //<- ???
            } else {
                if (column - 1 >= 0 && column + 1 < trimmed.size()) {
                //stay in bounds
                    if (trimmed.elementAt(column - 1).reducedFreqs[globalmax] > globalmax) {
                        column--; 
                        //if element at left side is > globalmax, recurse on column--;

                    } else if (trimmed.elementAt(column + 1).reducedFreqs[globalmax] > globalmax) {
                        column++; 
                        //if element at right side is > globalmax, recurse on column++;

                    } else { 
                        //if globalmax is higher than right or left element i have a peak
                        peaksrown.add(globalmax);
                        peakscolumnn.add(column);
                        Log.e(TAG, "" + peaksrown.size());
                    }
                }else{
                //what to do when out of bounds ?? break ??
                //if i break here, how can i be sure the algorithm 
                //went to both sides(column=0 and column=max) ??
                //just tried with break here, still infinit loop
                }
            }
        }
    }

It just loops endless.

Upvotes: 3

Views: 3428

Answers (2)

Neal Young
Neal Young

Reputation: 159

I think this algorithm has a subtle bug. A local maximum in the right half is not necessarily a local maximum in the entire array (e.g., when the local max in the right half is on its left border). So, although there is a local max (of the entire array) in the right half (assuming right is higher), the recursive call will not necessarily find it.

Upvotes: 1

svinja
svinja

Reputation: 5576

You don't seem to understand the concept of recursion so I would advise you look it up. Here's an algorithm in C# for reference, not tested beyond the one example in the paper but it should work. I ignored the "and quit if m=1" part as I don't think that's needed. Note how the function Peak() calls itself from within itself, but with changed parameters.

    static void Peak(int[,] map, int left, int right)
    {
        // calculate middle column
        int column = (right + left) / 2;


        // get max row in column
        int arow = 0;
        for (int row = 0; row < map.GetLength(0); row++)
            if (map[row, column] > map[arow, column])
                arow = row;

        int a = map[arow, column];

        // get left value
        int b = 0;
        if (column - 1 >= left) b = map[arow, column - 1];
        // get right value
        int c = 0;
        if (column + 1 <= right) c = map[arow, column + 1];

        // if left is higher, recurse left
        if (b > a) Peak(map, left, column - 1);
        // else if right is higher, recurse right
        else if (c > a) Peak(map, column + 1, right);
        // else, peak
        else Console.WriteLine("Peak: " + arow + " " + column + " " + a);
    }

    static void Main(string[] args)
    {
        int[,] map = { {12, 8, 5},
                       {11, 3, 6 },
                       {10, 9, 2 },
                       { 8, 4, 1 } };
        Peak(map, 0, 2);
        Console.ReadLine();
    }

Upvotes: 3

Related Questions