暑期算法训练.5

目录

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

20.1 题目解析:

20.2 算法思路:

20.3 代码演示:

​编辑

20.4 总结反思:

21.力扣 69.x的平方根 

21.1 题目解析:

21.2 算法思路:

21.3 代码演示:

21.4 总结反思:

22. 力扣 35.搜索插入位置

22.1 题目解析:

22.2 算法思路:

22.3 代码演示:

​编辑

22.4 总结反思:

23 力扣. 852 山脉数组的封顶索引

23.1 题目解析:

23.2 算法思路:

23.3 代码演示:

23.4 总结反思:

24.力扣 162 寻找峰值:

24.1 题目解析:

​编辑 

24.2 算法思路:

24.3 代码演示:

24.4 总结反思:

25.力扣 LCR 173 点名

25.1 题目解析:

25.2 算法思路:

25.3 代码演示:

​编辑

25.4 总结反思:

26 力扣 153.寻找旋转排序数组中的最小值

26.1 题目解析:

26.2 算法思路:

26.3 代码演示:

​编辑

26.4 总结反思:

 

 

 

 

 


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

20.1 题目解析:

题目很好理解,就是让你找出目标值的开始以及结束的位置。不过这道题目要注意处理一下,空数组以及没有结果的情况。

20.2 算法思路:

1.解法一就是暴力解法,就是遍历一遍数组,然后找出区间即可。这个的时间复杂度肯定是O(N)

2.解法二是咱们今天重点讲解的,就是用二分算法去解决这道题目。咱们直到,要想用二分算法,得先关注一下这道题目,得具有二段性才可以使用二分算法。 升不升序倒是无所谓。因为你只要发现了规律,均可以使用二分算法。

【1】求区间左端点

 

【2】求区间右端点

总结一下就是:

 

好了,这个题目的算法思路可算是写明白了。

20.3 代码演示:

vector<int> searchRange(vector<int>& nums, int target) {if (nums.size() == 0)  return { -1,-1 };//处理一下数组为空的情况int begin = 0;int left = 0; int right = nums.size() - 1;while (left < right){int mid = left + (right - left) / 2;if (nums[mid] < target) left = mid + 1;else right = mid;}//判断一下是否有结果,因为出了while循环后,left==rightif (nums[left] != target) return { -1,-1 };else begin = left;//这里写begin的目的仅仅是为了将left给存起来left = 0; right = nums.size() - 1;//其实,left直接从左端点开始就可以了while (left < right){int mid = left + (right - left + 1) / 2;if (nums[mid] <= target) left = mid;else right = mid - 1;}return { begin,right };//此时不需要判断是否有结果,因为只要有左端点,那么就一定有结果
}
int main()
{vector<int> nums = { 5,7,7,8,8,10 };int target = 8;vector<int> outcome = searchRange(nums, target);for (auto& e : outcome){cout << e << "";}cout << endl;return 0;
}

20.4 总结反思:

咱们来总结一下这类二分的模板:

 

不用死记硬背,只需要记住一点:就是若是下面出现了-1,那么上面mid给它加上1就可以了。

记住了求中点的方式,就可以推导出其他的了。

21.力扣 69.x的平方根 

21.1 题目解析:

21.2 算法思路:

暴力解法很简单,就是遍历一边【0,x】内的数字i,若 i*i=x,直接返回x。若是i*i>x,则返回上一个数即可。

下面看解法二:

注意:寻找区间左端点,即找到大于等于目标值,说明右边还有满足条件的目标值(第一个满足条件的元素)。

寻找区间右端点:即找到小于等于目标值,说明右边不可能还有满足条件的目标值。(最后一个满足条件的元素)

所以说,为什么说这个寻找左端点是: <       >=.原理上将等于归于右边,是因为若mid位于两个相等的值中间,此时不是最终结果。但你也可以想成,就是找左端点,右边肯定还有值。所以找右端点:左边还有值,就是<=       >

