There is an integer matrix which has the following features:
- The numbers in adjacent positions are different.
- The matrix has n rows and m columns.
- For all i < m, A[0][i] < A[1][i] && A[n - 2][i] > A[n - 1][i].
- For all j < n, A[j][0] < A[j][1] && A[j][m - 2] > A[j][m - 1].
We define a position P is a peek if A[j][i] > A[j+1][i] && A[j][i] > A[j-1][i] && A[j][i] > A[j][i+1] && A[j][i] > A[j][i-1].
Find a peak element in this matrix. Return the index of the peak.
Given a matrix:
[
[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]
]
return index of 41 (which is [1,1]
) or index of 24 (which is [2,2]
)
The matrix may contains multiple peeks, find any of them.
Solve it in O(n+m) time.
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?
http://www.lintcode.com/en/problem/find-peak-element-ii/
二分查找!
1 class Solution { 2 public: 3 /** 4 * @param A: An integer matrix 5 * @return: The index of the peak 6 */ 7 vector<int> findPeakII(vector<vector<int> > A) { 8 // write your code here 9 vector<int> res; 10 int left = 0, right = A.size() - 1; 11 while (left <= right) { 12 int mid = left + ((right - left) >> 1); 13 int col = findPeak(A[mid]); 14 if (A[mid][col] < A[mid+1][col]) { 15 left = mid + 1; 16 } else if (A[mid][col] < A[mid-1][col]) { 17 right = mid - 1; 18 } else { 19 return {mid, col}; 20 } 21 } 22 return res; 23 } 24 int findPeak(vector<int> &v) { 25 int res = 0; 26 for (int i = 1; i < v.size(); ++i) { 27 if (v[i] > v[res]) res = i; 28 } 29 return res; 30 } 31 };
下面是錯誤的,但是居然AC了,數據好弱啊。
這題跟楊氏矩陣有點像,可以使用楊氏矩陣的思想,因為題目已經說時了第二行第二列倒數第二行倒數第二列肯定比第一行第一列倒數第一行倒數第一列的元素大,那么我們只需從第二行第二列開始尋找,因為要找peek element,所以要跟四周元素比較,如果發現有比它大的元素,那么就移動到比它大的元素的坐標。如果有右側與下側都比它大,那么就移到更大的那一個元素那兒,這樣就可以保證下一個比當前元素大的元素只可能出現在右側或下側。因為我們只會向右或向下移動,所以最壞的情況就是移動到右下角,但時間復雜度還是O(N+M)。
1 class Solution { 2 public: 3 /** 4 * @param A: An integer matrix 5 * @return: The index of the peak 6 */ 7 bool isOK(vector<vector<int> > &A, int i, int j) { 8 if (i < 1 || i >= A.size() - 1 || j < 1 || j >= A[0].size() - 1) 9 return false; 10 return A[i][j] > A[i][j-1] && A[i][j] > A[i-1][j] 11 && A[i][j] > A[i][j+1] && A[i][j] > A[i+1][j]; 12 } 13 14 vector<int> findPeakII(vector<vector<int> > A) { 15 // write your code here 16 vector<int> res; 17 int i = 1, j = 1; 18 while (i < A.size() - 1 && j < A[0].size() - 1) { 19 if (isOK(A, i, j)) { 20 res.push_back(i); 21 res.push_back(j); 22 return res; 23 } else { 24 if (A[i+1][j] > A[i][j+1]) ++i; 25 else ++j; 26 } 27 } 28 return res; 29 } 30 };