二分搜索的模板(二)

版权声明:本文为博主原创文章,如有转载请标注来源。 https://blog.csdn.net/shengchaohua163/article/details/79789096

二分搜索是算法搜索一部分的重要内容。虽然变化多端,但仍有迹可循,有法可依。记录一下在网上遇到的模板~

这个模版的核心是将二分搜索(binary search)问题转化成:在给定升序数组中,寻找第一个或者最后一个 target 元素出现的索引。有几点需要注意:

  1. 初始化:start = 0,end = array.length - 1
  2. 循环判断条件:start + 1 < end。 表示当指针指到两个元素相邻或者相交的时候, 循环停止。
  3. 求中间值:mid = start + (end - start) / 2,防止溢出。(Python不用考虑,但Python的除号是 //)
  4. 对 array[mid] 判断大小分三种情况(>, <, ==)讨论。不相等时(> 或 <),需要移动start和end,直接写 start=mid 或 end=mid,不要 +1 或者 -1 。因为只移动边界到mid的位置,不会误删除target。相等(==)时,不要写return,在程序最后的时候统一写return,这样可以增强可读性。
  5. 在循环结束后,因为只有1~2个元素需要讨论,所以结果非常容易解释清楚。

该模板的Python代码如下:

class Solution:
    def binary_search(self, array, target):
        if not array:
            return -1

        start, end = 0, len(array) - 1
        while start + 1 < end:
            mid = (start + end) // 2
            if array[mid] == target:
                start = mid # 寻找最后一个target的index
                # end = mid # 寻找第一个target的index
            elif array[mid] < target:
                start = mid
            else:
                end = mid

        if array[start] == target:
            return start
        if array[end] == target:
            return end
        return -1

题目:lintcode No.61. Search for a Range

根据上面的模板进行解题。核心步骤为:1.寻找第一个 target 元素的index 2.寻找最后一个 target 元素的 index。 Python代码如下:

class Solution:
    """
    @param A: an integer sorted array
    @param target: an integer to be inserted
    @return: a list of length 2, [index1, index2]
    """
    def searchRange(self, A, target):
        # write your code here
        res = [-1, -1]
        if not A:
            return res
        # search the first target index of target
        start, end = 0, len(A) - 1
        while start + 1 < end:
            mid = (start + end) // 2
            if A[mid] == target:
                end = mid # 寻找第一个target的index
            elif A[mid] < target:
                start = mid
            else:
                end = mid
        if A[start] == target:
            res[0] = start
        elif A[end] == target:
            res[0] = end

        # search the last target index of target
        start, end = 0, len(A) - 1
        while start + 1 < end:
            mid = (start + end) // 2
            if A[mid] == target:
                start = mid # 寻找最后一个target的index
            elif A[mid] < target:
                start = mid
            else:
                end = mid
        if A[end] == target:
            res[1] = end
        elif A[start] == target:
            res[1] = start

        return res

参考资料:

  1. lintcode No.61. Search for a Range
  2. Binary Search - 二分搜索

猜你喜欢

转载自blog.csdn.net/shengchaohua163/article/details/79789096