所以本题是寻找k*k<=x,寻找右端点模板。

21.3 代码演示:

int mySqrt(int x) {if (x < 1)  return 0;//处理边界情况int left = 0;long long right = x;while (left < right){long long mid = left + (right - left + 1) / 2;//long long 防止溢出if (mid * mid <= x)  left = mid;else right = mid - 1;}return left;
}
int main()
{int x = 4;cout << mySqrt(x) << endl;return 0;
}

21.4 总结反思:

这个起始也就是一种二分算法的模板而已。

22. 力扣 35.搜索插入位置

22.1 题目解析:

注意关键句子:有序数组找到一个值。

22.2 算法思路:

1.找到了:直接返回下标即可。

2.若是没找到,就第一次出现了比目标值大的那个数(那个数大于等于目标值target)。或者数组末尾。

这个mid(x)其实就是“那个数”,然后再继续进行判断即可。

22.3 代码演示:

int searchInsert(vector<int>& nums, int target) {int left = 0; int right = nums.size() - 1;while (left < right){int mid = left + (right - left) / 2;if (nums[mid] < target)  left = mid + 1;else right = mid;}if (nums[left] < target) return left + 1;//处理一下边界的情况,就是插入到数组末尾return left;
}
int main()
{vector<int> nums = { 1,3,5,6 };int target = 5;cout << searchInsert(nums, target) << endl;return 0;
}

22.4 总结反思:

这道题目是用到了求左端点的模板。要注意分清楚,还是挺好抓住的。

23 力扣. 852 山脉数组的封顶索引

23.1 题目解析:

就是让你找出山顶的索引。

23.2 算法思路:

就是找出最大的值呗。

1.暴力解法也好办,即使先遍历一遍数组,直至找到后一个数字比前一个数字小为止。返回那个数字的下标就可以了。

2.解法二就是二分查找算法:

那么这个时候:1.arr[mid]>arr[mid-1](说明要到右区间去找),left=mid

                          2.arr[mid]<arr[mid-1](说明要到左区间去找),即right=mid-1

mid位置呈现上升:那么接下来要在[mid+1,right]区间内搜索山峰。

mid位置呈现下降趋势,在[left,mid-1]区间内搜索山峰。

mid位置就是山峰,那么直接返回即可。

23.3 代码演示:

int peakIndexInMountainArray(vector<int>& arr) {int left = 0; int right = arr.size();while (left < right){int mid = left + (right - left + 1) / 2;if (arr[mid] > arr[mid - 1])  left = mid;else right = mid - 1;}return left;
}
int main()
{vector<int> arr = { 0,1,0 };cout << peakIndexInMountainArray(arr) << endl;return 0;
}

23.4 总结反思:

这道题目就不可以傻乎乎的再硬用了,需要分析一下为什么使用二分算法了。

24.力扣 162 寻找峰值:

24.1 题目解析:

 

上一道题目是只有一个峰,但这个是有好多个峰,但是只返回任意一个峰即可。

并且题目中要求左,右,都可以是无穷小。

24.2 算法思路:

暴力解法:就是从第一个位置开始,一直向后走,分情况讨论:

 

1.一开始就下降。2,上升着突然就下降了。3  一直向上走到最后一个位置。

2.二分算法:

 

这个mid应该就是随机选取的地方,然后再由这个分析规律(一开始,mid可能不等于你要求的那个值,只要是一个随机的值,但是循环完了,之后呢?left=right,此时的mid即为所求的值了。)

且上面所说的模板,若你right=mid-1,看到了减去一,那么在前面加上一就可以了。 

24.3 代码演示:

 

int findPeakElement(vector<int>& nums) {int left = 0; int right = nums.size() - 1;while (left < right){int mid = left + (right - left) / 2;if (nums[mid] > nums[mid + 1]) right = mid;else left = mid + 1;}return left;
}int main()
{vector<int> nums = { 1,2,3,1 };cout << findPeakElement(nums) << endl;return 0;
}

