作业9:
使用二分查找算法来解决这个问题,首先需要找到数组的中间元素,然后比较它与目标值的关系。如果中间元素等于目标值,则返回中间元素的下标;如果中间元素小于目标值,则在右半部分继续查找;如果中间元素大于目标值,则在左半部分继续查找。重复这个过程,直到找到目标值或者搜索范围为空。
依旧是使用二分查找算法,nums
是输入的排序数组,target
是目标值。函数返回的是目标值在数组中的索引,如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
标准的二分查找target,记选出的数字为 pick ,猜测的数字为 x 。根据题目描述,若 guess ( x ) ≤ 0 则说明 x ≥ pick,否则 x < pick。根据这一性质可以使用二分查找来求出答案 pick。二分时,记当前区间为 [ left , right ],初始时 left = 1,right = n。记区间中间元素为 mid,若有 guess ( mid ) ≤0 则说明 pick ∈ [ left , mid ],否则 pick ∈ [ mid+1 , right ]。当区间左右端点相同时,则说明找到了答案,退出循环。
作业10:
需要找到一个非负整数 x 的平方根。为了找到平方根,可以使用二分查找的方法,从0到x之间进行查找。当找到一个数 a ,使得 a * a <= x < (a + 1) * (a + 1) 时,a 就是 x 的平方根的整数部分。由于返回类型是整数,我们可以对 a 进行取整操作,得到 x 的算术平方根。
经典的双指针问题,由于数组已经按非递减顺序排列,可以从数组的两端开始搜索,如果两端的数之和大于目标数,那么较小的数一定在另一端,反之亦然。这样,就可以在 O(n) 的时间复杂度内找到答案。首先初始化两个指针 left 和 right,分别指向数组的开始和结束。然后进入一个循环,只要 left < right,我们就继续搜索。在循环中,首先检查 left 和 right 指向的两个数之和是否等于目标数,如果是,就找到了答案,返回这两个数的下标;如果不是,就根据两数之和与目标数的大小关系,移动 left 或 right 指针,缩小搜索范围。如果最后没有找到答案,就返回一个空列表。
可以使用二分查找来解决。船的最低运载能力必定在包裹中的最大重量和所有包裹重量之和之间。因此,可以使用二分查找来缩小这个范围,直到找到最低的船的运载能力。在二分查找的每一步中,将当前的运载能力设为左右边界的中间值,然后模拟运输的过程,统计需要的天数。如果需要的天数小于或等于给定的天数,说明当前的运载能力可能是一个解,将右边界缩小为中间值;否则,说明当前的运载能力太小,将左边界增大为中间值加一。
作业11:
可以使用二分查找来解决。错误的版本一定在某个范围内,这个范围可以从最小版本到最大版本。因此,可以使用二分查找来缩小这个范围,直到找到第一个错误的版本。在二分查找的每一步中,将当前的版本设为左右边界的中间值,然后调用 isBadVersion 函数来判断这个版本是否出错。如果出错,说明错误的版本在当前版本或之后,将左边界缩小为中间值;否则,说明错误的版本在当前版本之前,将右边界缩小为中间值加一。
初始化左指针 left
和右指针 right
分别指向数组的第一个元素和最后一个元素。进入循环,计算中间指针 mid
。如果中间元素等于目标值,则返回中间元素的下标。如果左侧元素小于等于中间元素,说明左侧区间是单调递增的。此时,如果目标值在左侧区间内,则将右指针移动到中间元素的左侧;否则将左指针移动到中间元素的右侧。如果左侧元素大于中间元素,说明旋转点在中间元素的左侧,右侧区间是单调递增的。此时,如果目标值在右侧区间内,则将左指针移动到中间元素的右侧;否则将右指针移动到中间元素的左侧。如果循环结束仍未找到目标值,则返回 -1。时间复杂度为 O(log n),其中 n 是数组的长度。
由于数组最初是升序排列的,那么经过旋转后,数组的前半部分都大于后半部分。可以利用这个特性来进行二分查找。首先,初始化两个指针,一个指向数组的起始位置,一个指向数组的结束位置。然后,取中间的元素作为当前的元素。如果中间的元素大于结束位置的元素,那么最小元素一定在数组的右半部分,更新起始位置为中间元素的下一个位置。如果中间的元素小于结束位置的元素,那么最小元素一定在数组的左半部分或者就是当前中间元素,更新结束位置为中间元素的前一个位置。如果中间的元素等于结束位置的元素,那么最小元素就是当前中间元素,直接返回这个元素。这样,就可以在 O(log n) 的时间复杂度内找到数组中的最小元素。