【优选算法】二分算法(在排序数组中查找元素的第一个和最后一个位置,寻找峰值,寻找排序数组中的最小值)

 二分算法简介:

   提到二分我们可能都会想起二分查找,二分查找要求待查找的数组是有序的,与我们今天讲的二分算法不同,并不是数组元素严格按照有序排列才可以使用二分算法,只要数组中有一个点可以将数组分为两个部分,即存在“二段性”,就可以使用二分算法解决。

        二分算法的模版就是定义一个left指针和right指针,用mid来保存这段区间的中间下标,而求mid的时有一个小细节,如果我们直接采用(left+right)/2 的话,如果left和right的值很大,求mid时数据就会越界了,所以我们可以这样写:mid = left+ (right-left)/2 ,这样就可以解决越界的问题。

        求mid的方式其实有两种

  1. mid = left+ (right-left)/2
  2. mid = left+ (right-left+1)/2

两者的使用在数组大小为奇数时没有任何区别,但是如果数组大小为偶数的话,方式1求出来的mid就是靠左边的,方式2求出来的mid是靠右边的,具体使用哪种要看具体的场景了,用错了极容易造成死循环。

一、在排序数组中查找元素的第一个和最后一个位置

题目链接:

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

题目介绍:

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

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

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

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109
思路:

首先题目都说明了数组是非递减的数组,并且要求我们实现一个复杂度为 O(log n) 的算法,这样的题目基本上就是要让我们用二分算法了。

如果题目是让我们找第一个出现的元素位置或者最后一个元素出现的位置,这样就很简单,以找第一个出现的位置为例,一个元素要么是小于target,要么是大于等于target的,这样就把数组分成了两部分。

如果元素小于target那说明第一个元素的位置一定在他的右边,那就一定不在当前位置的左边,所以我们可以让 left=mid+1,如果元素大于等于target的话,我们只能确定第一个出现的位置一定不在这个下标的右边,而不能确定当前的下标的元素是不是数组中出现的第一个,所以我们可以让right=mid。通过这样right就会不断的向左压缩,当left = right时查找就结束了,至于是不是目标值我们还需要判断一下。

要注意,这里求mid不能使用方式2,假设此时区间只剩下两个元素【0,2】,而我们的目标值时2,如果采用方式2的话,求出来的mid就是指向2的,这样就会造成死循环了。

int begin = -1, end = -1;
int left = 0, right = nums.size() - 1;
while (left < right) {
    int mid = left + (right - left) / 2;
    if (nums[mid] >= target) {
        right = mid;
    } else {
        left = mid + 1;
    }
}
if (nums[left] == target)
    begin = left;
else
    return {-1, -1};

求最后一个元素出现位置的方式与上述的思路一样,但是此时求mid的方式要用方式2,因为这次是从左向右靠近的

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if (nums.empty())
            return {-1, -1};
        int begin = -1, end = -1;
        int left = 0, right = nums.size() - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] >= target) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        if (nums[left] == target)
            begin = left;
        else
            return {-1, -1};

        left = 0, right = nums.size() - 1;
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            if (nums[mid] <= target) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        if (nums[left] == target)
            end = left;
        else
            return {-1, -1};

        return {begin, end};
    }
};

二、寻找峰值

题目链接:

162. 寻找峰值 - 力扣(LeetCode)

题目介绍:

峰值元素是指其值严格大于左右相邻值的元素。

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞ 。

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

  • 1 <= nums.length <= 1000
  • -231 <= nums[i] <= 231 - 1
  • 对于所有有效的 i 都有 nums[i] != nums[i + 1]
思路:

寻找⼆段性: 任取⼀个点i ,与下⼀个点 i + 1 ,会有如下两种情况: 

  • arr[i] > arr[i + 1] :此时「左侧区域」⼀定会存在山峰(因为最左侧是负无穷),那么我们可以去左侧去寻找结果;
  • arr[i] < arr[i + 1] :此时「右侧区域」⼀定会存在山峰(因为最右侧是负无穷),那么我们可以去右侧去寻找结果。

当我们找到「二段性」的时候,就可以尝试用「二分查找」算法来解决问题。

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int left=0,right=nums.size()-1;
        while(left<right)
        {
            int mid=left+(right-left)/2;

            if(nums[mid]<nums[mid+1])
            left=mid+1;
            else
            right=mid;
        }
        return left;
    }
};