24.4 总结反思:

这道题目也是考你灵活的运用二分模板。

25.力扣 LCR 173 点名

25.1 题目解析:

 这道题目就是让你找出缺失的数字

25.2 算法思路:

其实这道题目解法有很多,但是咱们今天在这里只讲二分算法:

这个3就是区间的左端点。

1.左区间:若nums[mid]==mid,则left=mid+1;

2.右区间:nums[mid]!=mid,则right=mid

细节问题:边界:[0 ,1 ,2 ,3 ] 那么它缺的就是4.但是二分算法寻找的是右区间。但是这里没有右区间。所以,若最后一个值与下标值相同,则为完全递增数组,则返回left+1即可。

25.3 代码演示:

//点名
int takeAttendance(vector<int>& records) {int left = 0; int right = records.size() - 1;while (left < right){int mid = left + (right - left) / 2;if (records[mid] == mid)  left = mid + 1;else right = mid;}if (left == records[left]) return left + 1;else return left;
}
int main()
{vector<int> records = { 0,1,2,3,5 };cout << takeAttendance(records) << endl;return 0;
}

25.4 总结反思:

这道题目也是一道令人有想法的二分算法。 

26 力扣 153.寻找旋转排序数组中的最小值

26.1 题目解析:

这道题目是我做的二分算法题目里面最不好理解的,也是最不好想的。题目很简单。咱们接下来看怎么做

26.2 算法思路:

咱们只讲二分算法:

 

好,这个是以D点为参照点。那么以A点为参照点呢?

26.3 代码演示:

以D点为参照点:

//寻找旋转排序数组中的最小值
//以D点为参照点
int findMin(vector<int>& nums)
{int left = 0, right = nums.size() - 1;int x = nums[right]; // 标记⼀下最后⼀个位置的值(D点)while (left < right){int mid = left + (right - left) / 2;if (nums[mid] > x) left = mid + 1;else right = mid;}return nums[left];
}
int main()
{vector<int> nums1 = { 4,5,6,7,0,1,2 };vector<int> nums2 = { 3,4,5,1,2 };vector<int> nums3 = { 11,13,15,17 };cout << "nums1的最小值: " << findMin(nums1) << endl; // 输出0cout << "nums2的最小值: " << findMin(nums2) << endl; // 输出1cout << "nums3的最小值: " << findMin(nums3) << endl; // 输出11return 0;
}

以A点为参照点:

//以A点为参照点
int findMin(vector<int>& nums) {int left = 0;                  // A点,左边界int right = nums.size() - 1;// 数组未旋转的情况(完全升序)if (nums[left] <= nums[right]) {return nums[left];}// 二分查找while (left < right) {int mid = left + (right - left) / 2;// 中间元素大于左边界元素,说明左半部分有序,最小元素在右半部分if (nums[mid] > nums[left]) {left = mid;}// 中间元素小于左边界元素,说明最小元素在左半部分(包括mid)else {right = mid;}}// 循环结束时left == right,此时下一个元素即为最小值return nums[left + 1];
}
int main()
{vector<int> nums1 = { 4,5,6,7,0,1,2 };vector<int> nums2 = { 3,4,5,1,2 };vector<int> nums3 = { 11,13,15,17 };cout << "nums1的最小值: " << findMin(nums1) << endl; // 输出0cout << "nums2的最小值: " << findMin(nums2) << endl; // 输出1cout << "nums3的最小值: " << findMin(nums3) << endl; // 输出11return 0;
}

26.4 总结反思:

这道题目是今天最抽象的题目,大脚要好好的理解才可以。

本篇完...................... 

 

 

 

 

 

 

 

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

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

相关文章

【HDLBits习题详解 2】Circuit - Sequential Logic(5)Finite State Machines 更新中...

