搜索旋转排序数组(二分查找)

测试链接:https://leetcode.cn/problems/search-in-rotated-sorted-array/https://leetcode.cn/problems/search-in-rotated-sorted-array/https://leetcode.cn/problems/search-in-rotated-sorted-array/

问题描述

假设我们有一个旋转排序的数组,这个数组本身是一个升序数组,但是由于某种原因,它被旋转了一定的次数。我们要在这个数组中查找一个目标值。如果找到了目标值,返回其索引;如果没有找到,返回 -1。

旋转排序数组

比如一个升序排列的数组 [1, 2, 3, 4, 5, 6, 7] 被旋转过一次,得到 [4, 5, 6, 7, 1, 2, 3]。显然,原数组被旋转了 3 次。

这个旋转数组的特点是数组的前部分是递增的,后部分也是递增的,且存在一个旋转点使得数组的递增顺序断裂。通过这个特性,我们可以修改标准的二分查找算法来适应旋转排序数组的查找。

二分查找的修改版

思路

我们依然使用二分查找的基本思想:通过比较中间元素与目标值,决定继续查找的区间。不同的是,在旋转数组中,数组的两端(左端和右端)可能并非严格按顺序排列,这就要求我们在判断目标值和区间时多加小心。

  1. 首先判断中间元素与目标值:如果找到目标元素,直接返回索引。
  2. 处理重复元素的情况:如果左右元素相同,即 nums[l] == nums[m] == nums[r],则无法判断当前区间是有序还是无序的,因此只能通过将 l++r-- 来缩小查找区间。
  3. 判断区间的有序性:在每一次循环中,检查当前区间是有序的还是旋转的:
    • 如果左半部分是有序的,即 nums[l] <= nums[m],我们可以判断目标是否在左半部分。如果目标值在左半部分,则调整右边界;否则,调整左边界。
    • 如果右半部分是有序的,即 nums[m] <= nums[r],同样地,我们可以判断目标是否在右半部分。

实现

下面是针对旋转排序数组的二分查找实现:

class Solution {public int search(int[] nums, int target) {int l = 0;int r = nums.length - 1;while (l <= r) {int m = l + (r - l) / 2;  // 防止溢出if (nums[m] == target) {return m;  // 找到目标,返回索引}// 如果左右两端元素相同,无法确定哪一部分有序,直接移动边界if (nums[l] == nums[m] && nums[m] == nums[r]) {l++;r--;} // 如果左半部分是有序的else if (nums[l] <= nums[m]) {// 判断目标值是否在左半部分if (nums[l] <= target && target < nums[m]) {r = m - 1;} else {l = m + 1;}} // 如果右半部分是有序的else {// 判断目标值是否在右半部分if (nums[m] < target && target <= nums[r]) {l = m + 1;} else {r = m - 1;}}}return -1;  // 如果没有找到目标,返回-1}
}

关键点解析

