代码改变世界

二分查找总结及部分Lintcode题目分析 1

2016-07-04 11:13  chercher  阅读(421)  评论(0编辑  收藏  举报

进行二分查找课程回顾与总结,包括以下几个方面,二分法的模板总结和解题思路、应用。

 

二分法模板总结classical binary search:

1. 必须要做的排除极端情况,也就是数组(用A表示)不存在即A == None或者 A为空,即len(A) == 0 的情况。

2. 二分法核心找的是mid值,并判断这个mid是否跟我们要找的target一致,或者和target之间的关系,所以要先判断start和end。为start和end赋值,start = 0, end = len(A) - 1

3. 之后就是要进行while循环,目的是用一次次的二分来找出是否存在target或者target的位置、范围等问题,条件是start + 1 < end来避免死循环

    并有 mid = start + ( end - start ) / 2 来避免溢出

4. 判断A[mid] 与 target的关系,及采取怎样的赋值操作来保留有解的一半,即start == mid 或者 end == mid

5. 可能A[start] 与 A[end]的值与target相同,但是已经使 start + 1 < end 这个条件为False,所以在循环外还要判断这两个值是否和target一致。

6. 如果都不相等的话则返回空

 

下面,给出classical binary search的解法,这是简单而典型的binary search on index的问题

class Solution:
    # @param {int[]} A an integer array sorted in ascending order
    # @param {int} target an integer
    # @return {int} an integer
    def findPosition(self, A, target):
        # they are different
        if A is None or len(A) == 0:
            return -1
        # set start and end
        end = len(A) - 1
        start = 0
        # while loop, use start + 1 < end to avoid dead loop
        while (start + 1 < end):
            mid = start + ( end - start ) / 2
            if A[mid] == target:
                return mid
            elif A[mid] > target:
                # start..mid..end, target in start..mid
                end = mid
            else:
                start = mid
        if A[start] == target:
            return start
        if A[end] == target:
            return end
        return -1

 

由经典算法可以展开到the first position or the last position,都是binary search on index的典型例子,在这两种中即使找到了相应的元素为了判断是否是最开始或者最后的位置,在第四第五步要有所不同~以last position为例

while (start + 1 < end):
            mid = start + ( end - start ) / 2
            if A[mid] == target:
                start = mid
            elif A[mid] > target:
                # start..mid..end, target in start..mid
                end = mid
            else:
                start = mid
        if A[end] == target:
            return end
        if A[start] == target:
            return start
        

 

比较类似的像 search a 2D matrix 问题,只是把二维数组展开成一个一维数组,继续采用上面的二分法模板就可以解

class Solution:
    """
    @param matrix, a list of lists of integers
    @param target, an integer
    @return a boolean, indicate whether matrix contains target
    """
    def searchMatrix(self, matrix, target):
        if matrix is None or len(matrix) == 0:
            return False
        m = len(matrix)
        n = len(matrix[0])
        start = 0
        end = m * n - 1
        while(start + 1 < end):
            mid = start + (end - start) / 2
            line = mid / n
            column = mid % n
            if matrix[line][column] == target:
                return True
            elif matrix[line][column] < target:
                start = mid
            else:
                end = mid
        if matrix[(start / n)][(start % n)] == target:
            return True
        if matrix[(end / n)][(end % n)] == target:
            return True
        return False

 

 search insert position 只要把握住二分法一个重要的特性,就是判断条件,就可以转化为找first position >= target 的问题

class Solution:
    """
    @param A : a list of integers
    @param target : an integer to be inserted
    @return : an integer
    """
    def searchInsert(self, A, target):
        # find the position whose value is equal or more than target
        # only consider no duplicates conditions
        if A is None or len(A) == 0:
            return 0
        start = 0
        end = len(A) - 1
        while(start + 1 < end):
            mid = start + (end - start) / 2
            if A[mid] >= target:
                end = mid
            else:
                start = mid
        if A[start] >= target:
            return start
        if A[end] >= target:
            return end
# a condition that the target is more than all of the elements in array if A[end] < target: return end + 1 return -1