1. Fsm1&#xff08;Simple FSM 1 - asynchronous reset&#xff09;状态机可分为两类&#xff1a;&#xff08;1&#xff09;Mealy状态机&#xff1a;输出由当前状态和输入共同决定。输入变化可能立即改变输出。&#xff08;2&#xff09;Moore状态机&#xff1a;输出仅由当前…

多级缓存(亿级流量缓存)

传统缓存方案问题 多级缓存方案 流程 1.客户端浏览器缓存页面静态资源; 2. 客户端请求到Nginx反向代理;[一级缓存_浏览器缓存] 3.Nginx反向代理将请求分发到Nginx集群(OpenResty); 4.先重Nginx集群OpenResty中获取Nginx本地缓存数据;[二级缓存_Nginx本地缓存] 5.若Nginx本地缓存…

浅谈Rust语言特性

如大家所了解的&#xff0c;Rust是一种由Mozilla开发的系统编程语言&#xff0c;专注于内存安全、并发性和高性能&#xff0c;旨在替代C/C等传统系统编程语言。Rust 有着非常优秀的特性&#xff0c;例如&#xff1a;可重用模块 内存安全和保证&#xff08;安全的操作与不安全的…

React探索高性能Tree树组件实现——react-window、react-vtree

&#x1f680; 简介 在现代 Web 应用中&#xff0c;处理大量层级数据的树形结构是一个常见挑战。传统的树组件在面对成千上万个节点时往往会出现性能瓶颈&#xff0c;导致页面卡顿、内存占用过高等问题。本文将深入探讨如何使用 react-window 和 react-vtree 构建高性能的虚拟…

C++ 中的默认构造函数:非必要,不提供

《More Effective C&#xff1a;35个改善编程与设计的有效方法》 读书笔记&#xff1a;非必要不提供default constructor在 C 中&#xff0c;默认构造函数&#xff08;即无需任何参数即可调用的构造函数&#xff09;是对象“无中生有”的一种方式。它的核心作用是在没有外部信息…

如何选择低代码开发平台

选择低代码开发平台需要考虑平台的开发效率、灵活性和扩展能力、安全性和合规性、成本效益等关键因素。 具体来说&#xff0c;平台的灵活性和扩展能力尤为重要&#xff0c;这决定了平台是否能长期满足企业日益增长的复杂需求。例如&#xff0c;企业在评估平台时&#xff0c;应关…

电子数据取证领域的双轮驱动——手工分析 vs 自动化分析

在你刚步入电子数据取证领域时&#xff0c;可能很快就注意到一个普遍现象&#xff1a;大多数取证分析师前期都花费大量时间在网上查阅博客、PDF、推文等信息&#xff0c;寻找证据线索的“藏身之处”——例如注册表项、日志文件路径、可疑文件命名模式或远程登录痕迹等。这种信息…

《Python 实时通信全解:掌握 WebSocket 技术与 HTTP 的本质区别》

🚀《Python 实时通信全解:掌握 WebSocket 技术与 HTTP 的本质区别》 引言:通信方式的演进与 Python 的角色 在数字化世界里,**“实时性”**已经成为构建高质量应用的核心诉求。从聊天工具到股票交易系统,再到物联网设备管理——通信的即时响应能力直接决定用户体验。而…

GeoTools 自定义坐标系

前言在GIS开发中&#xff0c;坐标系统是重中之重&#xff0c;在接到任务时首先要确定的就是坐标系。大多数地图库或者互联网地图默认支持WGS84地理坐标系和Web墨卡托投影坐标系。而在我国要求使用自然资源数据使用2000国家大地坐标&#xff08;CGCS2000&#xff09;。1. 背景 经…

[特殊字符] Java反射从入门到飞升:手撕类结构,动态解析一切![特殊字符]

【&#x1f50d;震撼揭秘】 你是否曾想窥探Java类的内部结构&#xff1f;&#x1f914; 是否好奇Spring框架如何实现"万物皆可注入"&#xff1f;✨ 本文将带你从反射小白晋升为反射高手&#xff0c;用一行代码透视任意类的构造方法、成员变量和私有方法&#xff01;&…

