二分查找
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
具体实现
import random
# nums_test = sorted(random.randint(0, 100) for _ in range(random.randint(0,100)))
nums_test = [6, 6, 7, 7, 8, 11, 13, 13, 13, 14, 14, 15, 15, 18, 19, 21, 25, 25, 25, 25, 25, 26, 28, 29, 29, 30, 31, 33,
36, 37, 39, 40, 42, 43, 44, 45, 48, 48, 49, 50, 53, 53, 54, 54, 55, 56, 57, 58, 58, 59, 60, 60, 62, 62, 64,
69, 69, 70, 70, 71, 72, 74, 77, 78, 79, 79, 80, 81, 83, 85, 88, 91, 92, 93, 94, 95, 95, 98]
print(nums_test)
# 精确匹配
def search_exact(target: int, nums: list = nums_test) -> int:
l, r = 0, len(nums_test)
while l < r:
i = (l + r) // 2
if nums[i] < target:
l = i + 1
else:
r = i
return l if nums[l] == target else -1
# 大于等于目标值的第一个
def search_left(target: int, nums: list = nums_test) -> int:
l, r = 0, len(nums_test) - 1
while l < r:
i = (l + r) // 2
if nums[i] < target:
l = i + 1
else:
r = i
return l if nums[l] >= target else -1
# 小于等于目标值的最后一个
def search_right(target: int, nums: list = nums_test) -> int:
l, r = 0, len(nums) - 1
while l < r:
i = (l + r + 1) // 2
if nums[i] <= target:
l = i
else:
r = i - 1
return l if nums[l] <= target else -1
rp = random.randint(0, len(nums_test))
nums_rotate = nums_test[rp:] + nums_test[:rp]
# 旋转数组中查找最小值
def findMin(nums: list = nums_rotate) -> int:
l, r = 0, len(nums) - 1
while l < r:
i = (l + r) // 2
if nums[i] > nums[-1]:
l = i + 1
else:
r = i
return l
# 旋转数组中搜索
# 升序数组nums被分成了俩个互斥的子串,左右颠倒
# 如果t=target在数组中,它要么在左边的升序数组中,要么在右边的升序数组中
# 1. t在左边,则t>right_max, left_min <= t <= left_max
# 2. t在右边,则t<left_min, right_min <= t <= right_max
# 而 right_min <= right_max <= left_min <= left_max (取等号时只有一个元素)
# 由于nums的左右子串互斥,条件1和条件2不可能同时成立
def search_rotate(target: int, nums: list = nums_rotate) -> int:
l, r = 0, len(nums) - 1
while l < r:
i = (l + r) // 2
print(l, i, r)
if nums[i] == target:
return i
if nums[l] < nums[i]:
if nums[l] <= target <= nums[i]:
r = i
else:
l = i + 1
else:
if nums[i] <= target <= nums[r]:
l = i
else:
r = i - 1
return -1
t = 25
res_search_l = search_left(t)
print(res_search_l, nums_test[res_search_l - 1:res_search_l + 2])
res_search_r = search_right(t)
print(res_search_r, nums_test[res_search_r - 1:res_search_r + 2])
res_findMin = findMin()
print(nums_rotate)
print(res_findMin, nums_rotate[res_findMin - 1:res_findMin + 2])
res_search_ro = search_rotate(t)
print(res_search_ro, nums_rotate[res_search_ro - 1:res_search_ro + 2])
[6, 6, 7, 7, 8, 11, 13, 13, 13, 14, 14, 15, 15, 18, 19, 21, 25, 25, 25, 25, 25, 26, 28, 29, 29, 30, 31, 33, 36, 37, 39, 40, 42, 43, 44, 45, 48, 48, 49, 50, 53, 53, 54, 54, 55, 56, 57, 58, 58, 59, 60, 60, 62, 62, 64, 69, 69, 70, 70, 71, 72, 74, 77, 78, 79, 79, 80, 81, 83, 85, 88, 91, 92, 93, 94, 95, 95, 98]
16 [21, 25, 25]
20 [25, 25, 26]
[62, 64, 69, 69, 70, 70, 71, 72, 74, 77, 78, 79, 79, 80, 81, 83, 85, 88, 91, 92, 93, 94, 95, 95, 98, 6, 6, 7, 7, 8, 11, 13, 13, 13, 14, 14, 15, 15, 18, 19, 21, 25, 25, 25, 25, 25, 26, 28, 29, 29, 30, 31, 33, 36, 37, 39, 40, 42, 43, 44, 45, 48, 48, 49, 50, 53, 53, 54, 54, 55, 56, 57, 58, 58, 59, 60, 60, 62]
25 [98, 6, 6]
0 38 77
38 57 77
38 47 57
38 42 47
42 [25, 25, 25]
Process finished with exit code 0