leetcode--刷题日记第一天
二分查找
题号:704.二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-search
思路:这就是最基础的二分查找了,直接一直二等分,知道找到目标值就返回下标(如果目标值比中值小,就将右边界设置为中值,如此循环,反之亦然)
代码:
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
n = len(nums)
first = 0
last = n - 1
while first <= last:
mid = (first + last) // 2
if target == nums[mid]:
return mid
elif target < nums[mid]:
last = mid - 1
else:
first = mid + 1
return -1
题号:278.第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-bad-version
思路:首先这也是个二分查找问题,只不过有点变化,因为根据题目所说我们是要找到第一个出问题的版本,同时第一个出错版本的后面的版本都是错的,也就说明使用 isBadVersion(version) 函数时,在第一个错误版本后面的所有版本都会返回True,所以就会有一个核心的问题需要解决:
如何确定第一个版本?
1.如果第一个版本在mid的左边?
2.如果第一个版本在mid的右边?
3.如果第一个版本刚好就在mid?
解决方案:
首先分为两种情况
1.isBadVersion(mid)为True,这个版本是错的
2.isBadVersion(mid)为False,这个版本是对的
如果是:说明第一个版本一定在它的左侧或者就是它本身,如何验证呢,可以通过设置last(右侧边界)=mid,以此二分查找来不断地接近第一个版本,当first == last 的时候,就说明此时已经是第一个版本,返回该值
**如果不是:**说明第一个版本一定在它的右侧,可以通过设置:first(左侧边界)=mid +1,然后继续二分查找,直到找到一个错误版本,才能进入上面的循环
代码:
# The isBadVersion API is already defined for you.
# @param version, an integer
# @return a bool
# def isBadVersion(version):
class Solution(object):
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
first = 1
last = n
while first <= last:
mid = (first + last) // 2
if isBadVersion(mid):
last = mid
if first == last:
return mid
else:
first = mid + 1
或者
class Solution(object):
def firstBadVersion(self, n):
"""
:type n: int
:rtype: int
"""
first = 1
last = n
while first < last:
mid = (first + last) // 2
if isBadVersion(mid):
last = mid
if first == last:
return mid
else:
first = mid + 1
return first
上面两种代码的区别就是跳出 while 循环
题号: 35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position
思路:根据题目要求,可以把代码分为两部分,先查找数组中有没有目标值,如果有,就返回索引,没有就再比较目标值的大小,并返回顺序插入的位置(并不是插入之后再返回,只是逻辑上的处理而已)
比较分为三种情况:
1.比mid值大
2.与mid值相等
3.比mid值小
解决:
通过二分查找没找到该目标值的话,此时的mid值其实就已经与目标值相邻了
1.如果比mid值大,那么返回mid+1
2.3. 其实<=mid 值是一种情况,那就是把该mid位置上原有的值给替代就可以了,也就是 返回mid
代码:
class Solution(object):
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
n = len(nums)
first = 0
last = n-1
while first <= last:
mid = (first + last) // 2
if target == nums[mid]:
return mid
elif target < nums[mid]:
last = mid - 1
else:
first = mid + 1
if target > nums[mid]:
return mid + 1
else:
return mid