lintcode刷题 14. 二分查找,迭代和二分法Python实现

14. 二分查找

描述

给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1

您在真实的面试中是否遇到过这个题?  是

题目纠错

样例

在数组 [1, 2, 3, 3, 4, 5, 10] 中二分查找3,返回2

挑战

如果数组中的整数个数超过了2^32,你的算法是否会出错?

14. First Position of Target

Description

For a given sorted array (ascending order) and a target number, find the first index of this number in O(log n)time complexity.

If the target number does not exist in the array, return -1.

Have you met this question in a real interview?  Yes

Problem Correction

Example

If the array is [1, 2, 3, 3, 4, 5, 10], for given target 3, return 2.

Challenge

If the count of numbers is bigger than 2^32, can your code work properly?

二分查找使用迭代永远不会发生栈溢出

看代码吧,记得看最后的备注

#用迭代实现二分法
#写个类吧
class Solution:
	def binarySearch(self, nums, target):
		return self.search(nums, 0, len(nums) - 1, target)

	def search(self, nums, start, end, target):

		if start > end:
			return -1

		#start, end = 0, len(nums) -1
		mid = (start + end)//2
		if nums[mid] > target:
			return self.search(nums, start, mid, target)
		if nums[mid] == target:
			return mid
		if nums[mid] < target:
			return self.search(nums, mid, end, target)

my_solution = Solution()
nums = [1,2,3,4,5,6]
target = 2
#start, end = 0, len(nums) -1
targetIndex = my_solution.binarySearch(nums, target)
print(targetIndex)
'''
#用迭代实现二分法
#写个函数吧
def search(nums, start, end, target):

	if start > end:
		return -1

	#start, end = 0, len(nums) -1
	mid = (start + end)//2
	if nums[mid] > target:
		return search(nums, start, mid, target)
	if nums[mid] == target:
		return mid
	if nums[mid] < target:
		return search(nums, mid, end, target)

#my_solution = Solution()
nums = [1,2,3,4,5,6]
target = 2
start, end = 0, len(nums) -1
targetIndex = search(nums, start, end, target)
print(targetIndex)

'''

#二分法,模板实现
class Solution:
    def binarySearch(self, nums, target):
        if len(nums) == 0:
            return -1
        start, end = 0, len(nums) -1
        while (start + 1 < end):
            mid = (start + end) // 2
            if nums[mid] < target:
                start = mid
            else:
                end = mid

                '''
                这里不能画蛇添足,要不然错了,如果碰到nums[mid] == target情况,
                end = mid, nums[end]= nums[mid] == target, 跳转到最后,return end了
            elif nums[mid] > tartet:
                end = mid
            else:
                return mid 
                '''
                
        if nums[start] == target:
            return start
        if nums[end] == target:
            return end
        return -1

my_solution = Solution()
nums = [1,2,3,4,5,6]
target = 2
targetIndex = my_solution.binarySearch(nums, target)
print(targetIndex)    


为什么要用 start + 1 < end?而不是 start < end 或者 start <= end?

A: 为了避免死循环。二分法的模板中,整个程序架构分为两个部分:

  1. 通过 while 循环,将区间范围从 n 缩小到 2 (只有 start 和 end 两个点)。
  2. 在 start 和 end 中判断是否有解。

start < end 或者 start <= end 在寻找目标最后一次出现的位置的时候,出现死循环。

Q: 为什么明明可以 start = mid + 1 偏偏要写成 start = mid?

A: 大部分时候,mid 是可以 +1 和 -1 的。在一些特殊情况下,比如寻找目标的最后一次出现的位置时,当 target 与 nums[mid] 相等的时候,是不能够使用 mid + 1 或者 mid - 1 的。因为会导致漏掉解。那么为了节省脑力,统一写成 start = mid / end = mid 并不会造成任何解的丢失,并且也不会损失效率——log(n) 和 log(n+1) 没有区别。

认识你是我们的缘分,同学,等等,记得关注我。

微信扫一扫
关注该公众号

猜你喜欢

转载自blog.csdn.net/BTUJACK/article/details/82943681