力扣hot100:33. 搜索旋转排序数组(二分的理解)

 33.搜索旋转排序数组

d5b31574aa144e6fa1314d4c8c5fbc9e.png

这是一个非常有趣的问题,如果不要求使用O(logn)应该没人会想到吧。。

方法一:

        极致的分类讨论。旋转排序数组,无非就是右边的增区间的数小于左边的增区间的数,然后依次排序。因此我们只需要分三类讨论即可,即[left,right]在左增区间,[left,right]在右增区间,[left,right]在两个区间中间。只有最后一种情况需要讨论更多一点。

        前两种情况可以合并为nums[left]<=nums[right]时的情况,这样一定是有序数组。

        最后一种情况又分为,target在左增区间中,target在右增区间中、nums[mid]在左增区间中、nums[mid]在右增区间中:一共4种情况。

如果target在左增区间中,则有target>nums[right],

如果target在右增区间中,则target<=nums[right],

如果nums[mid]在左增区间中,则有nums[mid]>nums[rgiht],

如果nums[mid]在右增区间中,则有nums[mid]<=nums[rgiht],

如果使得right=mid-1;则有target在mid左边,则有两种情况:

①mid在右增区间中,target小于mid的值  或者  target大于mid的值且大于nums[right]的值,即target在左增区间中。

②mid在左增区间中,target小于mid的值 且target也在左增区间中

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1;
        while(left<=right){
            int mid=(left+right)>>1;
            if(nums[mid]==target) return mid;
            if(nums[left]>=nums[0]&&nums[right]>=nums[0]){
                if(nums[mid]>target) {right=mid-1;continue;}
            }else{
                if(nums[left]<nums[0]&&nums[right]<nums[0]){
                    if(nums[mid]>target) {right=mid-1;continue;}
                }else{
                    if(nums[left]>=nums[0]&&nums[right]<nums[0]){
                        if(nums[mid]>nums[right]&&target<nums[mid]&&target>nums[right]){right=mid-1;continue;}
                        if(nums[mid]<=nums[right]&&(target>nums[right]||target<nums[mid])) {right=mid-1;continue;}
                    }
                }
            }
            left=mid+1;
        }
        return -1;
    }
};
/*
或者讨论target在哪个区间
if(target>nums[right]&&(target<nums[mid]||nums[mid]<nums[right])){right=mid-1;continue;}
if(target<nums[right]&&target<nums[mid]&&nums[mid]<=nums[right]) {right=mid-1;continue;}
*/

合并情况:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1;
        while(left<=right){
            int mid=(left+right)>>1;
            if(nums[mid]==target) return mid;
            if(nums[left]<=nums[right]){
                if(nums[mid]>target) {right=mid-1;continue;}
            }else{
                    if(nums[mid]>nums[right]&&target<nums[mid]&&target>nums[right]) {right=mid-1;continue;}
                    if(nums[mid]<=nums[right]&&(target>nums[right]||target<nums[mid])) {right=mid-1;continue;}
                }
            left=mid+1;
        }
        return -1;
    }
};

方法二 :官方思路:

        一个区间分为左增区间和右增区间,那么在任意一个点将这个区间断开分为两个区间一定会有一个区间是顺序区间!我们保证每次只在那个顺序区间里找(doge),如果不在这个顺序区间里我们就直接将指针移入那个区间即可,这保证了每一次也是二分的。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int n = (int)nums.size();
        if (!n) {
            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[l] <= nums[mid]) {//左区间是顺序区间
                if (nums[l] <= target && target < nums[mid]) {//target在左区间内则r=mid-1
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            } else {//右区间是顺序区间
                if (nums[mid] < target && target <= nums[n - 1]) {//target在右区间内则l=mid+1
                    l = mid + 1;
                } else {
                    r = mid - 1;
                }
            }
        }
        return -1;
    }
};

总结来看,二分就是“均分”区间之后,判断left移入右边  还是 right移入左边,如果可以满足这一性质就是一个二分,O(logn)的算法。 

不管是第一种方法,还是第二种方法都是判断如何移动,只是判断方式不同,第二种方法更直接。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【测试开发学习历程】MySQL数据类型 + MySQL表创建与操作

前言&#xff1a; 半夜梦到自己没有写今天的博客&#xff0c;结果惊醒起来看一看。 得&#xff0c;真的没写。QWQ 可谓垂死病中惊坐起了。 看看发博的时间6&#xff1a;16&#xff0c;而不是什么整点的&#xff0c;就知道我4点就起来了&#xff0c;不是定时发布&#xff01…

知识积累(五):Transformer 家族的学习笔记

文章目录 1. RNN1.1 缺点 2. Transformer2.1 组成2.2 Encoder2.2.1 Input Embedding&#xff08;嵌入层&#xff09;2.2.2 位置编码2.2.3 多头注意力2.2.4 Add & Norm 2.3 Decoder2.3.1 概览2.3.2 Masked multi-head attention 2.4 Transformer 模型的训练和推理2.4.1 训练…

C语言学习过程总结(16)——指针(4)

一、数组名的理解 我们直接使用%p打印出地址来看看&arr【0】 和 arr的不同&#xff1a; int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] %p\n", &arr[0]);printf("arr %p\n", arr);} 、 很容易看出来两者的输出…

ES模块化

