数组中的算法

news/2024/10/25 8:13:08/

目录

1.什么是数组

2.数组上的算法

2.1二分查找算法

什么是二分查找算法

算法步骤

算法时间复杂度

一个问题

例题

题目分析

解题代码   

2.2双指针法

什么是双指针法?

例题

题目分析

解题代码


1.什么是数组

数组是在一块连续的内存空间上存储相同类型数据的集合。其实数组也是一种基本的数据结构,也是很多更加高级的数结构的基础,比如 栈、队列、哈希表……都可以基于数组实现。

下图展示了一个长度为12的 int 类型的数组:

需要注意的是: 

  • 数组的下标是从0开始计数的。
  • 数组在内存空间中的地址是连续的。

2.数组上的算法

因为数组的要求是一块连续的内存空间,所以我们可以利用其连续的特性玩一些算法

2.1二分查找算法

什么是二分查找算法

二分查找算法(Binary Search Algorithm)是一种在有序数组中查找某一特定元素的搜索算法

算法步骤

  • 定义左右两个指针。(这里的指针是形象的说法,代表数字的下标)
  • 计算出中间元素的下标,判断待查找元素与数组中间元素的大小。
  • 如果该特定元素小于中间元素,则在中间元素的左边的区间进行查找;需要更新右指针的值。
  • 如果该特定元素大于中间元素,则在中间元素的右边的区间进行查找;需要更新左指针的值。

算法时间复杂度

这种搜索算法每一次比较都使搜索范围缩小一半,因此其时间复杂度为O(log n),其中n是数组的长度。

一个问题

整个查找过程在一个循环中进行,在未找到指定元素的情况下,左指针不断向右移,右指针不断向左移,那么循环的结束条件是什么呢?是left < right 还是 left <= right 呢?

怎么写这个循环的结束条件,主要取决于left == right 的情况是否有意义,有意义就写成 <= ,没有意义就写成 < ;那么 left == right 到底有没有意义,主要取决于right指针的定义,right指针的定义决定了待查找的区间是 左闭右闭 还是 左闭右开 的。

例题

题目链接 —— 二分查找  (题目来源于力扣)

题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

题目分析

题目表明给定的数组是有序的,并且是升序,也就是说数组中没有重复的元素,因此查找到的下标是唯一的,我们可以考虑使用二分查找算法

解题代码   

写法一:定义左闭右闭区间。当我们定义区间为左闭右闭时,left == right 这种情况是有效的。

// 定义左闭右闭
class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size()-1;while(left <= right) //left == right 有意义{int mid = left + (right-left)/2; // 防止溢出if(nums[mid] > target) {right = mid-1;}else if(nums[mid] < target){left = mid+1;}else{return mid;}}return -1;}
};

写法二:定义左闭右开区间。当我们定义左闭右开区间时,left == right 这种情况是没有意义的。

// 定义左闭右开
class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size();while(left < right) //left == right 没有意义{int mid = left+(right-left)/2;if(nums[mid] < target){left = mid+1;}else if(nums[mid] > target){right = mid;}else{return mid;}}return -1;}
};

2.2双指针法

什么是双指针法?

双指针法就是用两个指针来标记数组中的元素,能够提高遍历的效率。

我们平时遍历数组的时候,都是使用一个变量来标记数组遍历的位置,但是有些情况下,一个变量不够用,这个时候就可以考虑多使用一个变量;如果还是不够,你甚至还能再增加一个变量来标记。

例题

题目链接 —— 移除元素  (题目来源于力扣)

题目:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

题目分析

题目说要我们原地移除所有数值等于val元素,但是数组是连续的空间,如果在中间移除元素,就需要将后面所有的元素都向前移动一个位置,这样一来时间复杂的会非常大。所以,在解决数组中需要删除元素的时候,我们通常考虑找一个合适的值,使用覆盖来达到删除的目的。

解题代码

解法一:暴力解法

