A peak element in a 2D grid is an element that is strictly greater than all of its adjacent neighbors to the left, right, top, and bottom.
Given a 0-indexed m x n
matrix mat
where no two adjacent cells are equal, find any peak element mat[i][j]
and return the length 2 array [i,j]
.
You may assume that the entire matrix is surrounded by an outer perimeter with the value -1
in each cell.
You must write an algorithm that runs in O(m log(n))
or O(n log(m))
time.
Example 1:
Input: mat = [[1,4],[3,2]] Output: [0,1] Explanation: Both 3 and 4 are peak elements so [1,0] and [0,1] are both acceptable answers.
Example 2:
Input: mat = [[10,20,15],[21,30,14],[7,16,32]] Output: [1,1] Explanation: Both 30 and 32 are peak elements so [1,1] and [2,2] are both acceptable answers.
Constraints:
m == mat.length
n == mat[i].length
1 <= m, n <= 500
1 <= mat[i][j] <= 105
- No two adjacent cells are equal.
Let
The problem asks us to find a peak, and the time complexity should be
We consider the maximum value of the
If
Why is the above method correct? We can prove it by contradiction.
If
For the case where
Therefore, we can use binary search to find the peak.
We perform binary search on the rows of the matrix, initially with the search boundaries
The time complexity is
class Solution:
def findPeakGrid(self, mat: List[List[int]]) -> List[int]:
l, r = 0, len(mat) - 1
while l < r:
mid = (l + r) >> 1
j = mat[mid].index(max(mat[mid]))
if mat[mid][j] > mat[mid + 1][j]:
r = mid
else:
l = mid + 1
return [l, mat[l].index(max(mat[l]))]
class Solution {
public int[] findPeakGrid(int[][] mat) {
int l = 0, r = mat.length - 1;
int n = mat[0].length;
while (l < r) {
int mid = (l + r) >> 1;
int j = maxPos(mat[mid]);
if (mat[mid][j] > mat[mid + 1][j]) {
r = mid;
} else {
l = mid + 1;
}
}
return new int[] {l, maxPos(mat[l])};
}
private int maxPos(int[] arr) {
int j = 0;
for (int i = 1; i < arr.length; ++i) {
if (arr[j] < arr[i]) {
j = i;
}
}
return j;
}
}
class Solution {
public:
vector<int> findPeakGrid(vector<vector<int>>& mat) {
int l = 0, r = mat.size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
int j = distance(mat[mid].begin(), max_element(mat[mid].begin(), mat[mid].end()));
if (mat[mid][j] > mat[mid + 1][j]) {
r = mid;
} else {
l = mid + 1;
}
}
int j = distance(mat[l].begin(), max_element(mat[l].begin(), mat[l].end()));
return {l, j};
}
};
func findPeakGrid(mat [][]int) []int {
maxPos := func(arr []int) int {
j := 0
for i := 1; i < len(arr); i++ {
if arr[i] > arr[j] {
j = i
}
}
return j
}
l, r := 0, len(mat)-1
for l < r {
mid := (l + r) >> 1
j := maxPos(mat[mid])
if mat[mid][j] > mat[mid+1][j] {
r = mid
} else {
l = mid + 1
}
}
return []int{l, maxPos(mat[l])}
}
function findPeakGrid(mat: number[][]): number[] {
let [l, r] = [0, mat.length - 1];
while (l < r) {
const mid = (l + r) >> 1;
const j = mat[mid].indexOf(Math.max(...mat[mid]));
if (mat[mid][j] > mat[mid + 1][j]) {
r = mid;
} else {
l = mid + 1;
}
}
return [l, mat[l].indexOf(Math.max(...mat[l]))];
}
impl Solution {
pub fn find_peak_grid(mat: Vec<Vec<i32>>) -> Vec<i32> {
let mut l: usize = 0;
let mut r: usize = mat.len() - 1;
while l < r {
let mid: usize = (l + r) >> 1;
let j: usize = mat[mid]
.iter()
.position(|&x| x == *mat[mid].iter().max().unwrap())
.unwrap();
if mat[mid][j] > mat[mid + 1][j] {
r = mid;
} else {
l = mid + 1;
}
}
let j: usize = mat[l]
.iter()
.position(|&x| x == *mat[l].iter().max().unwrap())
.unwrap();
vec![l as i32, j as i32]
}
}