三、寻找排序数组中的最小值

题目链接:

153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

题目介绍:

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

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

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums 中的所有整数 互不相同
  • nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转
思路:

数组经过旋转后元素的大小其实就是这样的,c点就是我们要找的这个值

通过图像我们可以发现, [A,B] 区间内的点都是严格大于 D 点的值的, C 点的值是严格小于 D 点的值的。但是当 [C,D] 区间只有⼀个元素的时候, C 点的值是可能等于 D 点的值的。

因此,初始化左右两个指针 left , right :

然后根据 mid 的落点,我们可以这样划分下⼀次查询的区间:

  • 当 mid 在 [A,B] 区间的时候,也就是 mid 位置的值严格大于 D 点的值,下⼀次查询区间在 [mid + 1,right] 上;
  • 当 mid 在 [C,D] 区间的时候,也就是 mid 位置的值严格小于等于 D 点的值,下次 查询区间在 [left,mid] 上。
  • 当区间长度变成 1 的时候,就是我们要找的结果。

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

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

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

相关文章

升级Ubuntu 24.04 LTS报错“Oh no! Something has gone wrong.”

强烈建议&#xff1a;升级Ubuntu系统之前先配置好SSH远程访问 最近升级Ubuntu系统&#xff08;18->24&#xff09;&#xff0c;经历了一些惊魂时刻&#xff0c;复盘下来没有重装系统的最得益于SSH访问。 在升级到24.04版本时&#xff0c;一切似乎表现得很正常&#xff0c;…

大模型底座 Transformer 的核心技术解析

1. 引言 说明目标 在深度学习领域&#xff0c;Transformer架构已成为近年来最重要的技术突破之一。它最早由Vaswani等人在2017年的论文《Attention is All You Need》中提出&#xff0c;迅速成为自然语言处理&#xff08;NLP&#xff09;和其他序列建模任务的核心工具。传统方法…

2.生成Transformation

目录 前言 Source FlatMap KeyBy sum print 总结 前言 以下面的WordCount为例 package com.wlh.p1;import org.apache.flink.api.common.functions.FlatMapFunction; import org.apache.flink.api.java.functions.KeySelector; import org.apache.flink.api.java.tuple…

1. 机器学习基本知识(3)——机器学习的主要挑战

1.5 机器学习的主要挑战 1.5.1 训练数据不足 对于复杂问题而言&#xff0c;数据比算法更重要但中小型数据集仍然很普遍&#xff0c;获得额外的训练数据并不总是一件轻而易举或物美价廉的事情&#xff0c;所以暂时不要抛弃算法。 1.5.2 训练数据不具有代表性 采样偏差&#…

TypeScript学习路线图

‌ TypeScript 是由微软开发和维护的一种静态类型编程语言&#xff0c;它是 JavaScript 的超集。TypeScript 的创建是为了解决构建大规模 JavaScript 应用程序所面临的挑战&#xff0c;并向该语言添加了可选的类型注解、类、接口和其他特性。 使用 TypeScript 的主要好处包括&a…

负载均衡oj项目:编译模块

编译运行模块是一个网络服务&#xff0c;这样编译模块就可以可以快速部署到&#xff0c;其他主机上。 编译模块思路 util.hpp #pragma once #include <string> #include <vector> #include <sys/types.h> #include <sys/stat.h> #include <unistd…

绿色浪潮,VELO Angel Glide坐垫奏响环保骑行乐章

地球的环境日益恶劣&#xff0c;冰川消融、海平面上升、极端天气频繁出现&#xff0c;这一切都在不断提醒着我们&#xff0c;保护地球家园刻不容缓。而在这场关乎人类未来的环保行动中&#xff0c;各个领域都在积极探索可持续发展的道路&#xff0c;自行车坐垫领域也迎来了绿色…

【从零开始入门unity游戏开发之——C#篇09】if-else条件表达式、三元运算符、switch-case的使用

文章目录 一、if条件表达式1、if 语句基本结构示例输出&#xff1a; 2、else语句示例输出&#xff1a; 3、else if 语句示例输出&#xff1a; 4、组合逻辑运算符示例输出&#xff1a; 5、嵌套 if 语句示例输出&#xff1a;总结 二、三元运算符1、语法&#xff1a;2、示例&#…