Node.js默认并不支持ES模块化&#xff0c;如果需要使用可以采用两种方式。方式一&#xff0c;直接将所有的js文件修改为mjs扩展名。方式二&#xff0c;修改package.json中type属性为module。 导出 默认导出 // 向外部导出内容 export let a 10 export const b "孙悟空…

数据分析 | NumPy

NumPy&#xff0c;全称是 Numerical Python&#xff0c;它是目前 Python 数值计算中最重要的基础模块。NumPy 是针对多维数组的一个科学计算模块&#xff0c;这个模块封装了很多数组类型的常用操作。 使用numpy来创建数组 import numpy as npdata np.array([1, 2, 3]) print…

Unity中UGUI中的PSD导入工具的原理和作用

先说一下PSD导入工具的作用&#xff0c;比如在和美术同事合作开发一个背包UI业务系统时&#xff0c;美术做好效果图后&#xff0c;程序在UGUI中制作好界面&#xff0c;美术说这个图差了2像素&#xff0c;那个图位置不对差了1像素&#xff0c;另外一个图大小不对等等一系列零碎的…

文件包含漏洞(input、filter、zip)

一、PHP://INPUT php://input可以访问请求的原始数据的只读流&#xff0c;将post请求的数据当作php代码执行。当传入的参数作为文件名打开时&#xff0c;可以将参数设为php://input,同时post想设置的文件内容&#xff0c;php执行时会将post内容当作文件内容。从而导致任意代码…

ngnix安装配置

通过yum -y install nginx的方式&#xff0c;有时候会出现No package nginx available的报错。迟迟无法解决。此时要通过下载安装包的方式安装。 1、下载安装包&#xff1a;官方网址 2、解压缩&#xff1a; tar -xzvf nginx-1.23.4.tar.gz cd nginx-1.23.4.tar.gz 3、源码包…

pycharm里test connection连接成功,但是无法同步服务器文件,deployment变灰

如果服务器test connection连接成功&#xff0c;但是无法同步文件。 可以尝试以下方式&#xff1a; 点击tools-deployment-browse remonte host&#xff0c;选择要连接的服务器的文件夹 如果能正常显示服务器文件夹&#xff0c;再点击tools-deployment&#xff0c;注意要把要…

echarts设置柱形图柱间距离

不同系柱形图柱间距离&#xff08;barGap&#xff09; {type: bar,itemStyle: {normal: {color: #ddd}},silent: true,barWidth: 40,barGap: 10%, //设置负值 不同系的柱形图会实现重叠效果data: [60, 60, 60, 60] },同系柱形图柱间距离&#xff08;barCategoryGap&#xff…

谈谈对数据库索引的认识

索引的概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。 可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#xff0c;各类索引有各自的数据结构实现。 索引的作用 默认情况下&#xff0c;进行条件查询操作&#xff0c;就是遍历表&a…

27. 移除元素 (Swift版本)

题目描述 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出…

【蓝桥杯每日一题】填充颜色超详细解释!!!

为了让蓝桥杯不变成蓝桥悲&#xff0c;我决定在舒适的周日再来一道题。 例&#xff1a; 输入&#xff1a; 6 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 1 1 1 1 输出&#xff1a; 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 2 2 1 1 1 2 2 2 1 1 2 2 2 2 1 1…

渐开线花键环规的几种加工方法

小伙伴们大家好&#xff0c;今天咱们聊一聊渐开线花键环规的几种加工方法。 渐开线花键环规是在汽车、摩托车以及机械制造工业应用非常广泛的一种检测量具。它属于是一种内花键齿轮&#xff0c;其精度和表面粗糙度要求都比较高。采用的加工方法也比较多&#xff0c;下面详细看…

Spring MVC文件上传配置

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 文件上传 Spring MVC文件上传基于Servlet 3.0实现&#xff1b;示例代码如下&#xff1a; Overrideprotected void customizeRegistration(ServletRegistration.Dynamic reg…

C语言-memcpy(不重复地址拷贝 模拟实现)

memcpy&#xff08;不重复地址拷贝&#xff09; 语法格式 在C语言中&#xff0c;memcpy 是一个标准库函数&#xff0c;用于在内存之间复制数据。它的原型定义在 <string.h> 头文件中。memcpy 的语法格式如下&#xff1a; c void *memcpy(void *destination, const voi…

2024全新返佣商城分销商城理财商城系统源码 全开源PHP+VUE源码

2023全新返佣商城分销商城理财商城系统源码 全开源PHPVUE源码 程序安装环境要求&#xff1a; nginx1.16 php7.2 mysql5.6 程序全开源PHPVUE源码 有需要测试的老铁&#xff0c;拿去测试吧

KKVIEW远程: 安卓免费远程控制软件

安卓免费远程控制软件&#xff1a;方便、实用且高效 在数字化日益增长的今天&#xff0c;远程控制软件正变得越来越重要。无论是在家庭环境还是工作环境中&#xff0c;它们都能为我们提供便利。特别是在移动设备上&#xff0c;如安卓设备&#xff0c;这种需求更为明显。幸运的是…

基于高斯模型的运动目标检测(车辆检测),Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

RTC协议与算法基础 - RTP/RTCP

首先&#xff0c;需要说明下&#xff0c;webrtc的核心音视频传输是通过RTP/RTCP协议实现的&#xff0c;源码位于src/modules/rtp_rtcp目录下&#xff1a; 下面让我们对相关的内容基础进行简要分析与说明&#xff1a; 一、TCP与UDP协议 1.1、TCP协议 TCP为了实现数据传输的可…