1. 程式人生 > 其它 >劍指 offer 學習記錄-二維陣列的查詢

劍指 offer 學習記錄-二維陣列的查詢

技術標籤:學習歷程演算法leetcode

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("不包含");

總結

自己想到的方法只是使用了列遞增的特點,並不能同時使用行列遞增特點,書中的方法從右上角開始查詢,就可以將行列遞增都應用到,並且時間複雜度也是最優。
今後還是得多觀察,將已有的條件都用起來

這次插的圖太粗糙了~