Question:數組
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:ide
For example,測試
Consider the following matrix:spa
[ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ]
Given target = 3, return true.指針
Solution:code
看到這個題目的第一想法是先對最右邊一列作二分查找,定位是在哪一行,而後在這一行作二分查找。時間複雜度是O(logm)+O(logn)=O(logm+logn)=O(log(m*n))。blog
這樣須要兩次二分查找,其實一次就能夠了。把二維數組轉化爲一維數組。從左向右,從上向下依次取出每一個元素,那麼這些元素是總體有序的,能夠看做一個一維數組,用二分查找解決。時間複雜度是O(log(m*n)),和上面的同樣。ci
開始實現這個二分查找代碼的時候,begin和end記錄的是兩個點,這樣代碼寫起來較複雜,見註釋中的代碼。後來begin和end改成轉化爲一維數組後的下標,這樣就簡單多了。代碼以下,在leetcode上測試經過了。leetcode
class Solution { public: bool searchMatrix(vector<vector<int> > &matrix, int target) { if (matrix.size() == 0) return false; int col_len = matrix[0].size(); int row_len = matrix.size(); int beg = 0; int end = row_len * col_len - 1; while (beg <= end) { int mid = beg + (end - beg) / 2; int k = matrix[mid/col_len][mid%col_len]; if (target == k) return true; else if (target > k) beg = mid + 1; else end = mid - 1; } /* * the following is another way, but more complex * int beg_row = 0; int beg_col = 0; int end_row = row_len - 1; int end_col = col_len - 1; while (end_row * col_len + end_col >= beg_row * col_len + beg_col) { int total = col_len - beg_col + end_col + 1 + col_len * (end_row - beg_row - 1); int k_col = (beg_col + (total / 2) % col_len) % col_len; int k_row = beg_row + (beg_col + (total / 2)) / col_len; if (target == matrix[k_row][k_col]) return true; else if (target > matrix[k_row][k_col]) { beg_row = k_row + (k_col + 1) / col_len; beg_col = (k_col + 1) % col_len; } else { end_row = (k_col == 0) ? k_row - 1 : k_row; end_col = (k_col == 0) ? col_len - 1 : k_col - 1; } } */ return false; } private: };
這個題目讓我想起了另一個二維數組題目,二維數組每一行,從左到右有序,每一列,從上到下有序,也是查找一個數。方法是從右上角的元素開始比較大小,指針向下或向左移動,時間複雜度是O(m+n)。get