代码改变世界

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

2016-07-04 15:24  chercher  阅读(276)  评论(0编辑  收藏  举报

二分法不只能像之前的记录,可以找到index~第二种类型是找到二分答案。有以下几个例子,都是之前二分法的扩展,不再赘述,只记录下忽略的点,以后回顾多注意~

1. wood cut

class Solution:
    """
    @param L: Given n pieces of wood with length L[i]
    @param k: An integer
    return: The maximum length of the small pieces.
    """
    def pieces(self, L, length):
        p = 0
        for i in L:
            p += i / length
        return p

    def woodCut(self, L, k):
        # at first, this if check condition is ignored
        if sum(L) < k:
            return 0
        start = 1
# at first, use the average of sum of array. end = max(L) while start + 1 < end: mid = start + (end - start) / 2 if self.pieces(L, mid) >= k: start = mid else: end = mid if self.pieces(L, end) >= k: return end return start

 

2. First Bad Version:可以看成找到第一个是false的位置

#class SVNRepo:
#    @classmethod
#    def isBadVersion(cls, id)
#        # Run unit tests to check whether verison `id` is a bad version
#        # return true if unit tests passed else false.
# You can use SVNRepo.isBadVersion(10) to check whether version 10 is a 
# bad version.
class Solution:
    """
    @param n: An integers.
    @return: An integer which is the first bad version.
    """
    def findFirstBadVersion(self, n):
        start = 1
        end = n
        while(start + 1 < end):
            mid = start + (end - start) / 2
            if SVNRepo.isBadVersion(mid):
                end = mid
            else:
                start = mid
        if SVNRepo.isBadVersion(start):
            return start
        return end

 

3. Search for a range:找到first position和last position的结合体,不过需要两次遍历,还没有找到更好的方法

class Solution:
    """
    @param A : a list of integers
    @param target : an integer to be searched
    @return : a list of length 2, [index1, index2]
    """
    def searchRange(self, A, target):
        # write your code here
        if A is None or len(A) == 0:
            return[-1,-1]
        start = 0
        end = len(A) - 1
        while(start + 1 < end):
            mid = start + (end - start) / 2
            if A[mid] == target:
                end = mid
            elif A[mid] < target:
                start = mid
            else:
                end = mid
        if A[start] == target:
            left = start
        elif A[end] == target:
            left = end
        else:
            return[-1,-1]
        
        start = left
        end = len(A) - 1
        while start + 1 < end:
            mid = start + (end - start) / 2
            if A[mid] == target:
                start = mid
            elif A[mid] < target:
                start = mid
            else:
                end = mid
        if A[end] == target:
            right = end 
        # one tip: cannot use another if, because there maybe two continuous 
        # same num. so A[start] and A[end] maybe the same and the value of 
        # A[start] may override the right value
        elif A[start] == target:
            right = start
        return [left,right]