【算法设计与分析】搜索旋转排序数组

news2025/1/11 22:51:31

       📝个人主页:五敷有你      

 🔥系列专栏:算法分析与设计

⛺️稳中求进,晒太阳

题目

整数数组 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

思路

二分查找

数组本身不是有序的,进行旋转后只保证了数组的局部是有序的,这还能进行二分查找吗?答案是可以的。

可以发现的是,我们将数组从中间分开成左右两部分的时候,一定有一部分的数组是有序的。拿示例来看,我们从 6 这个位置分开以后数组变成了 [4, 5, 6] 和 [7, 0, 1, 2] 两个部分,其中左边 [4, 5, 6] 这个部分的数组是有序的,其他也是如此。

        这启示我们可以在常规二分查找的时候查看当前 mid 为分割位置分割出来的两个部分 [l, mid] 和 [mid + 1, r] 哪个部分是有序的,并根据有序的那个部分确定我们该如何改变二分查找的上下界,因为我们能够根据有序的那部分判断出 target 在不在这个部分:

        在每一步循环中,计算当前中间元素的索引,并检查中间元素是否等于目标值。如果等于,则返回中间元素的索引。

        如果中间元素不等于目标值,则根据中间元素与左边界元素的关系来判断当前部分是否为升序序列。

        如果是升序序列,则判断目标值是否在该升序序列中,如果在,则将右边界移动到中间元素的左侧;如果不在,则将左边界移动到中间元素的右侧。

        如果不是升序序列,即处于旋转点右侧,则判断目标值是否在右半部分的升序序列中。如果在,则将左边界移动到中间元素的右侧;如果不在,则将右边界移动到中间元素的左侧。

        最终,如果找到目标值,则返回其索引;如果未找到,则返回 -1。

代码实现

class Solution {
    public int search(int[] nums, int target) {
     
        int right=nums.length-1;
        int left=0;
        while(left<=right){
            int middle=(left+right)/2;
            if(nums[middle]==target){
                 return middle;
            }else if(nums[middle]>=nums[left]){
               if(target>=nums[left]&&target<=nums[middle]){
                   right=middle-1;
               }else{
                   left=middle+1;
               }
               
            }else{
              //旋转点右边
              if(target<=nums[right]&&target>=nums[middle]){
                  left=middle+1;
              }else{
                  right=middle-1;
              }
            }
        }
        return -1;
    }
}

运行结果

时间复杂度 O(logn)

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

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

相关文章

【C++】 为什么多继承子类重写的父类的虚函数地址不同?『 多态调用汇编剖析』

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 本篇文章主要是为了解答有…

MATLAB计算极限和微积分

一.函数与极限 计算极限&#xff1a;lim(3*x^2/(2x1))&#xff0c;x分别趋于0和1&#xff0c;代码如下&#xff1a; syms x; limit(3*x*x/(2*x1),x,0) limit(3*x*x/(2*x1),x,1) 结果分别为0和1&#xff1a; 1.计算双侧极限 计算极限&#xff1a;lim(3*x^2/(2x1))&#xff0…

哈希表哈希桶(C++实现)

哈希的概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素 时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff0c;平衡树中为树的高度&#xff0c;即 O( l o g 2 N log_2 N log2​N)&…

JavaScript Let 块级作用域

JavaScript Let 学习手记 最近在学习 JavaScript ES6 (2015) 标准时&#xff0c;我发现了let这个关键字&#xff0c;它为声明变量提供了一种新的方式&#xff0c;而且这种方式具有块级作用域的特点&#xff0c;真的很有趣呢&#xff01; 理解块作用域 在 ES6 之前的版本中&a…

【html学习笔记】2.基本元素

1.标题 标题会自动粗体其中大写的内容&#xff0c;并带有换行的效果会使用<h1>到<h6>表示不同大小的标题 <h1>标题1</h1> <h2>标题2</h2> <h3>标题3</h3> <h4>标题4</h4> <h5>标题5</h5> <h6>…

【Web】从零开始的js逆向学习笔记(上)

目录 一、逆向基础 1.1 语法基础 1.2 作用域 1.3 窗口对象属性 1.4 事件 二、浏览器控制台 2.1 Network Network-Headers Network-Header-General Network-Header-Response Headers Network-Header-Request Headers 2.2 Sources 2.3 Application 2.4 Console 三、…

基于3种机器学习法的黄土高原农业干旱监测比较研究_王晓燕_2022

基于3种机器学习法的黄土高原农业干旱监测比较研究_王晓燕_2022 摘要关键词1 引言2 研究区与数据6 结论#pic_center =x260) 摘要 本文集成 MODIS、TRMM、GLDAS 和再分析等多源数据,选取了 13 个与干旱有关的变量,并与基于气象数据的 3 个月时间尺度的标准化降水蒸发指数(SP…

