力扣第三十三题——搜索旋转排序数组

内容介绍

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k0 <= 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) 的算法解决此问题。

示例 1:

输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4

示例 2:

输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1

示例 3:

输入:nums = [1], target = 0
输出:-1

提示:

  • 1 <= nums.length <= 5000
  • -104 <= nums[i] <= 104
  • nums 中的每个值都 独一无二
  • 题目数据保证 nums 在预先未知的某个下标上进行了旋转
  • -104 <= target <= 104

完整代码

 class Solution {public int search(int[] nums, int target) {int n = nums.length;if (n == 0) {return -1;}if (n == 1) {return nums[0] == target ? 0 : -1;}int l = 0, r = n - 1;while (l <= r) {int mid = (l + r) / 2;if (nums[mid] == target) {return mid;}if (nums[0] <= nums[mid]) {if (nums[0] <= target && target < nums[mid]) {r = mid - 1;} else {l = mid + 1;}} else {if (nums[mid] < target && target <= nums[n - 1]) {l = mid + 1;} else {r = mid - 1;}}}return -1;}
}

思路详解

方法概述

search方法实现了一个改进的二分查找算法,适用于经过旋转的有序数组。旋转数组的特点是,数组的一部分是有序的,另一部分也是有序的,但是两部分之间的顺序被打乱了。

思路详解

  1. 边界情况处理

    • 如果数组长度为0,直接返回-1,因为没有元素可以查找。
    • 如果数组长度为1,检查该元素是否为目标值,如果是则返回索引0,否则返回-1。
  2. 初始化二分查找的左右指针

    • l(左指针)初始化为0。
    • r(右指针)初始化为数组长度减1。
  3. 二分查找循环

    • l小于等于r时,进行以下操作:
      • 计算中间位置mid
      • 如果nums[mid]等于目标值target,直接返回mid
  4. 判断中间位置的元素与数组首元素的关系

    • 如果nums[0]小于等于nums[mid],说明左半部分是有序的:
      • 如果目标值targetnums[0]nums[mid]之间,则将右指针r移动到mid - 1
      • 否则,将左指针l移动到mid + 1
    • 如果nums[0]大于nums[mid],说明右半部分是有序的:
      • 如果目标值targetnums[mid]nums[n - 1]之间,则将左指针l移动到mid + 1
      • 否则,将右指针r移动到mid - 1
  5. 循环结束

    • 如果循环结束还没有找到目标值,说明目标值不在数组中,返回-1。

代码注释

以下是代码中关键步骤的注释:

public int search(int[] nums, int target) {int n = nums.length;if (n == 0) {return -1; // 数组为空,直接返回-1}if (n == 1) {return nums[0] == target ? 0 : -1; // 数组只有一个元素,检查是否为目标值}int l = 0, r = n - 1;while (l <= r) {int mid = (l + r) / 2; // 计算中间位置if (nums[mid] == target) {return mid; // 找到目标值,返回索引}if (nums[0] <= nums[mid]) {// 左半部分有序if (nums[0] <= target && target < nums[mid]) {r = mid - 1; // 目标值在左半部分} else {l = mid + 1; // 目标值在右半部分}} else {// 右半部分有序if (nums[mid] < target && target <= nums[n - 1]) {l = mid + 1; // 目标值在右半部分} else {r = mid - 1; // 目标值在左半部分}}}return -1; // 未找到目标值,返回-1
}

知识点精炼

 

二分查找算法(Binary Search)

  • 基本概念:一种在有序数组中查找特定元素的搜索算法,通过不断将搜索区间减半来提高搜索效率。
  • 时间复杂度:O(log n),其中n是数组的长度。

2. 循环数组的处理

  • 旋转数组:一个有序数组在某些点上被旋转,使得数组的一部分有序,另一部分同样有序,但整体不再有序。
  • 二分查找的适应:通过比较中间元素与数组首元素,确定哪部分是有序的,从而决定搜索方向。

3. 边界条件处理

  • 空数组:如果数组为空,直接返回-1,因为没有元素可以查找。
  • 单元素数组:如果数组只有一个元素,直接比较该元素与目标值。

4. 循环与递归的选择

  • 循环实现:使用while循环进行二分查找,避免了递归可能带来的额外开销。

5. 中间位置的取值

  • 防止溢出:使用(l + r) / 2计算中间位置,而非(l + r) >> 1,虽然后者在位运算上更高效,但在此场景下避免了整型溢出的风险。

6. 搜索区间的调整

  • 左半部分有序:如果中间元素大于等于首元素,说明左半部分是有序的,根据目标值的位置调整搜索区间。
  • 右半部分有序:如果中间元素小于首元素,说明右半部分是有序的,同样根据目标值的位置调整搜索区间。

7. 返回结果

  • 找到目标值:如果中间元素等于目标值,返回中间位置的索引。
  • 未找到目标值:如果循环结束仍未找到目标值,返回-1。

8. 算法优化

  • 避免重复比较:在每次循环中,仅比较一次中间元素与目标值,减少了不必要的比较次数。

通过以上知识点,我们可以看到,虽然代码实现的是二分查找,但针对旋转数组的特性进行了适当的调整,使得算法能够适应这种特殊的有序数组。这些知识点对于理解和实现高效的搜索算法至关重要。

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

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

相关文章

UDP进行端口转发时,数据丢失率太高怎么办

在网络通信中,UDP (用户数据报协议) 因其低延迟和高效率而被广泛使用。然而,当使用UDP进行端口转发时,我们可能会遇到数据丢失率高的问题。本文将探讨这个问题的原因及其解决方案,特别关注如何通过调整缓冲区大小来改善情况。 问题根源 UDP数据包丢失可能由多种因素导致,包括…

UDP/TCP协议解析

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

Elasticsearch:跨集群使用 ES|QL

警告&#xff1a;ES|QL 的跨集群搜索目前处于技术预览阶段&#xff0c;可能会在未来版本中更改或删除。Elastic 将努力解决任何问题&#xff0c;但技术预览中的功能不受官方 GA 功能的支持 SLA 约束。 使用 ES|QL&#xff0c;你可以跨多个集群执行单个查询。 前提&#xff1a; …

实战解读:Llama Guard 3 Prompt Guard

前序研究&#xff1a;实战解读&#xff1a;Llama 3 安全性对抗分析 近日&#xff0c;腾讯朱雀实验室又针对 Llama 3.1 安全性做了进一步解读。 2024年7月23日晚&#xff0c;随着Llama3.1的发布&#xff0c;Meta正式提出了“Llama系统”的概念&#xff0c;通过系统级的安全组件对…

谷粒商城实战笔记-62-商品服务-API-品牌管理-OSS整合测试

文章目录 一&#xff0c;Java中上传文件到阿里云OSS1&#xff0c;整合阿里云OSS2&#xff0c;测试上传文件 二&#xff0c;Java中整合阿里云OSS服务指南引言准备工作1. 注册阿里云账号2. 获取Access Key3. 添加依赖 实现OSS客户端1. 初始化OSSClient2. 创建Bucket3. 上传文件4.…

自定义 RAG 工作流:在 IDE 中结合 RAG 编排,构建可信的编码智能体

构建编码智能体并非一件容易的事。结合我们在 AutoDev、ArchGuard Co-mate、ChocoBuilder 等智能体项目的经验&#xff0c;我们开始思考在 Shire 语言中提供一种新的 RAG 工作流。结合我们先前构建的 IDE 基础设施&#xff08;代码生成、代码校验、代码执行等接口&#xff09;&…

基于PaddleClas的人物年龄分类项目

目录 一、任务概述 二、算法研发 2.1 下载数据集 2.2 数据集预处理 2.3 安装PaddleClas套件 2.4 算法训练 2.5 静态图导出 2.6 静态图推理 三、小结 一、任务概述 最近遇到个需求&#xff0c;需要将图像中的人物区分为成人和小孩&#xff0c;这是一个典型的二分类问题…

AI学习指南机器学习篇-SOM在数据聚类和可视化中的应用

AI学习指南机器学习篇 - SOM在数据聚类和可视化中的应用 引言 在机器学习领域&#xff0c;数据聚类和可视化是非常重要的任务。传统的聚类算法如K-means、DBSCAN等在一些场景下表现良好&#xff0c;但对于高维数据的聚类和可视化而言&#xff0c;它们的效果会受到限制。Self-…

Leetcode3219. 切蛋糕的最小总开销 II

Every day a Leetcode 题目来源&#xff1a;3219. 切蛋糕的最小总开销 II 解法1&#xff1a;贪心 谁的开销更大&#xff0c;就先切谁&#xff0c;并且这个先后顺序与切的次数无关。 代码&#xff1a; /** lc appleetcode.cn id3219 langcpp** [3219] 切蛋糕的最小总开销 I…

ubuntu20.04服务器搭建mongodb7

安装参考自mongo官网&#xff1a;在 Ubuntu 上安装 MongoDB Community Edition - MongoDB 手册 v7.0 MongoDB 版本 本教程安装的是 MongoDB 7.0 Community Edition。想要安装不同版本的 MongoDB Community Edition&#xff0c;请移步本页面左上角的版本下拉菜单&#xff0c;选…

ubuntu递归下载deb安装包,解决离线依赖问题

ubuntu递归下载安装包 主要针对离线环境的电脑安装deb包。 将下面的build-essential换成自己需要安装的包&#xff0c;虽然下面代码会递归下载依赖安装包&#xff0c;但是在离线环境下仍然可能会出现依赖包为配置问题。 因此&#xff0c;根据报错&#xff0c;手动递归下载报错…

【SQL 新手教程 1/20】SQL语言MySQL数据库 简介

&#x1f497; 什么是SQL&#xff1f;⭐ (Structured Query Language) 结构化查询语言&#xff0c;是访问和处理关系数据库的计算机标准语言 无论用什么编程语言&#xff08;Java、Python、C……&#xff09;编写程序&#xff0c;只要涉及到操作关系数据库都必须通过SQL来完成 …

4招清洁法,清理电脑无死角,焕然一新效率高

随着时间的积累&#xff0c;电脑内部可能会堆积起大量的垃圾文件、缓存数据和无用程序。因此&#xff0c;定期清理电脑是很有必要的。为了让你的电脑重新焕发生机&#xff0c;提高工作效率&#xff0c;本文将为你介绍4招实用的清洁法&#xff0c;助你轻松清理电脑死角&#xff…

js 数组常用函数总结

目录 1、push 2、unshif 3、pop 4、shift 5、concat 6、slice 7、splice 8、join 9、indexOf 10、lastIndexOf 11、forEach 12、map 13、filter 14、reduce 15、sort 16、reverse 17、includes 18、some 19、every 20、toString 21.、find 22、findLast 23、…

JavaWeb学习——请求响应、分层解耦

目录 一、请求响应学习 1、请求 简单参数 实体参数 数组集合参数 日期参数 Json参数 路径参数 总结 2、响应 ResponseBody&统一响应结果 二、分层解耦 1、三层架构 三层架构含义 架构划分 2、分层解耦 引入概念 容器认识 3、IOC&DI入门 4、IOC详解 …

Cadence23学习笔记(十四)

ARC就是圆弧走线的意思&#xff1a; 仅打开网络的话可以只针对net进行修改走线的属性&#xff1a; 然后现在鼠标左键点那个走线&#xff0c;那个走线就会变为弧形&#xff1a; 添加差分对&#xff1a; 之后&#xff0c;分别点击两条线即可分配差分对&#xff1a; 选完差分对之后…

微服务实践和总结

H5原生组件web Component Web Component 是一种用于构建可复用用户界面组件的技术&#xff0c;开发者可以创建自定义的 HTML 标签&#xff0c;并将其封装为包含逻辑和样式的独立组件&#xff0c;从而在任何 Web 应用中重复使用。 <!DOCTYPE html> <html><head…

css in js 相比较 css modules 有什么好处?

CSS-in-JS 和 CSS Modules 都是用于管理 React 组件样式的流行方案&#xff0c;它们各有优势。相比 CSS Modules&#xff0c;CSS-in-JS 的主要好处包括: 动态样式&#xff1a;CSS-in-JS 可以轻松创建基于 props 或状态的动态样式&#xff0c;更灵活地处理复杂的样式逻辑。 无需…

【vue3|第18期】Vue-Router路由的三种传参方式

日期:2024年7月17日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.408…

EtherNet/IP网络基础

EtherNet/IP&#xff08;Ethernet Industrial Protocol&#xff09;是一种用于工业自动化的通信协议&#xff0c;基于以太网技术。它允许设备和控制系统之间进行高效的数据交换和通信。以下是EtherNet/IP网络的基础知识。 1. 什么是EtherNet/IP&#xff1f; EtherNet/IP是由O…