CMake与catkin_make的find_package()命令使用说明

在 CMake 中&#xff0c;find_package() 是一个核心函数&#xff0c;用于查找并加载外部依赖库的配置。它的主要作用是定位头文件、库文件&#xff0c;并设置相关变量&#xff0c;以便后续编译和链接。以下是详细解析&#xff1a; 1. 基本语法 find_package(<PackageName&g…

Spring--BeanFactoryPostProcessor的用法

原文网址&#xff1a;Spring--BeanFactoryPostProcessor的用法_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Spring的BeanFactoryPostProcessor的用法。 BeanPostProcessor和BeanFactoryPostProcessor的区别 项BeanPostProcessorBeanFactoryPostProcessor处理的对象处理…

了解类加载器吗?类加载器的类型有哪些?

一、什么是类加载器&#xff08;ClassLoader&#xff09; 类加载器是 Java 虚拟机中的一部分&#xff0c;负责将 .class 文件加载到 JVM 内存中&#xff0c;生成对应的 Class 对象。 Java 程序中所有的类在使用前都必须通过类加载器加载进 JVM&#xff0c;才能被执行。二、类加…

PHP面向对象高级特性:魔术方法、对象迭代器与设计模式应用

引言 在前一篇文章中,我们探讨了PHP的Traits、匿名类和对象比较机制。本文将深入PHP面向对象编程的更多高级特性,包括魔术方法、对象迭代器以及常用设计模式的实际应用,这些特性能够帮助开发者构建更加灵活和强大的面向对象系统。 魔术方法深度解析 魔术方法是PHP中一组以…

【Java基础】一个月教你轻松掌握Java——第三篇Git

一、Java概述&#xff08;之前的文章&#xff09;二、版本控制工具Git其实这个与Java基础关系不大&#xff0c;但是这个工具还是很重要的&#xff0c;不管是团队之间打比赛还是就业都应该学会它&#xff0c;秉持着学的早一些&#xff0c;用的时间长一点&#xff0c;会更熟练。&…

【C# in .NET】16. 探秘类成员-索引器:通过索引访问对象

探秘类成员-索引器:通过索引访问对象 在 C# 中,索引器(Indexer)是一种独特的类成员,它允许类或结构的实例像数组一样被索引访问,为数据访问提供了极大的灵活性。本文将从基础概念出发,深入.NET 框架底层,剖析索引器的实现机制,并通过实战案例展示其强大的应用价值。 …

idea出现:java: Target level ‘1.7‘ is incompatible with source level ‘1.8‘.解决办法

在文件->设置->java编译器&#xff0c;把这里版本对应上。这里用的是8版本

ssms(SQL 查询编辑器) 添加快捷键 Ctrl+D(功能等于Ctrl+C + Ctrl+V),一步到位

1,打开ssms 工具&#xff0c;打开对应添加快捷键得地方2&#xff0c;分配 快捷键3&#xff0c;看效果

数学建模--层次分析法

层次分析法&#xff08;AHP&#xff09;笔记 一、核心概念 &#xff08;一&#xff09;问题本质 面对多方案、多准则决策&#xff0c;将复杂问题分层拆解&#xff0c;通过定性与定量结合&#xff0c;确定各因素权重&#xff0c;选出最优方案&#xff0c;比如选“微博之星”时综…

人工智能教研室暑期培训flask全栈开发培训

人工智能教研室暑期培训flask全栈开发培训第一天&#xff1a;Flask 基础入门与环境搭建实践项目&#xff1a;搭建个人博客首页&#xff0c;包含文章列表与详情页上午&#xff1a;环境搭建与 Flask 基础1. 安装 Python 与虚拟环境配置2. Flask 框架简介与第一个 "Hello Wor…