开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情
作者: 千石
支持:点赞、收藏、评论
欢迎各位在评论区交流
前言
本文内容来自我平时学习的一些积累,如有错误,还请指正
在题目实战部分,我将代码实现和代码解释设置在了解题思路的下方,方便各位作为参考刷题
一些话
本文内容来自我平时学习的一些积累,如有错误,还请指正
在题目实战部分,我将代码实现和代码解释设置在了解题思路的下方,方便各位作为参考刷题
题目练习步骤:
- 给自己10分钟,读题并思考解题思路
- 有了思路以后开始写代码,如果在上一步骤中没有思路则停止思考并且看该题题解
- 在看懂题解(暂时没看懂也没关系)的思路后,背诵默写题解,直至能熟练写出来
- 隔一段时间,再次尝试写这道题目
前置知识
二分查找的前提
- 目标函数单调性(单调递增或者递减)
- 存在上下界
- 能够通过索引访问
代码模板
left, right = 0, len(array)-1
while left <= right:
mid = (left + right)/2
if array[mid]==target:
# find the target
break or return result
elif array[mid]<targ:
left=mid+1
else:
right = mid -1
Eg:在递增数组里,查找31
10,14,19,26,27,31,33,35,42,44
题目
69. x 的平方根
思路一:二分查找法
对于一个非负整数 x,从 0 到 x/2+1 中查找算术平方根。每次查找平方根的结果 res,通过比较 res * res 和 x 的大小关系来更新查找的范围。如果 res * res 等于 x,则直接返回 res,否则如果 res * res 小于 x,说明算术平方根在 res 的右边,更新查找的左边界,反之更新查找的右边界。
class Solution:
def mySqrt(self, x: int) -> int:
if x == 0:
return 0
left, right = 1, x // 2 + 1
while left < right:
mid = (left + right + 1) // 2
if mid * mid > x:
right = mid - 1
else:
left = mid
return left
复杂度分析:
- 时间复杂度:O(log(x)),二分查找的时间复杂度。
- 空间复杂度:O(1),仅需要常数空间。
思路二:牛顿迭代法
牛顿迭代法是一种数值解法,通过迭代的方式求出函数的零点。在求算术平方根的问题中,使用牛顿迭代法,先随意猜测一个平方根的值,然后使用公式:res = (res + x/res) / 2 来迭代求解算术平方根的值。
class Solution:
def mySqrt(self, x: int) -> int:
if x == 0:
return 0
res = x
while res * res > x:
res = (res + x / res) // 2
return int(res)
复杂度分析:
- 时间复杂度:O(log(x)),通过每次迭代,误差的大小会接近于原来的一半,因此总的迭代次数是 log(x) 级别的。
- 空间复杂度:O(1),仅需要常数空间。
33. 搜索旋转排序数组
思路:二分查找
- 对于有序数组nums,使用二分查找,通过比较中间值与目标值的大小关系,将查询范围缩小为一半,并在其中继续查找目标值。
- 对于旋转后的数组,通过比较nums[start]与nums[mid]的大小关系,可以判断出前半部分是否有序,并缩小查找范围。
- 如果nums[start]<=nums[mid],说明前半部分有序,此时可以通过比较target与nums[mid]的大小关系缩小查找范围。
- 如果nums[start]>nums[mid],说明前半部分无序,此时可以通过比较target与nums[start]的大小关系缩小查找范围。
class Solution:
def search(self, nums: List[int], target: int) -> int:
start, end = 0, len(nums) - 1
while start <= end:
mid = (start + end) // 2
if nums[mid] == target:
return mid
if nums[start] <= nums[mid]:
if target >= nums[start] and target < nums[mid]:
end = mid - 1
else:
start = mid + 1
else:
if target <= nums[end] and target > nums[mid]:
start = mid + 1
else:
end = mid - 1
return -1