算法之反转数组

news2024/12/26 20:36:15

目录

  • 反转数组
    • 1、倒序压栈
    • 2、双指针反转
    • 3、总结
      • 时间复杂度与空间复杂度对比
      • 哪个更好?
      • 结论


反转数组

本文将使用两种方式讲述如何高效反转一个数组,同样的算法和概念也适用于字符串的反转。
什么?你说使用一个reverse函数不就实现了,来人,把这人叉出去🤧。


1、倒序压栈

倒序压栈:通过从后面遍历数组再进行压栈,实现数组反转。
这个方法简单易懂,但时间和空间复杂度都是O(n)

const arr = [9,8,7,6,5,4,3,2,1,0]

// 单指针倒序压栈实现
const reversal = (arr) => {
  const newArr = []
  for (let i = arr.length - 1; i >= 0; i--) {
    newArr.push(arr[i])
  }
  return newArr
}

2、双指针反转

双指针反转:通过首尾交换来实现数组反转。
时间复杂度是O(n),因为没有用到一个新数组来存储,空间复杂度是O(1)。
这里如果是小的数值,可以采用以下方法交换,如果数值较大或者可能是对象,则需要一个临时变量实现交换。

const reversal2 = (arr) => {
  for (let i = 0, mid = Math.floor(arr.length / 2); i < mid; i++) {
    const lastIndex = arr.length - i - 1
    arr[i] += arr[lastIndex]   // 如果数字较大,两者加法可能出现溢出的风险,可以采用临时变量来赋值交换。
    arr[lastIndex] = arr[i] - arr[lastIndex]
    arr[i] = arr[i] - arr[lastIndex]
  }
}

// 细心的同学会发现,上面函数有一个问题,就是改变了原数组,那么我们怎么才能做到不改变原数组同时反转呢?
const reversal2 = (arr) => {
  arr = [...arr]  // 浅拷贝元素
  for (let i = 0, mid = Math.floor(arr.length / 2); i < mid; i++) {
    const lastIndex = arr.length - i - 1
    arr[i] += arr[lastIndex]
    arr[lastIndex] = arr[i] - arr[lastIndex]
    arr[i] = arr[i] - arr[lastIndex]
  }
  return arr
}

3、总结


时间复杂度与空间复杂度对比

  • 时间复杂度:两个方法的时间复杂度都是 (O(n)),所以在时间上是相同的。
  • 空间复杂度
    • 双指针逆序 是原地算法,不需要额外的空间,因此空间复杂度为 (O(1))。
    • 单指针倒序压栈 需要使用栈来存储所有元素,因此空间复杂度为 (O(n)),这比双指针方法消耗更多的内存。

哪个更好?

  • 双指针逆序 的空间复杂度明显更好,因为它是原地操作,不需要额外的存储空间。因此,双指针逆序通常是更优的选择,尤其在需要处理大量数据时,能够减少内存消耗。
  • 单指针倒序压栈 虽然时间复杂度相同,但它的额外栈空间使得它不适合内存有限的环境或大规模数据操作。

结论

从效率和资源消耗的角度来看,双指针逆序是更好的方法

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

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

相关文章

STM32-C语言基础知识

C语言基础知识 stdint.h简介 给寄存器某个位赋值 给位6赋值为1流程&#xff1a;先清0&#xff0c;再赋值 带参数的宏定义 建议使用do {…}while(0)来构造宏定义 条件编译 条件编译后面必须跟宏语句&#xff0c;如#if _LED_H 指针使用常见的2大问题 1、未初始化 2、越界使…

Android 应用单元测试涉及 Telephony 环境初始化问题

Telephony 相关类注入问题 SubscriptionManager Cannot invoke "android.telephony.SubscriptionManager.getActiveSubscriptionInfoList()" because "this.mSubscriptionManager" is nulljava.lang.NullPointerException: Cannot invoke "android.t…

mysql 存储结构的进化之路

文章目录 前言一、线性结构二、二叉树&#xff08;BST&#xff09;三、平衡二叉树&#xff08;AVL&#xff09;四、多路平衡查找树&#xff08;B Tree&#xff09;五、加强版多路平衡查找树&#xff08;B Tree&#xff09;总结 前言 树形结构是一种具有层次关系的数据结构&…

高速定向广播声光预警系统赋能高速安全管控

近年来&#xff0c;高速重大交通事故屡见不鲜&#xff0c;安全管控一直是高速运营的重中之重。如何利用现代化技术和信息化手段&#xff0c;创新、智能、高效的压降交通事故的发生概率&#xff0c;优化交通安全管控质量&#xff0c;是近年来交管部门的主要工作&#xff0c;也是…

【机器学习】CatBoost 模型实践:回归与分类的全流程解析

一. 引言 本篇博客首发于掘金 https://juejin.cn/post/7441027173430018067。 PS&#xff1a;转载自己的文章也算原创吧。 在机器学习领域&#xff0c;CatBoost 是一款强大的梯度提升框架&#xff0c;特别适合处理带有类别特征的数据。本篇博客以脱敏后的保险数据集为例&#x…

游戏引擎学习第25天

Git: https://gitee.com/mrxiao_com/2d_game 今天的计划 总结和复述&#xff1a; 这段时间的工作已经接近尾声&#xff0c;虽然每次编程的时间只有一个小时&#xff0c;但每一天的进展都带来不少收获。尽管看起来似乎花费了很多时间&#xff0c;实际上这些日积月累的时间并未…

