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