二分法查找+树
一,查找存在的一個數,該數在列表中唯一
二分法查找是針對有序數據的查找方法,時間復雜度是O(logn)。。
其中 n/2^k=1 時,k 的值就是總共縮小的次數。而每一次縮小操作只涉及兩個數據的大小比較,所以,
經過了 k 次區間縮小操作,時間復雜度就是 O(k)。通過 n/2^k=1,我們可以求得 k=log2n,所以時間復雜度就是O(K),也就是O(logn)。
方法一,循環
實際上,mid=(low+high)/2 這種寫法是有問題的,因為low和high很大的時候,兩者之和可能會溢出,應該寫為low+(high-low)/2,
更好的話寫成,low+((high-low)>>1)?
方法二,遞歸
#有序列表的二分法,最簡單版 def binary_search(array,low,high,value):if low>high:return -1mid = low + int((high - low) >> 1)if value==array[mid]:return mid,array[mid]elif value>array[mid]:low=mid+1return binary_search(array,low,high,value)else:high=mid-1return binary_search(array, low, high, value) def binary_search_merge(array,value):return binary_search(array,0,len(array)-1,value) a=[0,1,2,3,4,9] index,res=binary_search_merge(a,9) print('index={},res={}'.format(index,res))缺點:(1)依賴的是順序表結構,比如數組,不能用于鏈表,(2)需要先排好序,而排序的最低時間復雜度是O(nlogn),(3)不適用于小數據量(4)二分查找更適合處理靜態數據,也就是沒有頻繁的數據插入、刪除操作。
二,查找第一個值等于給定值的元素(存在多個值)
target大于目標值,左邊界就變大,當找到等于的就返回左邊界值,也就是第一個值了
def searchLeft(nums, target):left, right = 0, len(nums) - 1while left <= right:middle = left + (right - left) // 2if nums[middle] < target:left = middle + 1else:right = middle - 1return leftnums = [5, 7, 7, 8, 8, 10] target = 8 # nums = [0, 1, 8, 8, 9, 9, 9] # target = 9 res = searchLeft(nums, target) print(res)三,查找最后一個值等于給定值的元素(存在多個值)
target大于等于左邊界的值,這時左邊界值越來越大直到找到最后一個才返回
def searchRight(nums, target):left, right = 0, len(nums) - 1while left <= right:middle = left + (right - left) // 2if nums[middle] <= target: # 加個等于符號 這樣left就可以找到最后一個left = middle + 1else:right = middle - 1return left - 1 nums = [5, 7, 7, 8, 8, 10] target = 8 # nums = [0, 1, 8, 8, 9, 9, 9] # target = 9 res = searchRight(nums, target) print(res)四,查找第一個大于等于給定值的元素(存在多個值)
#查找第一個大于等于目標值的數 def binary_search(array, value):left = 0right = len(array) - 1while left < right:middle = left + (right - left)//2print('====middle:', middle)if array[middle] < value:left = middle + 1else:right = middle# print(middle)return right, array[right] # a = [0,1,7,7,7,9,9] a = [0, 1, 1, 1, 1] index, res = binary_search(a, 1) print('index={},res={}'.format(index, res))?
五.?查找第一個大于給定值的元素(存在多個值)
#查找第一個大于目標值的數 def binary_search(array, value):left = 0right = len(array) - 1while left < right:middle = left + (right - left)//2if array[middle] <= value:left = middle + 1else:right = middle# print(middle)return right, array[right] a = [0,1,7,7,7,9,9] # a = [0, 1, 1, 1, 1] index, res = binary_search(a, 7) print('index={},res={}'.format(index, res))六,查找最后一個小于給定值的元素(存在多個值)
def binary_search(array,value):if len(array) <= 1:return arraylow=0high=len(array)-1while(low<=high):#多這種寫法mid = low+((high-low)>>1)#中間值小于valueif array[mid]<value:#中間值的前一位大于等于value或者mid==len(array)-1if array[mid+1]>value or mid==len(array)-1:return mid,array[mid]else:low=mid+1else:high=mid-1return -1,-1 a=[0,1,7,7,7,9,9] index,res=binary_search(a,8) print('index={},res={}'.format(index,res))實際上,二分法更適用于‘近似’查找問題,這類問題二分法查找優勢更加明顯,用其他數據結構比如散列表,二叉樹就比較難實現了。
由此引出樹:
對于1到11的元素,首先以6為分節點,然后不斷分。。。
?
總結
- 上一篇: 链表操作时头结点的好处
- 下一篇: nginx+uWSGI + django