  1. nums[l] == nums[m] == nums[r]:这是一个特殊情况,表示左端、右端和中间元素相等。在这种情况下,我们无法确定左半部分或右半部分是否有序,因此只能通过缩小边界来逐步排除元素。
  2. 区间有序性判断:每次选择中间元素后,通过判断左半部分或右半部分是否有序,来决定目标值的查找区间。
  3. 时间复杂度:在最坏情况下,当左右边界元素相同并且无法判断有序性时,我们会减少一个元素。因此,最坏情况下时间复杂度为 O(n)O(n)O(n),但通常情况的时间复杂度是 O(log⁡n)O(\log n)O(logn)。

大白话就是:先判断num[m]是否等于target,等于则直接返回索引m,如果不等,则继续判断。如果左右边界相等则无法判断哪一部分有序(若数组元素有序且无重复则无需做此判断,详见搜索旋转排序数组2),此时l++,r--移动左右边界;然后判断左右部分哪一部分有序,如果有序,则判断目标值是否在那一部分。

 

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

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

相关文章

JavaScript中的数组方法总结+详解

在JS中,数组方法是非常重要且常用的方法.在此整理总结一番. 1. javaScript常用数组方法 2.方法详解 1.push(); 功能: 在数组最后一位添加一个或多个元素,并返回新数组的长度,改变原数组.(添加多个元素用逗号隔开) var arr [1, 2, "c"];var rel arr.push(&q…

「全网最细 + 实战源码案例」设计模式——桥接模式

核心思想 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;将抽象部分与其实现部分分离&#xff0c;使它们可以独立变化。降低代码耦合度&#xff0c;避免类爆炸&#xff0c;提高代码的可扩展性。 结构 1. Implementation&#xff08;实现类…

动态规划DP 背包问题 完全背包问题(题目分析+C++完整代码)

概览检索 动态规划DP 概览&#xff08;点击链接跳转&#xff09; 动态规划DP 背包问题 概览&#xff08;点击链接跳转&#xff09; 完全背包问题 原题链接 AcWiing 3. 完全背包问题 题目描述 有 N种物品和一个容量是 V的背包&#xff0c;每种物品都有无限件可用。 第 i种物…

开源智慧园区管理系统对比五款主流产品探索智能运营新模式

内容概要 在这个数字化迅速发展的时代&#xff0c;园区管理也迎来了全新的机遇和挑战。众所周知&#xff0c;开源智慧园区管理系统作为一种创新解决方案&#xff0c;正逐步打破传统管理的局限性。它的开放性不仅使得系统可以根据具体需求进行灵活调整&#xff0c;也为用户提供…

Unity实现按键设置功能代码

一、前言 最近在学习unity2D&#xff0c;想做一个横版过关游戏&#xff0c;需要按键设置功能&#xff0c;让用户可以自定义方向键与攻击键等。 自己写了一个&#xff0c;总结如下。 二、界面效果图 这个是一个csv文件&#xff0c;准备第一列是中文按键说明&#xff0c;第二列…

稀疏混合专家架构语言模型(MoE)

注&#xff1a;本文为 “稀疏混合专家架构语言模型&#xff08;MoE&#xff09;” 相关文章合辑。 手把手教你&#xff0c;从零开始实现一个稀疏混合专家架构语言模型&#xff08;MoE&#xff09; 机器之心 2024年02月11日 12:21 河南 选自huggingface 机器之心编译 机器之心…

C++哈希(链地址法)(二)详解

文章目录 1.开放地址法1.1key不能取模的问题1.1.1将字符串转为整型1.1.2将日期类转为整型 2.哈希函数2.1乘法散列法&#xff08;了解&#xff09;2.2全域散列法&#xff08;了解&#xff09; 3.处理哈希冲突3.1线性探测&#xff08;挨着找&#xff09;3.2二次探测&#xff08;跳…

29.Word:公司本财年的年度报告【13】

目录 NO1.2.3.4 NO5.6.7​ NO8.9.10​ NO1.2.3.4 另存为F12&#xff1a;考生文件夹&#xff1a;Word.docx选中绿色标记的标题文本→样式对话框→单击右键→点击样式对话框→单击右键→修改→所有脚本→颜色/字体/名称→边框&#xff1a;0.5磅、黑色、单线条&#xff1a;点…

深入理解Java引用传递

先看一段代码&#xff1a; public static void add(String a) {a "new";System.out.println("add: " a); // 输出内容&#xff1a;add: new}public static void main(String[] args) {String a null;add(a);System.out.println("main: " a);…

Python从零构建macOS状态栏应用(仿ollama)并集成AI同款流式聊天 API 服务(含打包为独立应用)

在本教程中,我们将一步步构建一个 macOS 状态栏应用程序,并集成一个 Flask 服务器,提供流式响应的 API 服务。 如果你手中正好持有一台 MacBook Pro,又怀揣着搭建 AI 聊天服务的想法,却不知从何处迈出第一步,那么这篇文章绝对是你的及时雨。 最终,我们将实现以下功能: …

Qt之数据库操作三

主要介绍qt框架中对数据库的增加&#xff0c;删除和修改功能。 软件界面如下 程序结构 tdialogdata.h中代码 #ifndef TDIALOGDATA_H #define TDIALOGDATA_H#include <QDialog> #include<QSqlRecord> namespace Ui { class TDialogData; }class TDialogData : pub…

neo4j入门

文章目录 neo4j版本说明部署安装Mac部署docker部署 neo4j web工具使用数据结构图数据库VS关系数据库 neo4j neo4j官网Neo4j是用ava实现的开源NoSQL图数据库。Neo4作为图数据库中的代表产品&#xff0c;已经在众多的行业项目中进行了应用&#xff0c;如&#xff1a;网络管理&am…

JVM-运行时数据区

JVM的组成 运行时数据区-总览 Java虚拟机在运行Java程序过程中管理的内存区域&#xff0c;称之为运行时数据区。 《Java虚拟机规范》中规定了每一部分的作用 运行时数据区-应用场景 Java的内存分成哪几部分&#xff1f; Java内存中哪些部分会内存溢出&#xff1f; JDK7 和J…

Java篇之继承

目录 一. 继承 1. 为什么需要继承 2. 继承的概念 3. 继承的语法 4. 访问父类成员 4.1 子类中访问父类的成员变量 4.2 子类中访问父类的成员方法 5. super关键字 6. super和this关键字 7. 子类构造方法 8. 代码块的执行顺序 9. protected访问修饰限定符 10. 继承方式…

leetcode——验证二叉搜索树(java)

给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含小于当前节点的数。 节点的右子树只包含 大于 当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff1a; 输入…

家居EDI:Hom Furniture EDI需求分析

HOM Furniture 是一家成立于1977年的美国家具零售商&#xff0c;总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品&#xff0c;满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…

Spring Boot + Facade Pattern : 通过统一接口简化多模块业务

文章目录 Pre概述在编程中&#xff0c;外观模式是如何工作的&#xff1f;外观设计模式 UML 类图外观类和子系统的关系优点案例外观模式在复杂业务中的应用实战运用1. 项目搭建与基础配置2. 构建子系统组件航班服务酒店服务旅游套餐服务 3. 创建外观类4. 在 Controller 中使用外…

八、Spring Boot 日志详解

目录 一、日志的用途 二、日志使用 2.1 打印日志 2.1.1 在程序中获取日志对象 2.1.2 使用日志对象打印日志 2.2、日志框架介绍 2.2.1 门面模式(外观模式) 2.2.2 门面模式的实现 2.2.3 SLF4J 框架介绍 2.3 日志格式的说明 2.4 日志级别 2.4.1 日志级别的分类 2.4.2…

创建前端项目的方法

目录 一、创建前端项目的方法 1.前提&#xff1a;安装Vue CLI 2.方式一&#xff1a;vue create项目名称 3.方式二&#xff1a;vue ui 二、Vue项目结构 三、修改Vue项目端口号的方法 一、创建前端项目的方法 1.前提&#xff1a;安装Vue CLI npm i vue/cli -g 2.方式一&…

(leetcode 213 打家劫舍ii)

代码随想录&#xff1a; 将一个线性数组换成两个线性数组&#xff08;去掉头&#xff0c;去掉尾&#xff09; 分别求两个线性数组的最大值 最后求这两个数组的最大值 代码随想录视频 #include<iostream> #include<vector> #include<algorithm> //nums:2,…