大厂面试高频题——二分查找

news/2024/10/6 23:56:04/文章来源:https://www.cnblogs.com/forrestr/p/18290406

35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。

思考

二分模板题

class Solution:def searchInsert(self, nums: List[int], target: int) -> int:left = 0 right = len(nums)#[left,right)while left<right:mid = int((left+right)/2)if nums[mid] > target:right = midelif nums[mid] < target:left = mid + 1else:return midreturn left

BM21 旋转数组的最小数字(有重复数字)

思考

剑指offer上原题。数组划分为2个区间,二分搜索逐渐逼近最小值。遇到无法判断区间时,需要顺序逐个查找。

class Solution:def minNumberInRotateArray(self , nums: List[int]) -> int:# write code hereleft = 0right = len(nums)-1mid = 0while nums[left]>=nums[right]:if right-left == 1:return nums[right]mid = int((left+right)/2)if nums[left] == nums[right] and nums[left] == nums[mid]:res = nums[left]for i in range(left+1,right+1):if nums[i] < res:res = nums[i]return resif nums[mid] >= nums[left]:left = midelif nums[mid] <= nums[right]:right = midreturn nums[left]
  1. 搜索旋转排序数组 (无重复数字搜索指定target)
    整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

思考

根据mid值判断是左有序 还是 右有序。在有序的区间内进行二分查找。

class Solution:def search(self, nums: List[int], target: int) -> int:left = 0right = len(nums)-1#[left,right]mid = -1while left<=right:mid = int((left+right)/2)if nums[mid] == target:return midif nums[mid] >= nums[left]:#左有序if target >= nums[left] and target < nums[mid]:# 二分right = mid - 1else:left = mid + 1else:#右有序if target > nums[mid] and t arget <= nums[right]:left = mid + 1else:right = mid -1return -1

153.寻找旋转排序数组中的最小值(无重复)

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

思考

比有重复的要简单一点。两种方法。
方法1:剑指offer版本,比较容易理解:划分为2个区间,逐渐逼近结果。

class Solution:def findMin(self, nums: List[int]) -> int:left = 0right = len(nums)-1mid = 0while nums[left] > nums[right]:if right - left == 1:return nums[right]mid = (left+right)//2if nums[mid] >= nums[left]:left = midelif nums[mid] <=nums[right]:right = midreturn nums[0]

方法2:leetcode官方题解。
在二分查找的每一步中,左边界为 low,右边界为 high,区间的中点为 pivot,最小值就在该区间内。我们将中轴元素 nums[pivot] 与右边界元素 nums[high] 进行比较,可能会有以下的三种情况:


class Solution:def findMin(self, nums: List[int]) -> int:left = 0right = len(nums)-1mid = 0while left < right:mid = (left+right)//2if nums[mid] < nums[-1]:right = midelse:left = mid + 1return nums[left]

34. 在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

思考

划分为2个区间 <target 和 >=target 来寻找左边界。
右边界通过寻找targe+1的左边界-1来代替。优雅

class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:def getRightBorder(nums, target):left = 0 right = len(nums)-1#right_border = -2while left<=right:mid = int((left+right)/2)if nums[mid] > target:right = mid - 1else:left = mid + 1return rightdef getLeftBorder(nums, target):left = 0 right = len(nums)-1#left_border = -2while left<=right:mid = int((left+right)/2)if nums[mid] < target:left = mid + 1else:right = mid - 1#left_border = rightreturn leftleft_border = getLeftBorder(nums, target)#right_border = getRightBorder(nums,target)right_border = getLeftBorder(nums, target+1) - 1if left_border == len(nums) or nums[left_border] != target:return [-1,-1]else:return [left_border,right_border]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/740670.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何解决网页打开加载缓慢问题

以我为例 今天打开B站发现很多视频打开之后一直是加载状态,加载半天也打不开,还有知乎跳转到csdn也无法正常打自己捣鼓的许久发现可以通过修改DNS来解决 首先打开此电脑→找到网络→右键点击属性→左上角更改适配器设置→选择你的网络双击→点击属性→找到Internet 协议版本4…