算法沉淀——优先级队列(堆)(leetcode真题剖析)

算法沉淀——优先级队列 01.最后一块石头的重量02.数据流中的第 K 大元素03.前K个高频单词04.数据流的中位数 优先队列&#xff08;Priority Queue&#xff09;是一种抽象数据类型&#xff0c;它类似于队列&#xff08;Queue&#xff09;&#xff0c;但是每个元素都有一个关联的…

【精品】关于枚举的高级用法

枚举父接口 public interface BaseEnum {Integer getCode();String getLabel();/*** 根据值获取枚举** param code* param clazz* return*/static <E extends Enum<E> & BaseEnum> E getEnumByCode(Integer code, Class<E> clazz) {Objects.requireNonN…

C#,二分法(Bisection Method)求解方程的算法与源代码

1 二分法 二分法是一种分治算法&#xff0c;是一种数学思维。 对于区间[a&#xff0c;b]上连续不断且f&#xff08;a&#xff09;f&#xff08;b&#xff09;<0的函数yf&#xff08;x&#xff09;&#xff0c;通过不断地把函数f&#xff08;x&#xff09;的零点所在的区间…

OpenCV Mat 实例详解 二

构造函数 OpenCV Mat实例详解一中已介绍了部分OpenCV Mat构造函数&#xff0c;下面继续介绍剩余部分构造函数。 Mat (const std::vector< _Tp > &vec, bool copyDatafalse)&#xff1b; vec 包含数据的vec对象 copyData 是否拷贝数据&#xff0c;true— 拷贝数据&…

蓝桥杯真题:纸张尺寸

import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);//在此输入您的代码...String s scan.nextLine();char[] c s.toCharArray();char c1 c[1];in…

鸿蒙开发系列教程(二十二)--List 列表操作(1)

列表是容器&#xff0c;当列表项达到一定数量&#xff0c;内容超过屏幕大小时&#xff0c;可以自动提供滚动功能。 用于呈现同类数据类型或数据类型集&#xff0c;例如图片和文本 List、ListItemGroup、ListItem关系 列表方向 1、概念 列表的主轴方向是指子组件列的排列方…

【数据结构】无向图创建邻接表以及深度遍历、广度遍历(C语言版)

数据结构——无向图创建邻接表以及深度遍历、广度遍历 一、邻接表概念二、邻接表实现 &#xff08;1&#xff09;准备前提——结构体定义&#xff08;2&#xff09;创建边链表&#xff08;3&#xff09;打印边链表&#xff08;4&#xff09;深度优先遍历&#xff08;5&#xff…

前端可能需要的一些安装

Node.js Node.js 官网 Node.js 中文网 Node.js is an open-source, cross-platform JavaScript runtime environment. Node.js是一个开源、跨平台的JavaScript运行时环境。Recommended for most users 推荐大多数用户使用哔哩哔哩安装视频 安装 node.js 的时候&#xff0c;会…

安卓TextView 拖动命名

需求&#xff1a;该布局文件使用线性布局来排列三个文本视图和一个按钮&#xff0c;分别用于显示两个动物名称以及占位文本视图。在占位文本视图中&#xff0c;我们为其设置了背景和居中显示样式&#xff0c;并用其作为接收拖放操作的目标 效果图&#xff1b; 实现代码 第一布…

如何解决缓存和数据库的数据不一致问题

数据不一致问题是操作数据库和操作缓存值的过程中&#xff0c;其中一个操作失败的情况。实际上&#xff0c;即使这两个操作第一次执行时都没有失败&#xff0c;当有大量并发请求时&#xff0c;应用还是有可能读到不一致的数据。 如何更新缓存 更新缓存的步骤就两步&#xff0…

【C++】---类和对象(中)默认成员函数 和 操作符重载

前言&#xff1a; 假如一个类中既没有成员变量也没有成员函数&#xff0c;那么这个类就是空类&#xff0c;空类并不是什么都没有&#xff0c;因为所有类都会生成如下6个默认成员函数&#xff1a; 一、构造函数 1、构造函数的定义及其特性 对于日期类对象&#xff0c;我们可…

C语言---指针进阶

1.字符指针 int main() {char str1[] "hello world";char str2[] "hello world";const char* str3 "hello world.";const char* str4 "hello world.";if (str3 str4){//常量字符串在内存里面是无法修改的&#xff0c;所以没必要…

数据检索:倒排索引加速、top-k和k最邻近

之前在https://www.yuque.com/treblez/qksu6c/wbaggl2t24wxwqb8?singleDoc# 《Elasticsearch: 非结构化的数据搜索》我们看了ES的设计&#xff0c;主要侧重于它分布式的设计以及LSM-Tree&#xff0c;今天我们来关注算法部分&#xff1a;如何进行检索算法的设计以及如何加速倒排…