劍指 offer 學習記錄-二維陣列的查詢
阿新 • • 發佈:2020-12-22
Num4-二維陣列中的查詢
文章目錄
一、題目描述
在一個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。
二、分析題目
1. 二維陣列 每行 左 -> 右 遞增
2. 二維陣列 每列 上 -> 下 遞增
3. 即陣列中 無重複 元素
4. 判斷二維陣列 有無待查詢 元素
在上圖的二維陣列中,判斷元素7是否存在,返回true
三、方法
1.利用陣列列遞增特性(不是最好的方法)
經過觀察,可知,若待查詢元素 m
m < matrix[row][col]
那麼 m 就不需要再繼續和之後的列進行比較了(因為m必定小於後續列的值)
舉個栗子,一上面的二維陣列為matrix,待查詢元素為 7 .
7 < matrix[0][2] // matrix[0][2] = 8
因此 7 就不必在和 8 之後的 9 進行比較,也就是不必和 matrix[ 0 ][ 3 ] 比較, 也就是7在下圖這一部分
所以總結以下規律
- 若 m < matrix[ row ][ col ], 則 m 不需要再與後續行列元素進行比較,換句話說,待查詢元素,在 matrix[ row ][ col ] 的左部分
程式碼如下:
//面試題4 查詢二維陣列中的值
public static boolean search(int[][] matrix, int k){
int rows = matrix.length;
int cols = matrix[0].length;
for(int row = 0; row < rows; row++){
for (int col = 0; col < cols; col++){
if(matrix[row][col] == k)
return true;
if(matrix[row][col] > k)
cols = col; // 將邊界設定為當前的column
}
}
return false;
}
2. 效率更高的方法(書上的方法)
第一種方法的缺點: 一開始想出的方法,(也就是上面的方法),只用到了列遞增的特點。但是並沒有用到行遞增的特點。因為(還是按照上面的例子)若要找7。再與8(matrix[ 0 ][ 2 ] )比較之後不能直接拋棄1、2、3行
書中的方法:
試著從陣列的右上角開始進行比較,這樣子就可以同時利用行遞增,與列遞增。還是一查詢7為例。
- 左上角元素為 9 ,9 > 7, 那麼 9 這一列(12,13,15)都大於7,可以拋棄(向左移動一列)
- 新的左上角元素為 8 ,同 9一樣, 可以拋棄(向前移動一列)
- 新的左上角元素為 2,2 < 7, 那麼在2之前的元素(1)都肯定比7小,可以拋棄,向下移動一行
- 最終就會到左下角的元素
簡單來說,就是通過從右上角進行比較,若待查元素大於陣列中的值那麼就往下移動一行;若小於陣列中的值,則向左移動一列
public static boolean Best(int[][] matrix, int k){
int rows = matrix.length;
int cols = matrix[0].length;
//從右上角開始比較
int current_row = 0; //當前行
int curretn_col = cols - 1; //當前列
while(current_row<rows && curretn_col>=0){
if(matrix[current_row][curretn_col] == k)
return true;
if(matrix[current_row][curretn_col] > k)
curretn_col--;
if(matrix[current_row][curretn_col] < k)
current_row++;
}
return false;
}
主函式
public static void main(String[] args) {
int[][] matrix = {{1,2,8,9},
{2,4,9,12},
{4,7,10,13},
{6,8,11,15}};
for (int[] rows : matrix){
for (int data : rows)
System.out.print(data + " ");
System.out.println();
}
boolean flag = search(matrix,5);
// boolean flag = Best(matrix, 7);
if (flag) {
System.out.println("包含");
} else System.out.println("不包含");
總結
自己想到的方法只是使用了列遞增的特點,並不能同時使用行列遞增特點,書中的方法從右上角開始查詢,就可以將行列遞增都應用到,並且時間複雜度也是最優。
今後還是得多觀察,將已有的條件都用起來
這次插的圖太粗糙了~