服务器开发——setsockopt函数

setsockopt() setsockopt() 是一个用于设置套接字选项的 Unix 系统调用。它允许程序员修改套接字的行为,以适应不同的网络环境和应用程序需求。 1. 函数介绍 函数原型: #include <sys/socket.h> /*** level:选项所在的协议层。例如,SOL_SOCKET 表示套接字层,IPPRO…

Python OpenCv对规则物体进行实时检测

很多情况需要对物体进行检测,常规的方法也有很多种。但是检测出来的边缘一般都是非常多,结果也是非常杂乱的,显然这种结果不是我们想要的。如果颜色相较于背景非常鲜艳的可以调节hsv阈值再进行检测,如果是一直在运动的物体可以通过帧差法进行物体检测,还有很多高深的算法也…

学习canvas(一些常用api)

当然,以下是这些常用Canvas API的总结,按照Markdown格式编写: 常用Canvas API总结 1. 获取绘图上下文 const canvas = document.getElementById(myCanvas); const ctx = canvas.getContext(2d); // 或 webgl2. 绘制矩形 ctx.fillStyle = blue; ctx.fillRect(10, 10, 150, 10…

uniapp 解决本地跨域问题

让每一滴智慧绘制成一条不归路!

UniVAE:基于Transformer的单模型、多尺度的VAE模型

大家都知道,Transformer的$\mathscr{O}(n^2)$复杂度是它的“硬伤”之一。不过凡事有弊亦有利,$\mathscr{O}(n^2)$的复杂度也为Transformer带来很大的折腾空间,我们可以灵活地定制不同的attention mask,来设计出不同用途的Transformer模型来,比如UniLM、K-BERT等。 本文介绍…

从变分编码、信息瓶颈到正态分布:论遗忘的重要性

这是一篇“散文”,我们来谈一下有着千丝万缕联系的三个东西:变分自编码器、信息瓶颈、正态分布。 众所周知,变分自编码器是一个很经典的生成模型,但实际上它有着超越生成模型的含义;而对于信息瓶颈,大家也许相对陌生一些,然而事实上信息瓶颈在去年也热闹了一阵子;至于正…

应用升级

本文是在你已经安装三个软件的基础上进行优化 一、卸载NFG Multi Crack软件(没有就不用管) 二、进入Lsposed软件 点击模块,可以看到已安装的两个模块1. 点击FL-Xposed,勾选以下应用,然后返回2. 点击HookVip,勾选Fakelocation,然后返回三、进入隐藏应用列表软件 1. 点击模…

哪些方法可以将word导出为pdf格式?

在日常工作和学习中,我们经常需要将Word文档转换为PDF格式,以便更好地保存、分享和打印文件。PDF格式具有跨平台兼容性好、不易被篡改等优点,因此得到了广泛应用。那么Word如何转PDF呢?本文将介绍三种实用的word转pdf的方法,帮助读者轻松实现文档格式的转换。 方法一:使用…

2024春秋杯 stdout

考点:文件,setvbuf缓冲区,ret2syscall,ret2csu 题目给了libc文件。 main函数和vlun函数存在明显的栈溢出 int __cdecl main(int argc, const char **argv, const char **envp) {char buf[80]; // [rsp+0h] [rbp-50h] BYREFinit(argc, argv, envp);puts("where is my s…

怎么看时序图

时序图看法 从上到下,从左到右 看一个单位时间,拆分成一个一个模块 简单的时序图,一根线串口通信SPIS时序图总体传输24个bit注意无效电平可能传输不同的电平

工程仪器振弦采集仪的设计与研发进展

工程仪器振弦采集仪的设计与研发进展 工程仪器振弦采集仪是一种用于测量和记录物体振动参数的仪器。它能够实时采集物体的振动信号,并通过内部的传感器将振动信号转化为电信号,然后进行信号放大和处理,最终以数字形式显示或存储。 河北稳控科技振弦采集仪的设计与研发进展主…