Find Any Local Maximum in a 2D Matrix
Solve this Problem[row, col] of any peak — one is always guaranteed to exist.
Solve it in O(m log n) time by binary-searching over columns: find each candidate column's maximum, then let its left/right neighbors tell you which way to move — the same climbing idea as the 1D peak problem, one dimension up.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ matrix.length, matrix[0].length ≤ 100 - ◆
1 ≤ matrix[i][j] ≤ 10⁵ - ◆
No two cells that share an edge have equal values - ◆
If multiple peaks exist, returning the position of any one of them is accepted
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public int[] findPeakGrid(int[][] mat) { |
| 3 | int rows = mat.length, cols = mat[0].length; |
| 4 | int loCol = 0, hiCol = cols - 1; |
| 5 | while (loCol <= hiCol) { |
| 6 | int midCol = loCol + (hiCol - loCol) / 2; |
| 7 | int maxRow = 0; |
| 8 | for (int i = 1; i < rows; i++) { |
| 9 | if (mat[i][midCol] > mat[maxRow][midCol]) maxRow = i; |
| 10 | } |
| 11 | int left = midCol > 0 ? mat[maxRow][midCol - 1] : -1; |
| 12 | int right = midCol < cols - 1 ? mat[maxRow][midCol + 1] : -1; |
| 13 | if (mat[maxRow][midCol] > left && mat[maxRow][midCol] > right) { |
| 14 | return new int[]{maxRow, midCol}; |
| 15 | } else if (left > mat[maxRow][midCol]) { |
| 16 | hiCol = midCol - 1; |
| 17 | } else { |
| 18 | loCol = midCol + 1; |
| 19 | } |
| 20 | } |
| 21 | return new int[]{-1, -1}; |
| 22 | } |
| 23 | } |
| 24 |
2504Binary search on columns [0, 4]: for each candidate column, find its maximum value, then check whether that cell also beats its left/right neighbors.
Approach & Solutions
Brute Force — Check Every Cell's 4 Neighbors
BruteFor every cell, compare it against its up/down/left/right neighbors (treating a missing neighbor at the matrix's edge as -1, which any positive value beats). The first cell that beats all four is a peak. Correct, but it checks every cell instead of using comparisons to steer toward one directly.
O(m × n)O(1)1class Solution {
2 public int[] findPeakGrid(int[][] mat) {
3 int rows = mat.length, cols = mat[0].length;
4 for (int i = 0; i < rows; i++) {
5 for (int j = 0; j < cols; j++) {
6 int up = i > 0 ? mat[i - 1][j] : -1;
7 int down = i < rows - 1 ? mat[i + 1][j] : -1;
8 int left = j > 0 ? mat[i][j - 1] : -1;
9 int right = j < cols - 1 ? mat[i][j + 1] : -1;
10 if (mat[i][j] > up && mat[i][j] > down && mat[i][j] > left && mat[i][j] > right) {
11 return new int[]{i, j};
12 }
13 }
14 }
15 return new int[]{-1, -1};
16 }
17}Optimal — Binary Search on Columns
OptimalBinary-search over columns instead of cells. For a candidate column, find its maximum value (scan that one column, O(m)). That cell already beats its up and down neighbors by construction — it only remains to check left and right. If its left neighbor is bigger, a taller peak must exist somewhere in the columns to the left (the same argument as the 1D peak problem, applied column-wise) — search there. Same for the right. Otherwise it's a genuine 2D peak.
O(m log n)O(1)1class Solution {
2 public int[] findPeakGrid(int[][] mat) {
3 int rows = mat.length, cols = mat[0].length;
4 int loCol = 0, hiCol = cols - 1;
5 while (loCol <= hiCol) {
6 int midCol = loCol + (hiCol - loCol) / 2;
7 int maxRow = 0;
8 for (int i = 1; i < rows; i++) {
9 if (mat[i][midCol] > mat[maxRow][midCol]) maxRow = i;
10 }
11 int left = midCol > 0 ? mat[maxRow][midCol - 1] : -1;
12 int right = midCol < cols - 1 ? mat[maxRow][midCol + 1] : -1;
13 if (mat[maxRow][midCol] > left && mat[maxRow][midCol] > right) {
14 return new int[]{maxRow, midCol};
15 } else if (left > mat[maxRow][midCol]) {
16 hiCol = midCol - 1;
17 } else {
18 loCol = midCol + 1;
19 }
20 }
21 return new int[]{-1, -1};
22 }
23}