【剑指offer|图解|二分查找】点名 + 统计目标成绩的出现次数

news2024/9/30 17:25:58

在这里插入图片描述
🌈个人主页:聆风吟
🔥系列专栏:数据结构、剑指offer每日一练
🔖少年有梦不应止于心动,更要付诸行动。


文章目录

  • 一. ⛳️点名
    • 1.1 题目
    • 1.2 示例
    • 1.3 限制
    • 1.4 解题思路一
      • c++代码
    • 1.5 解题思路二
      • c++代码
  • 二. ⛳️统计目标成绩的出现次数
    • 1.1 题目
    • 1.2 示例
    • 1.3 限制
    • 1.4 解题思路
      • c++代码
  • 📝结语

一. ⛳️点名

⌈ 在线OJ链接,可以转至此处自行练习 ⌋

1.1 题目

某班级 n 位同学的学号为 0 ~ n-1。点名结果记录于升序数组 records。假定仅有一位同学缺席,请返回他的学号。

1.2 示例

输入: records = [0,1,2,3,5]
输出: 4

1.3 限制

  • 1 <= records.length <= 10000

1.4 解题思路一

二分查找
根据题意,数组可以按照以下规则进行划分为两部分:

  • 左子数组:records[i] = i
  • 右子数组:records[i] != i

缺失的数字等于 右子数组的首位元素 对应的索引,因此我们可以使用二分查找右子数组首元素。
在这里插入图片描述

算法执行过程

  1. 初始化 :左边界 l = 0 和 右边界 r = records.size() - 1
  2. 循环二分:当 l <= r 时循环
    • 计算中心点 mid = (l + r) / 2;
    • 如果 records[mid] = mid 说明要查找的值在区间[mid + 1, r] 之间,因此执行 l = mid + 1;
    • 如果 records[mid] != mid 说明要查找的值在区间[l, mid - 1] 之间,因此执行 r = mid - 1;
  3. 返回值:循环跳出时,返回 l 即可。

在这里插入图片描述

c++代码

class Solution {
public:
    int takeAttendance(vector<int>& records) {
        int sz = records.size();

        int l = 0;
        int r = sz - 1;
        while(l <= r)
        {
            int mid = (l + r) >> 1;
            if(records[mid] == mid) l = mid + 1;
            else r = mid -1;
        }

        return l;
};

1.5 解题思路二

求和做差
有题目可知:
0 ~ n - 1 之间所有同学的学号加在一起,然后减去数组中的每个元素,所得结果即是缺课人学号。
在这里插入图片描述

c++代码

class Solution {
public:
    int takeAttendance(vector<int>& records) {
        
        int sz = records.size();
        int sum = sz*(sz+1)/2;//使用等差求和公式求全班学号的总和
        
        //将全班人的学号 - 数组中的每一个元素
        for(int i = 0; i < sz; i++)
        {
            sum -= records[i];
        }

        return sum;
    }
};


二. ⛳️统计目标成绩的出现次数

⌈ 在线OJ链接,可以转至此处自行练习 ⌋

1.1 题目

某班级考试成绩按非严格递增顺序记录于整数数组 scores,请返回目标成绩 target 的出现次数。

1.2 示例

输入: scores = [2, 2, 3, 4, 4, 4, 5, 6, 6, 8], target = 4
输出: 3

1.3 限制

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

1.4 解题思路

对于已经排好序的数组查找问题,首先我们可以想到是用二分查找。

对于排序数组 scores 中所有数字 target 形成一个窗口,记做窗口的 左 / 右边界 索引分别为 left 和 right,分别对应窗口的左右两边。因此本题求数字 target 出现的次数,就可以转化为:使用二分法分别求出窗口的左边界 left 和 右边界 right,容易得出数字 target 出现的次数 right - left + 1。
在这里插入图片描述


1. 查找右边界:

//查找右边界
while(l < r)
{
	int mid = (l + r + 1) >> 1;
    if(scores[mid] <= target) l = mid;
    else r = mid - 1;
}

在这里插入图片描述

注意

