Find a Peak Element II

medium

You are given an m x n grid of integers mat (0-indexed). A cell is a peak if its value is strictly greater than each of its four edge-sharing neighbors — up, down, left, and right.

Two guarantees make life easier:

  • No two adjacent cells are ever equal, so comparisons never tie.
  • Imagine the whole grid is wrapped in an invisible border of -1 cells — a border cell only has to beat the neighbors that actually exist inside the grid.

Return the position of any peak as a length-2 array [i, j]. If the grid contains several peaks, any one of them is a correct answer.

Your algorithm must run in O(m log n) or O(n log m) time — a full scan of the grid is too slow in spirit, even if it passes small inputs.

Hints

You need any peak, not the tallest one. Does an answer always exist? Think about what happens if you keep stepping to a bigger neighbor.
Pick the middle row and find its maximum. That cell already beats its left and right neighbors — only up and down remain to check.
Compare the middle row's maximum with the cell directly below it. If below is bigger, a peak must exist in the bottom half; otherwise the top half. Binary search the rows: O(n log m).

Common doubts

You are not chasing one specific peak; you only need to keep some peak inside the search range. The row max beats its row neighbors for free, and the up/down comparison proves which half of the rows must contain a peak — possibly a different one than you started near, and that is fine.
Binary search never needed sortedness — it needs a test that reliably tells you which half contains an answer. Here the test is comparing the middle row's maximum with the cell below it. Sorted arrays are just the most familiar special case.
It makes every comparison strict, so there is always a clear uphill direction or you are at a peak. With ties allowed, a plateau could hide the peak on the discarded side and the halving argument would break.
Each step strictly increases the value and the grid is finite, so the walk cannot go on forever. Wherever it stops, no neighbor is bigger — by definition, a peak.

Interview follow-ups

Yes — binary search the columns instead: find the max of the middle column and compare it with the cell to its right. Prefer whichever halves the longer dimension: binary search rows when m >= n, columns otherwise, giving O(min(m,n) · log max(m,n)).
It is the same decider lifted a dimension: in 1-D you compare mid with mid+1 and keep the uphill half; in 2-D you first collapse a row to its maximum, then make the identical up/down comparison.
Plateaus appear and the halving proof collapses — a flat middle row tells you nothing about which side hides a peak. In the worst case you must inspect nearly every cell, so O(m·n) becomes unavoidable.
It is correct but only bounded by O(m·n) — the walk can snake through most of the grid. It is a great existence proof and a nice warm-up answer, but it does not meet the required complexity.

Fun facts

  • Peak finding is a celebrated opening lecture in MIT's algorithms course — it is often the very first example students see of binary search working on completely unsorted data.
  • The decider trick here — collapse a row to one representative, then compare across rows — reappears in matrix medians, 2-D matrix search, and even in gradient-ascent intuition for optimization.
  • The greedy walk-uphill argument is a discrete cousin of hill climbing in AI: guaranteed to terminate at a local optimum, with no promise it is the global one.

Asked at

GoogleAmazonMicrosoftUber
Frequently Sometimes Occasionally
Example 1
Input: mat = [[1,4],[3,2]]
Output: [0,1]
Both 4 (at [0,1]) and 3 (at [1,0]) are peaks — either answer is accepted.
Example 2
Input: mat = [[10,20,15],[21,30,14],[7,16,32]]
Output: [1,1]
30 beats 20, 21, 14, and 16, so [1,1] is a peak. 32 at [2,2] is also a peak, so [2,2] would be accepted too.
Constraints

- m == mat.length - n == mat[i].length - 1 <= m, n <= 500 - 1 <= mat[i][j] <= 10^5 - No two adjacent cells are equal.

Solve this problem →