二分查找基本模版:
def two_find(nums, target ,l ,r):
if l>r: return False
m = (l+r)//2
if nums[m]==target:
return True
elif nums[m] < target:
return two_find(nums, target, m+1, r)
elif nums[m] > target:
return two_find(nums, target, l, m-1)
def two_find2(nums,target):
l,r = 0, len(nums)-1
while l<=r:
m = (l+r)//2
if nums[m]==target: return True
elif nums[m]<target: l = m+1
else : r = m-1
return False
if __name__ == '__main__':
nums = [1,5,7,8,9,12,16,19,23]
target = 4
target = 23
r = two_find(nums, target, 0, len(nums)-1)
# r = two_find2(nums, target)
print(r)
33. 在旋轉數組中查找元素
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。 ( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。 搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。 你可以假設數組中不存在重複的元素。 你的算法時間複雜度必須是 O(log n) 級別。 輸入: nums = [4,5,6,7,0,1,2], target = 0 輸出: 4 輸入: nums = [4,5,6,7,0,1,2], target = 3 輸出: -1
方法思路: 1.根據 首尾判斷是否旋轉 2.若未旋轉,直接二分查找(注意:可以直接判斷target是否在首尾之內,否則直接返回-1) 3.若旋轉, 先找旋轉點(以找到最大值爲例) (1)情況一:target在[0,index_max]之內:此範圍二分查找 (2)情況二:target在[index_max+1,len(nums)-1]之內:此範圍二分查找 (3)情況三:若不在以上兩種情況則直接返回-1
class Solution:
def search(self, nums, target):
if len(nums)<1: return -1
# 二分查找
def two_find(l,r):
if l>r: return -1
m = (l+r)//2
if nums[m]==target: return m
elif nums[m]>target: return two_find(l,m-1)
else: return two_find(m+1,r)
# 尋找最大的 max_index 值
def find_max(l,r):
m = (l+r)//2
if nums[m]>nums[m+1]: return m
elif nums[m]>nums[0]: return find_max(m+1,r)
else : return find_max(l,m-1)
# 正常的升序數組
if nums[len(nums)-1]>nums[0]:
return two_find(0,len(nums)-1)
else:
max_index = find_max(0,len(nums)-1)
if nums[max_index]>=target and target>=nums[0]: return two_find(0,max_index)
elif target>=nums[max_index+1] and target<nums[-1]:return two_find(max_index+1,len(nums)-1)
else: return -1
from typing import List
def search2(self, nums: List[int], target: int) -> int:
if len(nums) < 1: return -1
if len(nums) == 1:
return 0 if nums[0] == target else -1
# 二分查找
def two_find(l, r):
while l <= r:
m = (l + r) // 2
if nums[m] == target:
return m
elif nums[m] < target:
l = m + 1
else:
r = m - 1
return -1
def find_max(nums):
l, r = 0, len(nums) - 1
while l <= r:
m = (l + r) // 2
if m != len(nums) - 1 and nums[m] > nums[m + 1]:
return m
elif nums[0] <= nums[m]:
l = m + 1
else:
r = m - 1
return len(nums) - 1
max_id = find_max(nums)
# print(max_id)
if target <= nums[max_id] and target >= nums[0]:
res = two_find(0, max_id)
else:
res = two_find(max_id + 1, len(nums) - 1)
return res
34.在排序數組中查找元素的 第一個和最後一個位置
給定一個按照升序排列的整數數組 nums,和一個目標值 target。 找出給定目標值在數組中的開始位置和結束位置。 你的算法時間複雜度必須是 O(log n) 級別。 如果數組中不存在目標值,返回 [-1, -1]。 -------------------------------------------------------------------------------- 輸入: nums = [5,7,7,8,8,10], target = 8 輸出: [3,4] 輸入: nums = [5,7,7,8,8,10], target = 6 輸出: [-1,-1]
class Solution:
def searchRange(self, nums, target):
# 二分查找--左邊界
def find_left(l ,r):
if l> r: return -1
m = (l + r) // 2
if (target == nums[m] and m == 0) or (target == nums[m] and target != nums[m - 1]):
return m
elif target < nums[m] or (target == nums[m] and target == nums[m - 1]):
return find_left(l, m - 1)
else:
return find_left(m + 1, r)
# 查找最右邊界 index
def find_right(l, r):
if l > r: return -1
m = (l + r) // 2
if (target == nums[m] and m == len(nums) - 1) or (target == nums[m] and target != nums[m + 1]):
return m
elif target > nums[m] or (target == nums[m] and target == nums[m + 1]):
return find_right(m + 1, r)
else:
return find_right(l, m - 1)
if len(nums) == 0: return [-1, -1]
if target >= nums[0] and target <= nums[-1]:
left = find_left(0, len(nums) - 1)
if left == -1: return [-1, -1]
if left == len(nums) - 1 or nums[left + 1] != target:
return [left, left]
else:
right = find_right(left + 1, len(nums) - 1)
return [left, right]
else:
return [-1, -1]
if __name__=="__main__":
s=Solution()
nums=[1]
target=1
r = s.searchRange(nums,target)
print(r)