// 暴力解法
class Solution {
public:int removeElement(vector<int>& nums, int val) {int size = nums.size();for(int i = 0; i < size; ++i) // 遍历数组,找到需要删除的值{if(nums[i] == val) //就需要移除了{// 从需要删除的值的后面找一个值来覆盖for(int j = i+1; j < size; ++j) {nums[j-1] = nums[j];}i--;size--;}}return size;}
};

解法二:双指针法

// 双指针解法
class Solution {
public:int removeElement(vector<int>& nums, int val) {int fast = 0;int slow = 0;for(fast = 0; fast < nums.size(); ++fast){if(nums[fast] != val)  // 找到不等于val的值放到前面去{nums[slow++] = nums[fast];}}return slow;}
};

双指针法对比与暴力解法,可以看出省略了一个查找替换循环的循环,减少了不必要的重复的查找。因此优化了代码的时间复杂度。


http://www.ppmy.cn/news/1541786.html

相关文章

C/C++每日一练:实现冒泡排序

题目要求 编写一个程序&#xff0c;实现冒泡排序算法。给定一个由 n 个整数组成的数组&#xff0c;要求通过冒泡排序对数组从小到大进行排序。 输入&#xff1a;一个整数数组&#xff0c;长度为 n&#xff0c;数组中的元素可能是正数或负数。 输出&#xff1a;按照升序排序后的…

PHP企业门店订货通进销存系统小程序源码

订货通进销存系统&#xff0c;企业运营好帮手&#xff01; &#x1f4e6; 开篇&#xff1a;告别繁琐&#xff0c;企业运营新选择 嘿&#xff0c;各位企业主和创业者们&#xff01;今天我要给大家介绍一款超实用的企业运营神器——“订货通进销存系统”。在这个数字化时代&…

GIS常见前端开发框架

#1024程序员节&#xff5c;征文# 伴随GIS的发展&#xff0c;陆续出现了众多开源地图框架&#xff0c;这些地图框架与众多行业应用融合&#xff0c;极大地拓展了GIS的生命力&#xff0c;这里介绍几个常见的GIS前端开发框架&#xff0c;排名不分先后。 1.Leaflet https://leafl…

重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-Spring WebFlux之HttpHandler和HttpServer 1. 什么是响应式编程&#xff1f;2. Project Reactor 概述3. HttpHandler概述3.1 HttpHandler是什么3.2 Http…

草地杂草数据集野外草地数据集田间野草数据集YOLO格式VOC格式目标检测计算机视觉数据集

一、数据集概述 数据集名称&#xff1a;杂草图像数据集 数据集是一个包含野草种类的集合&#xff0c;其中每种野草都有详细的特征描述和标记。这些数据可以包括野草的图片、生长习性、叶片形状、颜色等特征。 1.1可能应用的领域 农业领域: 农业专家和农民可以利用这一数据集来…

链路分析对性能测试的意义

目录 一、白盒能力的提升 二、人员技术门槛的提升 链路分析的出现对测试工程师也带来了不同的影响&#xff0c;能实际提升测试工程师的分析能力&#xff0c;但是需要测试工程师具备主动的自我提升意识。 一、白盒能力的提升 传统的性能测试主要以TPS、响应时间、成功率等用户…

【三方服务集成】最新版 | 阿里云短信服务SMS使用教程(包含支持单双参数模板的工具类,拿来即用!)

一、阿里云短信服务介绍 短信服务&#xff08;Short Message Service&#xff09;是阿里云为广大企业用户或个人用户提供的通信服务。通过API/SDK、控制台调用短信发送能力&#xff0c;将指定信息发送至国内或境外手机号码。可以在不同场景发送不同类型的短信&#xff0c;例如…

Vue3——模板引用

绑定dom组件 defineExpose 可以用来暴露子组件的变量&#xff08;例如 ref 或 reactive&#xff09;和方法。这让父组件可以直接访问子组件的某些状态。 defineExpose 示例 以下是如何通过 defineExpose 暴露变量的示例&#xff1a; <template> <div> <bu…