数据结构中数据有序性/ 单调性 ——二分查找

以下记录的都是闭区间写法

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

1.关系转换

寻找目标值有四种情况:≥、>、≤、<

比如目标值x, 可以转化为         ≥x、≥ x+1、≤x、≤ x+1

比如数组大小为6,目标值为5,我们将数组中最左端和最右端标记为left和right指针

2.避免溢出的写法

Mid = left+(right-left)/2  

3.闭区间的含义

闭区间【L,R】中的数字都是不确定的,准确的说,是不知道具体比几大,比几小(包括边界)

我们将nums[ mid ] 和目标值 target 进行比较,nums[mid] <target ,则说明target应该在mid右边(因为闭区间,所以这个mid肯定不是,我们已经验过了),所以left指针指向mid+1,同理,如果大于等于的情况:
我们需要看这个mid的前面(左边)是否还有目标值(允许重复),同时mid也是验过了,我们将right指针指向mid-1。 
总结: 我们每次移动指针,移动的地方都是没有验过的,都是交给下一次来去验证!!!

什么时候循环结束呢? while(left ≤ right)当left > right 的时候

如果left == right ,我们始终明确一点:【L,R】中的数字是不确定的,也就是nums[left]==nums[right] 这一个数字,我们还没验呢!!! 怎么能结束? 

最终一定存在left == right+1 吗?

是的
随着指针移动,mid的移动幅度会越来越小,后面一定是一格一格的移动,所以最后一定存在left == right ,此时不管是nums[mid] 是大于等于 target 还是 小于 target ,前者左指针加1,后者右指针减一,最终都会存在left == right + 1 .....

 例1:

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

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

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

看到有序数字,看到时间复杂度O(log n) -> 二分查找。
其实看到有序数组就应该想到二分查找。

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int start = Search(nums,target);
        if(start == nums.length || nums[start] != target) // 优化,如果没找到start 没必要找end了
        return new int[]{-1,-1};
        // 这里找最后一个位置,相当于找 ≥ x+1的第一个位置的上一个位置
        int end = Search(nums,target + 1) - 1;
        return new int[]{start , end};
    }
    private int Search(int[] nums , int target){
        int n = nums.length;
        int left = 0 , right = n -1 ; 
        while(left <= right){  // 这里小于等于 ,很精髓
            int mid = left+ (right-left)/2;
            if(nums[mid]<target){
                left = mid + 1;
            }else{
                right = mid -1 ;
            }
        }
        // 这里返回right +1 也可以
        return left ;
    }
}

最后返回的时候,返回left / right+ 1都可,因为最后的情况一定是 left == right ,然后mid =left =right,然后right = mid -1 = left -1 ;

进阶写法:通过数据的单调性去完成二分查找

例2:

给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。

请你找出并返回只出现一次的那个数。

你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。

 

 这题比较特殊:一个元素只出现一次,其他元素都出现两次,也就是说,以目标元素为中间值,它前面的元素,索引值为偶数的一定是其他元素,后面的元素,索引值为奇数的才是其他元素。

我们通过每次去判断索引为 2k和2k+1的值,是否相等,相等说明目标值在后面,不相等说明目标值在前面(因为目标值的存在打破了这个规律)。

我们这里除以2,乘以2
以及在定义左右指针,闭区间的话为0和(n/2)-1
都是为了避免数组越界问题

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int n = nums.length;
        int left = 0 , right = n/2 -1 ; // 注意边界,这里要减1
        while(left <= right){
            int mid = left+(right-left)/2;
            if(nums[mid*2] == nums[mid*2+1]){
                left = mid + 1;
            }else{
                right = mid -1;
            }
        }
        return nums[left*2];
    }
}

还有一种方法,这个也是用到了答案一定在索引值为2k的上面,然后一次遍历,比较取巧.....
这是我没学二分法的想法:

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int n = nums.length;
        int k = 0 ;
        if(n == 1)return nums[0];
        for( ; k < n ; k = k + 2){
           if( k < n-1 &&  nums[k]!=nums[k+1]){
            return nums[k];
           } 
        }
        return nums[n-1]; // 因为答案一定存在,前面没找到则说明为数组中最后一个元素
    }
}

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

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