Visual Studio 使用 GitHub Copilot 扩展

&#x1f380;&#x1f380;&#x1f380;【AI辅助编程系列】&#x1f380;&#x1f380;&#x1f380; Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码Visual Studio 安装和管理 GitHub CopilotVisual Studio 使用 GitHub Copilot 扩展Visual Studio 使用 GitHu…

conda学习

参考: Anaconda 官网教程 https://freelearning.anaconda.cloud/get-started-with-anaconda/18202conda配置虚拟环境/conda环境迁移/python环境迁移 https://blog.csdn.net/qq_43369406/article/details/127140839 环境&#xff1a; macOS 15.2Anaconda Navigator 2.4.2 x.1…

Nginx配置示例教程

最近对Nginx做了一些初步研究&#xff0c;Nginx是lgor Sysoev为俄罗斯访问量第二的rambler.ru站点设计开发。主要根据工作中各类应用服务部署访问的需求&#xff0c;围绕HTTP服务、负载均衡、正反向代理、子路由、静态资源发布访问等&#xff0c;以及结合minio管理的图片文件资…

git使用教程(超详细)-透彻理解git

一.核心基础 核心概念有六个 首先请把与svn有关的一切概念暂时从你的脑海中移除掉&#xff0c;我们要重新认识本文所讲述的所有概念。 1.worktree worktree是一个目录&#xff0c;你在这里对文件进行增加、删除、修改。也就是我们常说的工作区。在git中worktree必须要与一个…

Django结合websocket实现分组的多人聊天

其他地方和上一篇大致相同&#xff0c;上一篇地址点击进入, 改动点1&#xff1a;在setting.py中最后再添加如下配置&#xff1a; # 多人聊天 CHANNEL_LAYERS {"default":{"BACKEND": "channels.layers.InMemoryChannelLayer"} }因此完整的se…

Keil-MDK开发环境编译后axf自动转换bin格式文件

编译选项添加如下&#xff0c;调用fromelf工具自动完成转换&#xff1a; fromelf --bin -o "$LL.bin" "#L"

如何快速搭建若依管理系统?

1、下载若依管理系统前后端分离版代码至本地&#xff08;当前版本为RuoYi v3.8.8&#xff09;&#xff1a; RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff0c;JWT&#xff0c;Vue & Element 的前后端分离权限管理系统&#xff0c;同时提供…

【JavaEE】网络(1)

&#x1f435;本篇文章开始讲解计算机网络相关的知识 一、基础概念 1.1 局域网和广域网 局域网→Local Area Network→简称LAN&#xff0c;局域网是局部组建的一种私有网络&#xff0c;局域网内的主机之间可以进行网络通信&#xff0c;局域网和局域网之间在没有连接的情况不能…

网络应用技术 实验八:防火墙实现访问控制(华为ensp)

目录 一、实验简介 二、实验目的 三、实验需求 四、实验拓扑 五、实验步骤 1、设计全网 IP 地址 2、设计防火墙安全策略 3、在 eNSP 中部署园区网 4、配置用户主机地址 5、配置网络设备 配置交换机SW-1~SW-5 配置路由交换机RS-1~RS-5 配置路由器R-1~R-3 6、配置仿…

day11 性能测试(4)——Jmeter使用(黑马的完结,课程不全)直连数据库+逻辑控制器+定时器

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、复习 1.1 断言&#xff08;3种&#xff09; 1.2 关联&#xff08;3种&#xff09; 1.3 录制脚本 2、Jmeter直连数据库 2.1 直连数据库——使用场景 2.2 直连数据库——操作步骤 2.2.1 案例1&…

Modelscope AgentFabric: 开放可定制的AI智能体构建框架

目录 git clone https://github.com/modelscope/modelscope-agent.git cd modelscope-agent && pip install -r requirements.txt && pip install -r apps/agentfabric/requirements.txtexport PYTHONPATH$PYTHONPATH:/home/ubuntu/users/lilingfei/modelscop…

CSS|08 浮动清除浮动

浮动 需求: 能够实现让多个元素排在同一行&#xff0c;并且给这些元素设置宽度与高度! 让多个元素排在同一行:行内元素的特性 给这些元素设置宽高:块级元素的特性 在标准文档流中的元素只有两种:块级元素和行内元素。如果想让一些元素既要有块级元素的特点也要有行内元素的特…