1. 程式人生 > >Search a 2D Matrix(在二維陣列中查詢)

Search a 2D Matrix(在二維陣列中查詢)

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

For example,

Consider the following matrix:

[
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]

Given target = 3, return true.

LeetCode上的一道題,這個題比較特殊,如果從二維陣列在記憶體中的儲存來看,其實是一個排序的一位陣列(自行查閱二維陣列在記憶體的順序)。所以肯定搞個二分查詢就OK了。但是可以先探討其他方案。

方案1:由於本人審題比較輕率,沒有看到本行第一個比上一行最後一個大的條件,看成了本行第一個比上一行第一個大。顯然如果這樣的話,就會更難處理:

我的方案是先按第一列處理,二分查詢找到行,然後行內二分查詢。渣程式碼如下:

public boolean searchMatrix1(int[][] matrix, int target) {
    	int low = 0;
        int high = matrix.length-1;
        int mid = 0;
        while (low <= high) {
        	mid = low + (high-low)/2;
        	if (matrix[mid][0] <= target && target <= matrix[mid][matrix[mid].length-1]) {
        		break;
        	} else if (matrix[mid][matrix[mid].length-1] < target){
        		low = mid +1;
        	} else if (matrix[mid][0] > target){
        		high = mid -1;
        	}
        }
        int row = mid;
        low = 0;
        high = matrix[row].length-1;
        while (low <= high) {
        	mid = low + (high-low)/2;
        	if (matrix[row][mid] == target) {
        		return true;
        	} else if (matrix[row][mid] < target) {
        		low = mid+1;
        	} else {
        		high = mid -1;
        	}
        }
        return false;
    }
其實時間複雜度也就O(lgn+lgm);也算挺快的。

但是由於本題的特殊之處,直接按一維陣列處理,渣程式碼如下:

public boolean searchMatrix(int[][] matrix, int target) {
		int row = matrix.length;
		int col = matrix[0].length;
		int low = 0; 
		int high = row * col -1;
		while (low <= high) {
			int mid = low + (high-low)/2;
			int num = matrix[mid/col][mid%col];
			if (num == target) {
				return true;
			} else if (num < target) {
				low = mid+1;
			} else {
				high = mid-1;
			}
		}
		return false;
    }

時間複雜度O(lg(m+n));但是由於現在計算機快取的問題,其實速度沒有提升多少。

再看劍指offer的一道題目:

在一個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上往下遞增的順序排序。請寫一個函式,輸入一個二維陣列和一個整數,判斷陣列中是否含有該整數。

例如下面的二維陣列就是每行、每列都是遞增順序,如果在這個陣列中查詢數字7,則返回true,如果查詢數字5,由於陣列中不含有該數字,則返回false。

1   2   8   9

2  4   9   12

4  7  10   13

6  8   11   15

public boolean find(int[][] matrix, int number) {
		if (matrix != null && matrix.length > 0 && matrix[0].length > 0) {
			int rows = matrix.length;
			int columns = matrix[0].length;
			int row = 0;
			int col = columns-1;
			while (row < rows && col >= 0) {
				int temp = matrix[row][col];
				if (number > temp) {
					row++;
				} else if (number < temp) {
					col--;
				} else {
					return true;
				}
			}
		}
		return false;
	}

時間複雜度是多少?O(m+n),豈不是還沒有我開始第一種方法效率高?