Peak Finding: 1D and 2D
http://courses.csail.mit.edu/6.006/fall11/notes.shtml
http://courses.csail.mit.edu/6.006/fall10/notes.shtml
T(n) = T(n/2) + O(1)
Divide and Conquer
• Very powerful design tool:
– Divide input into multiple disjoint parts
– Conquer each of the parts separately
(using recursive call)
• Occasionally, we need to combine results
from different calls
1D
Consider the middle element of the array
and compare with neighbors
– If A[n/2-1]>A[n/2]
then search for a peak among A[1]… A[n/2-1]
– Else, if A[n/2]<A[n/2+1]
then search for a peak among A[n/2]… A[n]
– Else A[n/2] is a peak!
(since A[n/2-1]≤A[n/2] and A[n/2] ≥A[n/2+1] )
2D
Algorithm I:
– For each column j, find its global maximum B[j]
– Apply 1D peak finder to find a peak (say B[j])
of B[1...m]
O(n*m)
Algorithm II => O(nlogm)• 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!
Proof (by contradiction):
T(n,m)= T(n,m/2) + O(n) = O(nlogm)
T(n,n)= (n) + (n) +...+ (n) = (nlog m)
http://stackoverflow.com/questions/10531720/2d-peak-finding-algorithm-java-found-one-example-but-cant-code-it
https://github.com/fekberg/Algorithms/blob/master/Peak%20Finding/Peak%20Finding/Program.cs
linear-time O(n + m)Reading only O(n + m) elements, reduce an array of n*m candidates to an array of n/2*m/2 candidates
http://stackoverflow.com/questions/23120300/2d-peak-finding-algorithm-in-on-worst-case-time
http://ideone.com/K3ggGm
Code:
https://gist.github.com/tiraeth/1306602
http://www.geeksforgeeks.org/find-a-peak-in-a-given-array/
http://cresspahl.blogspot.com/2012/03/simple-algorithm-for-2d-peakfinding.html
http://stackoverflow.com/questions/9587173/algorithm-to-find-peaks-in-2d-array
http://courses.csail.mit.edu/6.006/fall11/notes.shtml
http://courses.csail.mit.edu/6.006/fall10/notes.shtml
T(n) = T(n/2) + O(1)
Divide and Conquer
• Very powerful design tool:
– Divide input into multiple disjoint parts
– Conquer each of the parts separately
(using recursive call)
• Occasionally, we need to combine results
from different calls
1D
Consider the middle element of the array
and compare with neighbors
– If A[n/2-1]>A[n/2]
then search for a peak among A[1]… A[n/2-1]
– Else, if A[n/2]<A[n/2+1]
then search for a peak among A[n/2]… A[n]
– Else A[n/2] is a peak!
(since A[n/2-1]≤A[n/2] and A[n/2] ≥A[n/2+1] )
2D
Algorithm I:
– For each column j, find its global maximum B[j]
– Apply 1D peak finder to find a peak (say B[j])
of B[1...m]
O(n*m)
Algorithm II => O(nlogm)• 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!
Proof (by contradiction):
T(n,m)= T(n,m/2) + O(n) = O(nlogm)
T(n,n)= (n) + (n) +...+ (n) = (nlog m)
http://stackoverflow.com/questions/10531720/2d-peak-finding-algorithm-java-found-one-example-but-cant-code-it
https://github.com/fekberg/Algorithms/blob/master/Peak%20Finding/Peak%20Finding/Program.cs
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);
}
linear-time O(n + m)Reading only O(n + m) elements, reduce an array of n*m candidates to an array of n/2*m/2 candidates
http://stackoverflow.com/questions/23120300/2d-peak-finding-algorithm-in-on-worst-case-time
http://ideone.com/K3ggGm
- int findPeakLinearTime(int[][] arr){
- int rows = arr.length;
- int cols = arr[0].length;
- return kthLinearColumn(arr, 0, cols-1, 0, rows-1);
- }
- // helper function that splits on the middle Column
- int kthLinearColumn(int[][] arr, int loCol, int hiCol, int loRow, int hiRow){
- if(loCol==hiCol){
- int max = arr[loRow][loCol];
- int foundRow = loRow;
- for(int row = loRow; row<=hiRow; row++){
- if(max < arr[row][loCol]){
- max = arr[row][loCol];
- foundRow = row;
- }
- }
- if(!correctPeak(arr, foundRow, loCol)){
- }
- return max;
- }
- int midCol = (loCol+hiCol)/2;
- int max = arr[loRow][loCol];
- for(int row=loRow; row<=hiRow; row++){
- }
- boolean centralMax = true;
- boolean rightMax = false;
- boolean leftMax = false;
- if(midCol-1 >= 0){
- for(int row = loRow; row<=hiRow; row++){
- if(arr[row][midCol-1] > max){
- max = arr[row][midCol-1];
- centralMax = false;
- leftMax = true;
- }
- }
- }
- if(midCol+1 < M){
- for(int row=loRow; row<=hiRow; row++){
- if(arr[row][midCol+1] > max){
- max = arr[row][midCol+1];
- centralMax = false;
- leftMax = false;
- rightMax = true;
- }
- }
- }
- if(centralMax) return max;
- if(rightMax) return kthLinearRow(arr, midCol+1, hiCol, loRow, hiRow);
- if(leftMax) return kthLinearRow(arr, loCol, midCol-1, loRow, hiRow);
- }
- // helper function that splits on the middle
- int kthLinearRow(int[][] arr, int loCol, int hiCol, int loRow, int hiRow){
- if(loRow==hiRow){
- int ans = arr[loCol][loRow];
- int foundCol = loCol;
- for(int col=loCol; col<=hiCol; col++){
- if(arr[loRow][col] > ans){
- ans = arr[loRow][col];
- foundCol = col;
- }
- }
- if(!correctPeak(arr, loRow, foundCol)){
- }
- return ans;
- }
- boolean centralMax = true;
- boolean upperMax = false;
- boolean lowerMax = false;
- int midRow = (loRow+hiRow)/2;
- int max = arr[midRow][loCol];
- for(int col=loCol; col<=hiCol; col++){
- }
- if(midRow-1>=0){
- for(int col=loCol; col<=hiCol; col++){
- if(arr[midRow-1][col] > max){
- max = arr[midRow-1][col];
- upperMax = true;
- centralMax = false;
- }
- }
- }
- if(midRow+1<N){
- for(int col=loCol; col<=hiCol; col++){
- if(arr[midRow+1][col] > max){
- max = arr[midRow+1][col];
- lowerMax = true;
- centralMax = false;
- upperMax = false;
- }
- }
- }
- if(centralMax) return max;
- if(lowerMax) return kthLinearColumn(arr, loCol, hiCol, midRow+1, hiRow);
- if(upperMax) return kthLinearColumn(arr, loCol, hiCol, loRow, midRow-1);
- }
- int[][] randomArray(){
- int[][] arr = new int[N][M];
- for(int i=0; i<N; i++)
- for(int j=0; j<M; j++)
- return arr;
- }
- boolean correctPeak(int[][] arr, int row, int col){//Function that checks if arr[row][col] is a peak or not
- if(row-1>=0 && arr[row-1][col]>arr[row][col]) return false;
- if(row+1<N && arr[row+1][col]>arr[row][col]) return false;
- if(col-1>=0 && arr[row][col-1]>arr[row][col]) return false;
- if(col+1<M && arr[row][col+1]>arr[row][col]) return false;
- return true;
- }
- }
Code:
https://gist.github.com/tiraeth/1306602
http://www.geeksforgeeks.org/find-a-peak-in-a-given-array/
http://cresspahl.blogspot.com/2012/03/simple-algorithm-for-2d-peakfinding.html
http://stackoverflow.com/questions/9587173/algorithm-to-find-peaks-in-2d-array