在数组中查找指定元素_剑指 offer 第一题: 二维数组中的查找
題目描述
在一個二維數(shù)組中(每個一維數(shù)組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數(shù),輸入這樣的一個二維數(shù)組和一個整數(shù),判斷數(shù)組中是否含有該整數(shù)。
題目分析
圖 1
如果沒有頭緒的話,很顯然使用 暴力解法 是完全可以解決該問題的。
即遍歷二維數(shù)組中的每一個元素,時間復雜度:O(n^2)。
其實到這里我們就可以發(fā)現(xiàn),使用這種暴力解法并沒有充分利用題目給出的信息。這個二維數(shù)組是有特點的。
- 每一行都是遞增的
- 每一列都是遞增的
圖 2
解法
解法一:二分法
對于有序數(shù)組的查找問題而言,二分法是最容易想到的一個解法。
在這里,對每一行使用二分查找,時間復雜度為 O(nlogn) 。二分查找復雜度 O(logn),一共 n 行,所以是總體的時間復雜度是 O(nlogn) 。
解法二:規(guī)律法
根據(jù)二維數(shù)組由上到下,由左到右遞增的規(guī)律。
從左下角開始遍歷,如果當前值比 target 小則往右找,如果比 target 大則往上找,如果存在,必然可以找到目標數(shù)字。
即選取右上角或者左下角的元素 a[row] [col] 與 target 進行比較, 當target小于元素 a[row] [col] 時,那么 target 必定在元素 a 所在行的左邊,讓 col-- ;當 target 大于元素 a[row] [col] 時,那么 target 必定在元素 a 所在列的下邊,讓 row++ ;
圖 3
代碼如下:
public class Solution { public boolean Find(int target, int [][] array) { int row = 0; int col = array[0].length - 1; while(row <= array.length - 1 && col >= 0){ if(target == array[row][col]) return true; else if(target > array[row][col]) row++ ; else col-- ; } return false; }}解法三:二分規(guī)律法
將解法一和解法二進行結合:對每行每列都使用二分查找,此時的時間復雜度為 O(logn * logm)。
圖 4
比如查找數(shù)字 9,首先使用用二分查找選出一行,總共有 5 行,那么( 0 + 5 ) / 2 = 2,所以我們找出了第 2行為基準行。
圖 5
接下來對這一行(即第 2 行)又使用二分查找, 找出這一行(即第 2 行)中最后一個比目標值小的值,這里是 6。
圖 6
6 及其所在的行和列把這個矩形劃分為 4 部分:
圖 7
這樣,實際上篩選的區(qū)域就只剩下左下部分(圖 7 藍色部分)和 右上部分(圖 7 棕色部分)這兩塊區(qū)域了,相比于解法二而言,使用這種解法平均情況下每一次查找,都可以把行和列的長度減少一半。
代碼如下:
public class Solution { public boolean Find(int target, int [][] array) { // 特殊情況處理 if (array == null || array.length == 0 || array[0].length == 0) { return false; } int h = array.length - 1; int w = array[0].length - 1; // 如果目標值小于最小值 或者 目標值大于最大值,那肯定不存在 if (array[0][0] > target || array[h][w] < target) { return false; } return binarySearchIn2DArray(array, target, 0, h, 0, w); } public static boolean binarySearchIn2DArray(int[][] array, int target, int startX, int endX, int startY, int endY) { if (startX > endX || startY > endY) { return false; } //首先,根據(jù)二分法找出中間行 int x = (startX + endX) / 2; //對該行進行二分查找 int result = binarySearch(array[x], target, startY, endY); //找到的值位于 x 行,result 列 if (array[x][result] == target) { return true; // 如果找到則成功 } //對剩余的兩部分分別進行遞歸查找 return binarySearchIn2DArray(array, target, startX, x - 1, result + 1, endY) || binarySearchIn2DArray(array, target, x + 1, endX, startY, result); } public static int binarySearch(int[] array, int target, int start, int end) { int i = (start + end) / 2; if (array[i] == target || start > end) { return i; } else if (array[i] > target) { return binarySearch(array, target, start, i - 1); } else { return binarySearch(array, target, i + 1, end); } }}總結
以上是生活随笔為你收集整理的在数组中查找指定元素_剑指 offer 第一题: 二维数组中的查找的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中tolist_高效的张量操
- 下一篇: vb6 判断打印机是否有效_智能收银机的