AI开发:生成式对抗网络入门 模型训练和图像生成 -Python 机器学习

阶段1&#xff1a;GAN是个啥&#xff1f; 生成式对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;&#xff0c;名字听着就有点“对抗”的意思&#xff0c;没错&#xff01;它其实是两个神经网络互相斗智斗勇的游戏&#xff1a; 生成器&#xff08;Gene…

040集——CAD中放烟花(CAD—C#二次开发入门)

效果如下&#xff1a; 单一颜色的烟花&#xff1a; 渐变色的火花&#xff1a; namespace AcTools {public class HH{public static TransientManager tm TransientManager.CurrentTransientManager;public static Random rand new Random();public static Vector3D G new V…

JavaScript实现tab栏切换

JavaScript实现tab栏切换 代码功能概述 这段代码实现了一个简单的选项卡&#xff08;Tab&#xff09;切换功能。它通过操作 HTML 元素的类名&#xff08;class&#xff09;来控制哪些选项卡&#xff08;Tab&#xff09;和对应的内容板块显示&#xff0c;哪些隐藏。基本思路是先…

【天地图】HTML页面实现车辆轨迹、起始点标记和轨迹打点的完整功能

目录 一、功能演示 二、完整代码 三、参考文档 一、功能演示 运行以后完整的效果如下&#xff1a; 点击开始&#xff0c;小车会沿着轨迹进行移动&#xff0c;点击轨迹点会显示经纬度和时间&#xff1a; 二、完整代码 废话不多说&#xff0c;直接给完整代码&#xff0c;替换…

HCIA笔记6--路由基础与静态路由:浮动路由、缺省路由、迭代查找

文章目录 0. 概念1.路由器工作原理2. 跨网访问流程3. 静态路由配置4. 静态路由的应用场景4.1 路由备份4.2 浮动路由4.3 缺省路由 5. 迭代路由6 问题6.1 为什么路由表中有的下一跳的地址有接口&#xff1f;6.2 个人电脑的网关本质是什么&#xff1f; 0. 概念 自治系统&#xff…

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libncurses.so.5的问题

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libncurses.so.5的问题 2024/11/29 21:11 缘起&#xff1a;中科创达的高通CM6125开发板的Android10的编译环境需要。 vendor/qcom/proprietary/commonsys/securemsm/seccamera/service/jni/jni_if.…

Matlab搜索路径添加不上

发现无论是右键文件夹添加到路径&#xff0c;还是在“设置路径”中专门添加&#xff0c;我的路径始终添加不上&#xff0c;导致代码运行始终报错&#xff0c;后来将路径中的“”加号去掉后&#xff0c;就添加成功了&#xff0c;经过测试&#xff0c;路径中含有中文也可以添加成…

自由学习记录(28)

C# 中的流&#xff08;Stream&#xff09; 流&#xff08;Stream&#xff09;是用于读取和写入数据的抽象基类。 流表示从数据源读取或向数据源写入数据的矢量过程。 C# 中的流类是从 System.IO.Stream 基类派生的&#xff0c;提供了多种具体实现&#xff0c;每种实现都针对…

Redis3——线程模型与数据结构

Redis3——线程模型与数据结构 本文讲述了redis的单线程模型和IO多线程工作原理&#xff0c;以及几个主要数据结构的实现。 1. Redis的单线程模型 redis6.0之前&#xff0c;一个redis进程只有一个io线程&#xff0c;通过reactor模式可以连接大量客户端&#xff1b;redis6.0为了…

使用playwright自动化测试时,npx playwright test --ui打开图形化界面时报错

使用playwright自动化测试时&#xff0c;npx playwright test --ui打开图形化界面时报错 1、错误描述&#xff1a;2、解决办法3、注意符号的转义 1、错误描述&#xff1a; 在运行playwright的自动化测试项目时&#xff0c;使用npm run test无头模式运行正常&#xff0c;但使用…

深度学习模型:门控循环单元(GRU)详解

本文深入探讨了门控循环单元&#xff08;GRU&#xff09;&#xff0c;它是一种简化版的长短期记忆网络&#xff08;LSTM&#xff09;&#xff0c;在处理序列数据方面表现出色。文章详细介绍了 GRU 的基本原理、与 LSTM 的对比、在不同领域的应用以及相关的代码实现&#xff0c;…

用html+jq实现元素的拖动效果——js基础积累

用htmljq实现元素的拖动效果 效果图如下&#xff1a; 将【item10】拖动到【item1】前面 直接上代码&#xff1a; html部分 <ul id"sortableList"><li id"item1" class"w1" draggable"true">Item 1</li><li …

单片机学习笔记 12. 定时/计数器_定时

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

【乐企文件生成工程】搭建docker环境,使用docker部署工程

1、自行下载docker 2、自行下载docker-compose 3、编写Dockerfile文件 # 使用官方的 OpenJDK 8 镜像 FROM openjdk:8-jdk-alpine# 设置工作目录 WORKDIR ./app# 复制 JAR 文件到容器 COPY ../lq-invoice/target/lq-invoice.jar app.jar # 暴露应用程序监听的端口 EXPOSE 1001…