題目描述
在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
知識點
數組;查找
Qiang的思路
通過對問題的分析,我發現題目中的二維數組具有如下的特點:
- 左上角元素為整個數組中的最小值。
- 右下角元素為整個數組中的最大值。
對于該問題通過遍歷的方法肯定是可以得到結果的。但是如果通過這種方法去做這個題就沒有什么意義了。所以肯定有更加高效的算法等待著我們去發現。
再進一步思考,想要簡化時間復雜度,必須能夠大幅度的降低問題的搜索空間才行。判斷整數的存在與否的關鍵在于大小的判斷,那這個過程中必然出現小于或者是大于的情況,那么可以通過這個角度出發去降低問題的搜索空間。
可以發現,二維數組右上角的元素具有非常良好的特性,因為它比其左側的元素都大,比其右側的元素都小。所以如果對其進行判斷的時候發現目標整數值大于右上角的元素值,那么肯定大于二維數組第一行所有的元素,這種情況下該行元素便可以完全刪除。
相反,當目標整數值小于二維數組右上角的元素時,整個數組最后一列元素也就沒有了比較的價值,可以被刪除。這樣一次比較便可以將整個搜索空間減少一次。
當右上角的元素等于目標整數時便找到了該整數,如果當二維數組被刪減為空了還沒有找到就說明該數組中不存在該整數。
# -*- coding:utf-8 -*-
class Solution:
# array 二維列表
def Find(self, target, array):
# write code here
if array==[] or array[0]==[]:
return False
if array[0][-1]==target:
return True
if array[0][-1]<target:
return self.Find(target, array[1:])
if array[0][-1]>target:
return self.Find(target, [a[:-1] for a in array])
在該代碼中應該注意python對二維數組的操作,不像C/C++,在不使用numpy等庫的時候,python對二維數組的操作相對復雜一些,在這里借助了for循環才實現了對列的刪減。
另外,在判斷數組是否為空的時候存在兩個條件,這是因為當按行刪減時,最后的數組為[],如果按列刪減最后的數組應該是這樣的[[],[],...,[]]。并且因為or的短路原則,所以這樣寫也不會因為判斷[]的第0號位置而出錯。
時間復雜性分析
最壞的情況下,該算法需要將所有的行和列都刪除一遍,時間復雜度為O(n+m),n為行數,m為列數。也就是線性的時間復雜度,但是遍歷將會是O(nm),平方級別的復雜度。所以該算法肯定是搞笑的。該代碼首先需要得到一個全為False的flag數組,時間復雜度為O(n)。然后通過遍歷的方式去判斷是否當前的數為重復出現的數,時間復雜度為O(n)。綜上,時間復雜度為O(n)。
Book中的思路
可能之前做過類似的,這次想到的思路和書上的是一樣的。另外注意,對于該問題右上角或者是左下角都是可以選擇的,原理是一樣的。
作者原創,如需轉載及其他問題請郵箱聯系:lwqiang_chn@163.com。
個人網站:https://www.myqiang.top。