相关文章

探索Python的HTTP利器:Requests库的神秘面纱

文章目录 **探索Python的HTTP利器&#xff1a;Requests库的神秘面纱**一、背景&#xff1a;为何选择Requests库&#xff1f;二、Requests库是什么&#xff1f;三、如何安装Requests库&#xff1f;四、Requests库的五个简单函数使用方法1. GET请求2. POST请求3. PUT请求4. DELET…

《Linux从小白到高手》综合应用篇:深入详解Linux swap及其调整优化

1. 引言&#xff1a; Swap是存储设备上的一块空间&#xff08;分区&#xff09;&#xff0c;操作系统可以在这里暂存一些内存里放不下的东西。这从某种程度上相当于增加了服务器的可用内存。虽然从swap读写比内存慢&#xff0c;但总比没有好&#xff0c;算是内存不足时一种比较…

SpringMVC学习笔记(一)

一、SpringMVC的基本概念 &#xff08;一&#xff09;三层架构和MVC 1、三层架构概述 我们的开发架构一般都是基于两种形式&#xff0c;一种是 C/S 架构&#xff0c;也就是客户端/服务器&#xff0c;另一种是 B/S 架构&#xff0c;也就是浏览器服务器。在 JavaEE 开发中&…

小面馆叫号取餐流程 佳易王面馆米线店点餐叫号管理系统操作教程

一、概述 【软件资源文件下载在文章最后】 小面馆叫号取餐流程 佳易王面馆米线店点餐叫号管理系统操作教程 点餐软件以其实用的功能和简便的操作&#xff0c;为小型餐饮店提供了高效的点餐管理解决方案&#xff0c;提高了工作效率和服务质量 ‌点餐管理‌&#xff1a;支持电…

【.NET 8 实战--孢子记账--从单体到微服务】--简易权限--角色可访问接口管理

咱们继续来编写孢子记账的简易权限&#xff0c;这篇文章中我们将编写角色可访问接口的管理API&#xff0c;同样我不会把完整的代码全都列出来&#xff0c;只会列出部分代码&#xff0c;其余代码我希望大家能自己手动编写&#xff0c;然后对比项目代码。废话不多说&#xff0c;开…

Linux上Python使用MySQLdb包连接MySQL5.7和MySQL8的问题

在一台安装有MySQL8的Linux上用MySQLdb包连接MySQL5.7&#xff0c;连接参数中加上ssl_mode‘DISABLED’,能正常连接&#xff1b;不加ssl_mode参数&#xff0c;会报 而在连接MySQL8时加不加ssl_mode都能正常连接&#xff0c;但在使用过程&#xff0c;加了ssl_mode参数&#xff…

列表(list)

一、前言 本次博客主要讲解 list 容器的基本操作、常用接口做一个系统的整理&#xff0c;结合具体案例熟悉自定义内部排序方法的使用。如有任何错误&#xff0c;欢迎在评论区指出&#xff0c;我会积极改正。 二、什么是list list是C的一个序列容器&#xff0c;插入和删除元素…

spring使用xml文件整合事务+druid+mybatis

1.事务 事务&#xff08;Transaction&#xff09;是数据库管理系统中的一个重要概念&#xff0c;它表示一组不可分割的操作序列&#xff0c;这些操作要么全部执行成功&#xff0c;要么全部不执行&#xff0c;以确保数据库从一个一致性状态转换到另一个一致性状态。事务具有以下…

大语言模型LLM综述

一、LM主要发展阶段 1.1、统计语言模型SLM 基于统计学习方法&#xff0c;基本思想是基于马尔可夫假设HMM建立词概率预测模型。如n-gram语言模型 1.2、神经语言模型NLM 基于神经网络来做词的分布式表示。如word2vec模型 1.3、 预训练语言模型PLM 预训练一个网络模型来做词表…

【Jenkins实战】Windows安装服务启动失败

写此篇短文&#xff0c;望告诫后人。 如果你之前装过Jenkins&#xff0c;出于换域账号/本地帐号的原因想重新安装&#xff0c;你大概率会遇上一次Jenkins服务启动失败提示&#xff1a; Jenkins failed to start - Verify that you have sufficient privileges to start system…

