Find Peak Element II
update Mar 6, 2021
Given an integer matrix A which has the following features :
The numbers in adjacent positions are different.
The matrix has n rows and m columns, n and m will not less than 3.
For all i < n, A[i][0] < A[i][1] && A[i][m - 2] > A[i][m - 1].
For all j < m, A[0][j] < A[1][j] && A[n - 2][j] > A[n - 1][j]
We define a position [i, j] is a peak if:
A[i][j] > A[i + 1][j] &&
A[i][j] > A[i - 1][j] &&
A[i][j] > A[i][j + 1] &&
A[i][j] > A[i][j - 1]
Find a peak element in this matrix. Return the index of the peak. Example
Example 1:
Input:
[[1, 2, 3, 6, 5],
[16,41,23,22, 6],
[15,17,24,21, 7],
[14,18,19,20,10],
[13,14,11,10, 9]]
Output: [1,1] Explanation: [2,2] is also acceptable.
The element at [1,1] is 41, greater than every element adjacent to it.
Example 2:
Input:
[[1, 5, 3],
[4,10, 9],
[2, 8, 7] ]
Output: [1,1] Explanation: There is only one peek.
Challenge
Solve it in O(n+m) time.
If you come up with an algorithm that you thought it is O(nlogm) or O(mlogn), can you prove it is actually O(n+m) or propose a similar but O(n+m) algorithm? Notice
Guarantee that there is at least one peak, and if there are multiple peaks, return any one of them.
Basic Idea
注意到这道题中所给矩阵的每一行每一列都保证有山峰,并且保证peak存在。那么理论上我们只需要从某个位置出发,一直向高的地方走,就一定可以找到山峰。
于是我们可以利用二分法,对列进行二分,每次找出该列最大的元素,然后检查这个元素的左右两个元素,如果遇到比该元素更大的,那么就向那边继续进行二分。
Java Code
public class Solution {
public List<Integer> findPeakII(int[][] A) {
int R = A.length, C = A[0].length;
int left = 1, right = C - 2;
// 二分列,也可以二分行
while (left + 1 < right) {
int midCol = left + (right - left) / 2;
int maxRow = getMaxRow(A, midCol);
if (A[maxRow][midCol] < A[maxRow][midCol - 1]) {
right = midCol;
} else if (A[maxRow][midCol] < A[maxRow][midCol + 1]) {
left = midCol;
} else {
return Arrays.asList(maxRow, midCol);
}
}
int maxRowLeft = getMaxRow(A, left);
int maxRowRight = getMaxRow(A, right);
if (A[maxRowLeft][left] > A[maxRowRight][right]) {
return Arrays.asList(maxRowLeft, left);
} else {
return Arrays.asList(maxRowRight, right);
}
}
// 找到输入列中最大元素所在的行的index
private int getMaxRow(int[][] arr, int col) {
int maxIndex = 0, maxValue = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; ++i) {
if (arr[i][col] > maxValue) {
maxValue = arr[i][col];
maxIndex = i;
}
}
return maxIndex;
}
}
Last updated