If you come up with an algorithm that you thought it is O(n log m) or O(m log n), can you prove it is actually O(n+m) or propose a similar but O(n+m) algorithm?
public List<Integer> findPeakII(int[][] A) {
if (A == null || A.length == 0) {
return null;
}
int n = A.length; // x going down
int m = A[0].length; // y going right
// cut squre in half horizontally, so pass in true;
// then cut square in half, vertically to shrink the peak position.
return findInRange(1, 1, n - 2, m - 2, A, true);
}
private List<Integer> findInRange(int x1, int y1, int x2, int y2,
int[][] A, boolean horizontal) {
if (horizontal) { // cut square in half horizontally
int mid = x1 + (x2 - x1) / 2;
// use max Index to keep track of max elem's index in the row
int maxInd = y1;
for (int i = y1; i <= y2; i++) {// loop to find max
if (A[mid][i] > A[mid][maxInd]) {
maxInd = i;
}
}
if (A[mid][maxInd] < A[mid - 1][maxInd]) {
// the max elem in this row smaller than it's top,
// means peak elem can be found in upper half
// next time cut it vertically
return findInRange(x1, y1, mid - 1, y2, A, false);
} else if (A[mid][maxInd] < A[mid + 1][maxInd]) {
// the max elem in this row smaller than it's bottom,
// means peak elem can be found in lower half
// next time cut it vertically
return findInRange(mid + 1, y1, x2, y2, A, false);
} else { // the max elem is the peak;
return new ArrayList<Integer>(Arrays.asList(mid, maxInd));
}
} else { // cut square in half vertically
int mid = y1 + (y2 - y1) / 2;
int maxInd = x1;
for (int i = x1; i <= x2; i++) {
if (A[maxInd][mid] < A[i][mid]) {
maxInd = i;
}
}
if (A[maxInd][mid] < A[maxInd][mid - 1]) {
// the max elem in this col smaller than it's left,
// means peak can be found in the left half
return findInRange(x1, y1, x2, mid - 1, A, true);
} else if (A[maxInd][mid] < A[maxInd][mid + 1]) {
// the max elem in this col is smaller than it's right,
// means peak can be found in the right half
return findInRange(x1, mid + 1, x2, y2, A, true);
} else { // the max elem is the peak;
return new ArrayList<Integer>(Arrays.asList(maxInd, mid));
}
}
}