Linux kernel 堆溢出利用方法(二)

前言 本文我们通过我们的老朋友heap_bof来讲解Linux kernel中off-by-null的利用手法。在通过讲解另一道相对来说比较困难的kernel off-by-null docker escape来深入了解这种漏洞的利用手法。&#xff08;没了解过docker逃逸的朋友也可以看懂&#xff0c;毕竟有了root权限后&a…

微服务(一)

目录 1.认识微服务 1.1.单体架构 1.2.微服务 1.3.SpringCloud SpringCloud版本 SpringBoot版本 2.服务注册和发现 2.1.注册中心原理 2.2.Nacos注册中心 2.3.服务注册 2.3.1.添加依赖 2.3.2.配置Nacos 2.4.服务发现 2.4.1.引入依赖 2.4.2.配置Nacos地址 2.4.3.发…

ubontu--cuDNN安装

1. 下载 cuDNN https://developer.nvidia.com/cudnn 2. 拷贝到服务器/home/<username>文件夹下 解压缩到当前文件夹&#xff1a; tar -xvf cudnn-linux-x86_64-9.5.1.17_cuda11-archive.tar.xz复制头文件和库文件到cuda安装目录/usr/local/cuda/ sudo cp /home/usern…

Vue 批量注册组件实现动态组件技巧

介绍 Vue 动态组件的应用场景很多,可应用于动态页签,动态路由等场景,其核心原理是批量注册。在Vue2和Vue3中实现原理相同,只是语法略有差异。 Vue2 实现 基于 webpack require.context() 是webpack提供的一个自动导入的API 参数1&#xff1a;加载的文件目录 参数2&#xff…

WEB攻防-通用漏洞SQL读写注入MYSQLMSSQLPostgraSQL

知识点&#xff1a; 1、SQL注入-MYSQL数据库&#xff1b; 2、SQL注入-MSSQL数据库&#xff1b; 3、SQL注入-PostgreSQL数据库&#xff1b; 首先要找到注入点 详细点&#xff1a; Access无高权限注入点-只能猜解&#xff0c;还是暴力猜解 MYSQL&#xff0c;PostgreSQL&am…

NocoBase 本周更新汇总:提升工作流易用性

汇总一周产品更新日志&#xff0c;最新发布可以前往我们的博客查看。 NocoBase 目前更新包括两个分支&#xff1a;main 和 next 。 main &#xff1a;截止目前最稳定的版本&#xff0c;推荐安装此版本。 next&#xff1a;内测版&#xff0c;包含一些未发布的新特性&#xff…

python高级之面向对象编程

一、面向过程与面向对象 面向过程和面向对象都是一种编程方式&#xff0c;只不过再设计上有区别。 1、面向过程pop&#xff1a; 举例&#xff1a;孩子上学 1. 妈妈起床 2. 妈妈洗漱 3. 妈妈做饭 4. 妈妈把孩子叫起来 5. 孩子起床 6. 孩子洗漱 7. 孩子吃饭 8. 妈妈给孩子送学校…

❤React-React 组件基础(类组件)

❤React-React 组件基础 1、组件化开发介绍 组件化开发思想&#xff1a;分而治之 React的组件按照不同的方式可以分成类组件&#xff1a; 划分方式一&#xff08;按照组件的定义方式&#xff09; 函数组件(Functional Component )和类组件(Class Component)&#xff1b; …

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战

目录 前言 一、原始的处理办法 1、使用Set方法来转换 2、使用构造方法转换 二、基于ModelMapper的动态转换 1、ModelMapper简介 2、集成到项目中 3、Shapefile属性读取 三、总结 前言 在现代软件开发中&#xff0c;尤其是在多层架构中&#xff0c;经常需要将数据从一个…

Arduino IDE Windows 系统 离线安装 esp32 开发板 亲测好用。

1、前提条件需要具备特殊网络。 2、官方文档地址&#xff1a;Installing - - — Arduino ESP32 latest documentation 3、系统&#xff1a;Windows10 Arduino IDE 版本2.3.3 之前安装的esp32开发板的版本是2.0.13&#xff0c;由于之前没有接触过esp32开发&#xff0c;也没…