【千字过程分析】剑指 Offer 04. 二维数组中的查找
立志用最少的代碼做最高效的表達
在一個 n * m 的二維數(shù)組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個高效的函數(shù),輸入這樣的一個二維數(shù)組和一個整數(shù),判斷數(shù)組中是否含有該整數(shù)。
示例:
現(xiàn)有矩陣 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
給定 target = 5,返回 true。
給定 target = 20,返回 false。
限制:
0 <= n <= 1000
0 <= m <= 1000
解法一:暴力
直接遍歷該二維數(shù)組,判斷這個值在數(shù)組中是否存在即可。
class Solution { public:bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {for(int i = 0; i < matrix.size(); i++) {for(int j = 0; j < matrix[i].size(); j++) {if(matrix[i][j] == target) {return true;}}}return false;} };解法二:線性查找(雙指針法)
例如下面的二維數(shù)組就是每行、每列都遞增排序。如果在這個數(shù)組中查找數(shù)字7,則返回true;如果查找數(shù)字5,由于數(shù)組不含有該數(shù)字,則返回false。
在分析這個問題的時候,很多應聘者都會把二維數(shù)組畫成矩形,然后從數(shù)組中選取一個數(shù)字,分3種情況來分析查找的過程。
- 當數(shù)組中選取的數(shù)字剛好和要查找的數(shù)字相等時,就結束查找過程。
- 如果選取的數(shù)字小于要查找的數(shù)字,那么根據(jù)數(shù)組排序的規(guī)則,要查找的數(shù)字應該在當前選取位置的右邊或者下邊,如圖2.1 (a)所示。
- 同樣,如果選取的數(shù)字大于要查找的數(shù)字,那么要查找的數(shù)字應該在當前選取位置的上邊或者左邊,如圖2.1 (b)所示。
注:在數(shù)組中間選擇一個數(shù)(深色方格),根據(jù)它的大小判斷要查找的數(shù)字可能出現(xiàn)的區(qū)域(陰影部分)。
在上面的分析中,由于要查找的數(shù)字相對于當前選取的位置有可能在兩個區(qū)域中出現(xiàn),而且這兩個區(qū)域還有重疊,這問題看起來就復雜了,于是很多人就卡在這里束手無策了。
當我們需要解決一個復雜的問題時,一個很有效的辦法就是從一個具體的問題入手,通過分析簡單具體的例子,試圖尋找普遍的規(guī)律。
針對這個問題,我們不妨也從一個具體的例子入手。下面我們以在題目中給出的數(shù)組中查找數(shù)字7為例來一步步分析查找的過程。
前面我們之所以遇到難題,是因為我們在二維數(shù)組的中間選取一個數(shù)字來和要查找的數(shù)字進行比較,這就導致下一次要查找的是兩個相互重疊的區(qū)域。如果我們從數(shù)組的一個角上選取數(shù)字來和要查找的數(shù)字進行比較,那么情況會不會變簡單呢?
首先我們選取數(shù)組右上角的數(shù)字9。由于9大于7,并且9還是第4列的第一個(也是最小的)數(shù)字,因此7不可能出現(xiàn)在數(shù)字9所在的列。
于是我們把這一列從需要考慮的區(qū)域內(nèi)剔除,之后只需要分析剩下的3列,如圖2.2( a)所示。在剩下的矩陣中,位于右上角的數(shù)字是8。同樣8大于7,因此8所在的列我們也可以剔除。接下來我們只要分析剩下的兩列即可,如圖2.2 (b)所示。
在由剩余的兩列組成的數(shù)組中,數(shù)字2位于數(shù)組的右上角。2小于7,那么要查找的7可能在2的右邊,也可能在2的下邊。在前面的步驟中,我們已經(jīng)發(fā)現(xiàn)2右邊的列都已經(jīng)被剔除了,也就是說7不可能出現(xiàn)在2的右邊,因此7只有可能出現(xiàn)在2的下邊。
于是我們把數(shù)字2所在的行也剔除,只分析剩下的三行兩列數(shù)字,如圖2.2(c)所示。在剩下的數(shù)字中,數(shù)字4位于右上角,和前面一樣,我們把數(shù)字4所在的行也刪除,最后剩下兩行兩列數(shù)字,如圖2.2(d)所示。
在剩下的兩行兩列4個數(shù)字中,位于右上角的剛好就是我們要查找的數(shù)字7,于是查找過程就可以結束了。
代碼
class Solution { public:bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {int row_len = matrix.size(), col_len = 0;if(!matrix.empty()) col_len = matrix[0].size();int now_row = 0, now_col = col_len-1;while(1) {if(now_row >= row_len || now_col < 0) break;if(target == matrix[now_row][now_col]) return true;else if(target < matrix[now_row][now_col]) now_col--;else if(target > matrix[now_row][now_col]) now_row++;}return false;} };本題考點
考察應聘者對二維數(shù)組的理解及編程能力。二維數(shù)組在內(nèi)存中占據(jù)連續(xù)的空間。在內(nèi)存中從上到下存儲各行元素,在同一行中從左到右的順序存儲。
因此我們可以根據(jù)行號和列號計算出相對于首地址的偏移量,從而找到對應的元素。
考查應聘者分析問題、發(fā)現(xiàn)規(guī)律、解決問題的能力。
這道題只要從一個具體的二維數(shù)組的右上角開始分析,找到查找的規(guī)律,從而找到解決問題的突破口
總結
以上是生活随笔為你收集整理的【千字过程分析】剑指 Offer 04. 二维数组中的查找的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【报错】:Char 5: error:
- 下一篇: 【千字分析】剑指 Offer 05. 替