  1. 在查找完右边界后,需要用 scores[right] 判断一下数组中是否含有 target,若不包含则直接提前返回 0,无需继续查找左边界
  2. 记得让指针 l,r 重新回到起点处

2. 查找左边界:

//查找左边界
while(l < r)
{
	int mid = (l + r) >> 1;
	if(scores[mid] >= target) r = mid;
	else l = mid + 1;
}

由于左边界的查找同右边界运行类似,大家可以在下面自己画出图形,调试。

c++代码

class Solution {
public:
    int countTarget(vector<int>& scores, int target) {
        int sz = scores.size();
        int l = 0;
        int r = sz - 1;

        // 搜索右边界
        while(l < r)
        {
            int mid = (l + r + 1) >> 1;
            if(scores[mid] <= target) l = mid;
            else r = mid - 1;
        }
        int right = r;

        // 若数组中无 target ,则提前返回
        if(r >= 0 && scores[right] != target) return 0;

        // 搜索左边界
        l = 0, r = sz - 1;//让指针返回到初始状态
        while(l < r)
        {
            int mid = (l + r) >> 1;
            if(scores[mid] >= target) r = mid;
            else l = mid + 1;
        }
        int left = l;

        return right - left + 1;
    }
};


📝结语

     今天的干货分享到这里就结束啦!如果觉得文章还可以的话,希望能给个三连支持一下,聆风吟的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的最大动力!
在这里插入图片描述

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

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

相关文章

ARM I2C通信

1.概念 I2C总线是PHLIPS公司在八十年代初推出的一种串行的半双工同步总线&#xff0c;主要用于连接整体电路2.IIC总线硬件连接 1.IIC总线支持多主机多从机&#xff0c;但是在实际开发过程中&#xff0c;大多数采用单主机多从机模式 2.挂接到IIC总线上&#xff0c;每个从机设备都…

leetcode--1004 最大连续1的个数 III[滑动窗口c++]

原题链接&#xff1a; 3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 题目的翻转0&#xff0c;意思就是把0变成1&#xff1b; 将题的 最多可翻转k个0 操作看成 限定范围内最多可有k个0&#xff08;等价转换&#xff09; 因为实…

js 时间字符串截掉微秒后面的内容及加1秒

老规矩先上效果图: 一、js 时间字符串截掉微秒后面的内容&#xff0c;保留前面的 let str 2023-11-27 19:08:34.733; let index str.lastIndexOf(".") str str.substring(0, index); console.log(str) // 2023-11-27 19:08:34 二、转成时间戳&#xff0c;加1秒的…

人机融合与意图理解

人机融合本质上是人类智能与机器自动化之间的协同。 人机融合的目标是利用人类智能和机器自动化的优势&#xff0c;使二者相互补充、相互支持&#xff0c;共同实现更高效、更智能的工作和生活方式。 人类智能和机器自动化具有不同的特点和优势。人类智能具有创造性、灵活性、推…

VS Code串口监视插件Serial Monitor

文章目录 初步使用参数设置VS Code插件 初步使用 Serial Monitor&#xff0c;即串行监视器&#xff0c;提供串口和TCP协议的通信监控功能。在插件栏搜索安装之后&#xff0c;按下Ctrl打开终端&#xff0c;终端界面会多出一个串行监视器选项卡&#xff0c;进入之后&#xff0c;…

基于vue实现的疫情数据可视化分析及预测系统-计算机毕业设计推荐 django

本疫情数据可视化分析及预测系统 开发&#xff0c;用小巧灵活的MySQL数据库做完后台存储解释。本系统不仅主要实现了注册登录&#xff0c;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;全国实时数据管理&#xff0c;每日实时数据管理&#xff0c;国内实时动态…

KUKA机器人如何在程序中编辑等待时间?

KUKA机器人如何在程序中编辑等待时间&#xff1f; 如下图所示&#xff0c;如何实现在P1点和P2点之间等待设定的时间&#xff1f; 如下图所示&#xff0c;可以直接输入wait sec 2&#xff08;等待2秒&#xff09;&#xff0c; 如下图所示&#xff0c;再次选中该程序后&#…

ZLMediaKit中的线程

EventLoop的线程模型 服务器通用的IO模型event-loop 非阻塞IO。线程模型可以是单线程&#xff0c;可以是多线程。对于已经普及了的多核环境&#xff0c;通常都是采用多线程。 通常一个线程中有一个EventLoop&#xff0c;比如accept是一个专门线程&#xff0c;accept后的fd分…

I.MX RT1170双核学习(2):双核相互激活和启动流程

RT1170这个芯片带有双核&#xff1a;Cortex-M7和Corterx-M4&#xff0c;两个核都可以独立地运行&#xff0c;当然双核也可以同时运行。在上一篇文章中&#xff0c;介绍了一下在RT1170中消息模块MU的使用&#xff1a;双核通信之MU消息单元详解&#xff0c;因为这是双核之间用来通…

基于Dockerfile创建LNMP

实验组件 172.111.0.10&#xff1a;nginx docker-nginx 172.111.0.20&#xff1a;mysql docker-mysql 172.111.0.30&#xff1a;php docker-php 实验步骤 1.建立nginx-lnmp镜像及容器 cd /opt mkdir nginx cd nginx/ --上传nginx-1.22.0.tar.gz和wordpress-6.4.2-zh_C…

JOSEF 约瑟 时间继电器 DHC6A AC/DC100-240V 面板安装

特点 DIN&#xff08;4848mm&#xff09;标准面板尺寸 9 种工作模式可任意设定&#xff0c;简化外围线路,增强可靠性 带背光源 LCD 显示&#xff0c;在阳光或黑夜都能清晰显示 键保护可按要求锁定相关的按键,保护部分或全部的设定数据不受更 改&#xff0c;有效的防止误操…

02-详解请求路由的实现和常见的断言工厂

请求路由 路由转发 第一步: 新建一个SpringBoot工程如gateway模块, 引入网关依赖和nacos服务发现依赖 <!--网关依赖--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId&…

【免费神器】一键转换PDF文件,轻松解决你的烦恼!

你是否曾经因为PDF文件的格式问题而感到困扰&#xff1f;是否曾经因为无法快速转换PDF文件而感到烦恼&#xff1f; 现在&#xff0c;这些问题都可以迎刃而解了&#xff01;下面这个在线PDF转换网站&#xff0c;就是你的解决方案。 目前5M以下文件免费转换&#xff0c;赶紧来看…

Python-自制简易音乐播放器

文章目录 前言一、代码二、代码实现1.库2.做ui窗口3爬虫 前言 原理简单&#xff1a;通过外链和歌曲Id拼接成下载链接来下载歌曲。 一、代码 做了个ui输入歌单链接&#xff1a; 注意这里歌单的url格式固定: https://music.163.com/playlist?id歌单id import sys from PyQt5.…

JavaWeb笔记之MySQL数据库

#Author 流云 #Version 1.0 一、引言 1.1 现有的数据存储方式有哪些&#xff1f; Java程序存储数据&#xff08;变量、对象、数组、集合&#xff09;&#xff0c;数据保存在内存中&#xff0c;属于瞬时状态存储。 文件&#xff08;File&#xff09;存储数据&#xff0c;保存…

飞致云与上海吉谛达成战略合作,获得Gitea企业版中国大陆地区独家代理权

2023年12月13日&#xff0c;中国领先的开源软件提供商FIT2CLOUD飞致云宣布与上海吉谛科技有限公司&#xff08;以下简称为上海吉谛&#xff09;正式达成战略合作&#xff0c;FIT2CLOUD飞致云获得上海吉谛旗下代码托管平台Gitea企业版中国大陆地区独家代理权。 Gitea项目&…

Github 2023-12-14开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-14统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量非开发语言项目5TypeScript项目2JavaScript项目1Jupyter Notebook项目1PHP项目1 基于项目的学习 创建周期&a…

[ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证

文章目录 一、前言二、在 Azure Portal 中创建 VM三、验证已创建的虚拟机资源3.1 方法一&#xff1a;在虚拟机服务中查看验证3.1 方法二&#xff1a;在资源组服务中查看验证 四、文末总结 一、前言 本文会开始创建新系列的专栏&#xff0c;专门更新 Azure 云实践相关的文章。 …

CAN 三: STM32 CAN相关寄存器介绍

1、寄存器列表&#xff08;F1/F4/F7&#xff09; 寄存器名称作用CAN_MCRCAN主控制寄存器主要负责CAN工作模式的配置CAN_BTR位时序寄存器用来设置分频/TBS1/TBS2/TSWJ等参数&#xff0c;设置测试模式CAN_(T/R)IxR标识符寄存器存放(待发送/接收)的报文ID、扩展ID、IDE位及RTR位C…

MySQL 报错 You can‘t specify target table for update in FROM clause解决办法

You can’t specify target table for update in FROM clause 其含义是&#xff1a;不能在同一表中查询的数据作为同一表的更新数 单独执行复合查询是正常的&#xff0c;如下&#xff1a; 但是当执行子查询删除命令时&#xff0c;报如下错误 DELETE FROM abpusers WHERE Id I…