劍指 Offer——面試題 4-1
題目
在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。
請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
樣例
輸入數組:
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
如果輸入查找數值爲7,則返回true,
如果輸入查找數值爲5,則返回false。
思路
首先這道題如果使用暴力做法,遍歷數組的每個元素來進行查找的話,時間複雜度爲O(n²)
,這顯然不是一個精妙的解法,我們要通過一些特殊的性質,來減少我們需要訪問的元素個數
怎麼做呢,我們可以看到,整個二維數組是每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序,這是一條很重要的性質,也就是說,每一列的第一個元素是整列中最小的,每一行的第一個元素也是整行中最小的,我們可以從這個數組的右上角開始檢測,如果右上角的元素大於target
,我們就可以直接排除掉最右邊的一列,因爲target < 右上角元素 < 最右邊的一列中其他元素
,而如果右上角元素大於target
,那麼我們就可以刪除最上邊的一行,因爲有target > 右上角元素 > 第一行中的其他元素
,根據這個性質,我們可以每次去除二維數組的一行或者是一列,這樣可以大大縮減我們查找所消耗的時間,下面看代碼
代碼
class Solution {
public:
bool searchArray(vector<vector<int>> array, int target) {
if (array.size() == 0)
return false;
int i = 0;
int j = array[0].size() - 1;
while (i < array.size() && j >= 0) {
if (array[i][j] == target)
return true;
if (array[i][j] > target) --j;
if (array[i][j] < target) ++i;
}
return false;
}
};
class Solution {
public boolean searchArray(int[][] array, int target) {
if (array.length == 0) return false;
for (int i = 0, j = array[0].length - 1; i < array.length && j >= 0;) {
if (array[i][j] == target) return true;
if (array[i][j] > target) --j;
else ++i;
}
return false;
}
}