《剑指Offer》——二维数组中的查找(JZ1)C++
文章目錄
- 前言
- 題目:JZ1 二維數組中的查找
- 一、暴力解法
- 二、優化解法
- 總結
前言
題目:JZ1 二維數組中的查找
在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
給定 target = 7,返回 true。
提示:以下是本篇文章正文內容,下面案例可供參考
一、暴力解法
代碼如下(示例):
/*** 暴力解法* 通過兩層循環查找所有的數去對比* 時間復雜度O(mn),最壞情況查找了m行,n列才找到* @param target* @param array* @return bool*/ class Solution { public:bool Find(int target, vector<vector<int> > array) {if(array.size()==0) return false; //判斷異常情況for(int i=0;i<array.size();i++) //兩層for循環查找{for(int j=0;j<array[0].size();j++){if(target==array[i][j]){ return true;}}}return false;} };二、優化解法
代碼如下(示例):
/*** 利用二維數組由上到下,由左到右遞增的規律,* 那么選取左下角或者右上角的元素a[i][j]與target進行比較,* 當target大于元素a[i][j]時,那么target必定在元素a所在行的右邊,* 即j++;* 當target大于元素a[i][j]時,那么target必定在元素a所在列的上邊,* 即i--;* 時間復雜度m+n** @param target* @param array* @return*/ class Solution { public:bool Find(int target, vector<vector<int> > array) {if(array.size()==0||array[0].size()==0) //處理異常情況{return false;}int m = array.size(); //二維數組的行數mint n = array[0].size(); //二維數組的列數nint r=0,c=n-1; //從右上開始找while(r<m&&c>=0){if(target == array[r][c]){return true;}else if(target>array[r][c]){++r;}else{--c;}}return false;} };總結
方法2:二分查找
分析:對于方法一,此題有額外信息沒有利用上,數組從左到右遞增,從上到下遞增。有序的數組很顯然應該想到二分。那么應該如何二分呢?
回想一下一維有序數組查找某個值二分的過程,如下圖所示:
假設目標tar在arr[1]處,那么我們的二分過程就是:
1)設初始值:定義一個二分的開始下標為l,結束下標為r,如圖所示:
2)二分一半,中間位置為 mid = l + ((r - l) >> 1), val>>1, 表示val右移一位相當于val/2,相當于 l+(r-l)/2,這樣的寫法是防止溢出。如果寫成 mid = (l+r)/2; l+r可能會溢出。
3) 如果 tar == arr[mid],說明找到tar
4)比較:如果tar > arr[mid], 說明tar在區間[mid+1, r]中,l = mid + 1
5)如果tar < arr[mid],說明tar在區間[l, mid-1]中, r = mid - 1
圖中的例子就是步驟4)的情況,一次比較之后,如圖所示,表示找到了tar。
錯誤的想法:將一維擴展到二維。照葫蘆畫瓢,
假設我們設二分的開始下標為左上角坐標(0,0)為上圖的l,結束下標為(4,5)為圖中的r,二分一次下標為(2,2)圖中的mid,假設tar > arr[mid],
由一維二分可知,接下來應該找大于arr[mid]的位置,可是根據圖可知,?處可能大于,也可能小于,所以就不能按照之前的規則進行二分了。所以說,這樣是錯的。
總結一下:錯誤的原因是:之前二分之后,無法確定下一次二分應該往哪邊分,由此無法進行二分下去。如果我們找個位置,每次都能確定的往哪個部分二分,即可達到我們想要的結果。
新想法
假設arr數組,val,tar如下圖所示:
如果我們把二分值定在右上角或者左下角,就可以進行二分。這里以右上角為例,左下角可自行分析:
圖片說明
1)我么設初始值為右上角元素,arr[0][5] = val,目標tar = arr[3][1]
2)接下來進行二分操作:
3)如果val == target,直接返回
4)如果 tar > val, 說明target在更大的位置,val左邊的元素顯然都是 < val,間接 < tar,說明第 0 行都是無效的,所以val下移到arr[1][5]
5)如果 tar < val, 說明target在更小的位置,val下邊的元素顯然都是 > val,間接 > tar,說明第 5 列都是無效的,所以val左移到arr[0][4]
6)繼續步驟2)
復雜度分析
時間復雜度:O(m+n) ,其中m為行數,n為列數,最壞情況下,需要遍歷m+n次。
空間復雜度:O(1)
應該完整考慮好題目給出的條件
總結
以上是生活随笔為你收集整理的《剑指Offer》——二维数组中的查找(JZ1)C++的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TensorFlow官方入门实操课程-卷
- 下一篇: QTexe软件设置系统默认的图标