題目
二維數組中的查找
在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
例如:
1,2,5
3,4,9
7,8,21
3*3的數組
解答
思路
從二維數組的右上角的元素開始判斷,因爲此元素是它所在行的最大數,是它所在的列的最小數。如果它等於要查找的數字,則查找過程結束。如果它大於要查找的數字,則可以排除它所在的列。如果它小於要查找的數字,則可排除它所在的行。這樣如果要查找的數字不在數組的右上角,則每次判斷都可以排除一行或一列以縮小查找範圍,直到找到要查找的數字,或者查找範圍爲空。
代碼
Java代碼實現
public boolean findNum(int [][] array,int target) {
if(array == null || array.length==0 ||array[0].length==0){
return false;
}
int rowLen = array.length; // 行數
int columnLen = array[0].length; // 列數
if(target < array[0][0] || target > array[rowLen-1][columnLen-1]){
return false;
}
int i = 0;
int j = columnLen-1;
while(i<rowLen && j>=0){
if(array[i][j] == target){
return true;
}else if(array[i][j] > target){
j--;
}else{
i++;
}
}
return false;
}
擴展
若是在上題中加入一個條件:每行的首數大於上行的尾數
例如:
1,2,3
4,5,6
7,8,9
3*3的數組
思路
對於排好序的數組考慮使用二分查找法,可以得到O(logn)的查找效率。那麼這個二維數組其實可以看作一維有序數組,在這個一維數組中,元素被分爲m段,每段固定長度。即要將此二維數組映射到一個一維數組。
假設映射到一維數組A,A有m*n個元素,那麼A[k]=matrix[i][j], 當k=*n+j,即i=k/n, j=k%n。有了映射關係後就可以堆展開之後的一維數組進行二分查找,時間複雜度爲O(log(m*n))。
代碼
Java代碼實現
public boolean findNumEx(int [][] array,int target) {
if(array == null || array.length==0 || array[0].length==0){
return false;
}
int rowLen = array.length;
int columnLen = array[0].length;
if(target < array[0][0] || target > array[rowLen-1][columnLen-1]){
return false;
}
int low = 0;
// 總共有rowLen*columnLen個元素
int high = rowLen*columnLen-1;
while(low <= high){
int mid = (low + high)/2;
if(array[mid/columnLen][mid%columnLen] == target){
// 找到此元素,返回true
return true;
}else if(array[mid/columnLen][mid%columnLen] < target){
// 在右半部分繼續找
low = mid+1;
}else{
// 在右半部分繼續找
high = mid-1;
}
}
return false;
}