LeetCode之二分查找实战2之第一个错误的版本(278)、猜数字大小(374)

二分查找2

  • 1、第一个错误的版本(278)
  • 2、猜数字大小(374)

1、第一个错误的版本(278)

题目描述:

【简单题】
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

LeetCode之二分查找实战2之第一个错误的版本(278)、猜数字大小(374)_第1张图片
题目链接

思路分析

1、由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。一带而发,因此可以用二分查找方法解决此题。
2、对中间值mid调用 isBadVersion(),如果返回False,则说明mid左半部分的版本均未出错,则在其右半部分继续二分查找,否则在左半部分查找。
【python3代码实现】

# The isBadVersion API is already defined for you.
# @param version, an integer
# @return a bool
# def isBadVersion(version):

class Solution:
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        left=0
        right=n
        while left<right:
            mid=left+(right-left)//2
            if isBadVersion(mid):
                right=mid
            else:
                left=mid+1
        return left#或者right,因为终止条件是left==right

2、猜数字大小(374)

题目描述:

【简单题】
LeetCode之二分查找实战2之第一个错误的版本(278)、猜数字大小(374)_第2张图片
题目链接

思路分析

-1 : 你猜测的数字比系统选出的数字大
1 : 你猜测的数字比系统选出的数字小
0 : 恭喜!你猜对了!

显然可以使用二分查找法。

# The guess API is already defined for you.
# @param num, your guess
# @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
# def guess(num: int) -> int:

class Solution:
    def guessNumber(self, n: int) -> int:
        left = 0
        right = n
        while left<=right:
            mid=left+(right-left)//2
            if guess(mid) == 0:
                return mid
            elif guess(mid)==1:
                left=mid+1
            else:
                right=mid-1

另一种写法

# The guess API is already defined for you.
# @param num, your guess
# @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
# def guess(num: int) -> int:

class Solution(object):
    def guessNumber(self, n):
        left = 1
        right = n
        while left < right:
            # mid = left + (right - left) // 2
            mid = (left + right) >> 1
            if guess(mid) == 1:
                # 中位数比猜的数小,因此比中位数小的数包括中位数都不是目标元素
                left = mid + 1
            else:
                right = mid
        # 最后剩下的数一定是所求,无需后处理
        return left

中位数的计算方法:

1、mid = (left + right) / 2; 是初级写法,是有 bug 的:有可能会溢出。

2、 mid = left + (right - left) / 2; 是正确的写法,考虑到了整型溢出的风险;

3、mid = (low + high) >> 1; 右移运算符>>,运算结果正好能对应一个整数的二分之一值,这就正好能代替数学上的除2运算,但是比除2运算要快。

你可能感兴趣的:(leetcode,#,查找,二分查找,Leetcode)