算法学习笔记(Hello算法)—— 初识算法

news2024/11/15 11:12:08

1、相关链接

Hello算法:Hello 算法 (hello-algo.com)

2、算法是什么

2.1 算法定义

算法是一系列明确、有限且有效的步骤或指令的集合,用于解决特定问题或执行特定任务。

算法具有以下基本特征:

  • 输入:算法至少有一个输入(某些算法可能有多个输入),或者可以没有输入。
  • 输出:算法必须至少产生一个输出,这个输出是解决问题的结果。
  • 明确性:算法中的每一步都必须清晰无误,不能有歧义。
  • 有限性:算法必须在有限的时间内完成,不能无限循环下去。
  • 可行性:算法的每一步都应该是基本操作,可以被实际执行。
2.2 数据结构定义

数据结构(Data Structure)是计算机存储、组织数据的方式。它是计算机科学中的一个重要概念,主要目的是使数据的存储和访问更加高效、方便。数据结构根据其性质和用途,可以分为多种不同的类型。

不同数据元素之间不是独立的,而是存在特定的关系,我们将这些关系称为结构。

以下是数据结构的基本定义:

  1. 数据对象的集合:数据结构是数据对象(或称为元素、值)的集合,这些对象可以是数字、字符、记录等。

  2. 数据对象之间的关系:数据结构不仅包含数据对象,还包含数据对象之间的关系。这些关系定义了数据对象是如何组织和联系的。

  3. 操作的集合:数据结构通常伴随着一系列预定义的操作,这些操作可以创建、修改、访问和删除数据结构中的数据。

数据结构的主要类型包括:

  • 逻辑结构:这是从逻辑关系角度描述数据结构的,不考虑数据在计算机中的实际存储方式。常见的逻辑结构有:

    • 集合
    • 线性结构(如数组、链表、栈、队列)
    • 树形结构(如二叉树、多叉树、堆)
    • 图形结构(如无向图、有向图)
  • 物理结构:这是数据结构在计算机中的实际存储方式,描述了数据的物理位置关系。常见的物理结构有:

    • 顺序存储结构:数据元素在内存中连续存放。
    • 链式存储结构:数据元素可以分散存储,通过指针连接。

数据结构的选择对算法的设计和程序的效率有着重要的影响。不同的数据结构适合解决不同类型的问题,例如:

  • 数组适合随机访问,但不适合频繁的插入和删除操作。
  • 链表适合频繁的插入和删除操作,但随机访问效率较低。
  • 结构适合表示具有层次或网状关系的数据。
2.3 数据结构和算法的关系

数据结构与算法之间有着紧密的关系,它们相辅相成,共同构成了计算机科学的核心内容。以下是数据结构与算法关系的几个方面:

算法依赖于数据结构

  • 算法的设计往往需要根据待处理数据的特性来选择合适的数据结构。例如,排序算法通常需要数组这种可以随机访问的数据结构,而图算法则需要用到图这种可以表示复杂关系的结构。
  • 不同的数据结构可以影响算法的效率。例如,在链表和数组上实现排序算法,其时间和空间复杂度可能会有显著差异。

数据结构为算法提供服务

  • 数据结构提供了存储和管理数据的手段,使得算法能够高效地读取和修改数据。
  • 数据结构封装了一些基本操作,如插入、删除、查找等,这些操作是算法实现的基础。

算法实现数据结构的操作

  • 数据结构定义了一组操作,而算法则是这些操作的实现。例如,链表数据结构定义了插入和删除操作,具体的插入和删除算法则决定了这些操作如何执行。

算法效率受数据结构影响

  • 数据结构的选择直接影响算法的性能。例如,哈希表提供了平均情况下常数时间的查找效率,而二叉搜索树则提供了对数时间的查找效率。
  • 合适的数据结构可以降低算法的时间复杂度和空间复杂度。

2.4 其他定义

数据:是描述害观事物的符号,是计算机中可以操作的对象,是能被计算机识别,并输入给计算机处理的符号集合。数据不仅仅包括整型、实型等数值类型’还包括字符及声音、图像、视频等非数值类型。·

数据元素:是组成数据的、有一定意义的墓本单位,在计算机中通常作为整体处理,也被称为记录。

数据顶:—个数据元素可以由若干个数据顶组成。

比如人这样的数据元素,可以有眼睛、耳朵、鼻子、嘴巴、手、脚这些数据项,也可以有姓名、年龄、性别、家庭地址、联系电话、邮政编码等数据项,具体有哪些数据项,要由你做的系统来决定。

数据项是数据不可分割的最小单位。

数据对象:呈性质相同的数据元素的集合,是数据的子集。

2.算法复杂度分析

在算法设计中,我们先后追求以下两个层面的目标。

  • 找到问题解法:算法需要在规定的输入范围内可靠地求得问题的正确解。
  • 寻求最优解法:同一个问题可能存在多种解法,我们希望找到尽可能高效的算法。

算法效率已成为衡量算法优劣的主要评价指标,它包括以下两个维度。

  • 时间效率:算法运行速度的快慢。 ‧
  • 空间效率:算法占用内存空间的大小。

效率评估方法主要分为两种:实际测试、理论估算。

实际测试的优点和缺点

优点:

  • 实际反映:实际测试可以在真实的硬件和软件环境下运行算法,能够反映出算法在实际使用中的性能,包括执行时间和内存消耗。
  • 易于理解:测试结果通常以直观的数字形式呈现,易于非专业人士理解。
  • 发现隐藏问题:在测试过程中可能会发现算法在实际应用中才会出现的隐藏问题,如并发执行时的竞态条件、内存泄漏等。
  • 比较不同系统:通过在不同系统上进行测试,可以比较算法在不同环境下的表现。

缺点:

  • 时间消耗:进行实际测试需要花费大量时间,特别是对于复杂算法和大数据集。
  • 可能不全面:测试可能只覆盖了算法的部分功能或特定数据集,无法全面评估算法的性能。
  • 环境依赖:测试结果受测试环境(如CPU、内存、操作系统等)的影响,可能不具有普遍性。
  • 结果解释困难:有时候测试结果可能会因为外部因素(如系统负载)而出现波动,解释这些波动可能比较困难。

理论估算的优点和缺点

优点:

  • 普适性:理论估算通常基于数学模型,可以在不考虑具体硬件和软件环境的情况下评估算法的性能。
  • 预测性:理论分析可以帮助预测算法在不同规模数据上的表现,特别是在大数据集上。
  • 成本低:与实际测试相比,理论估算通常不需要实际的硬件资源,成本较低。
  • 指导意义:理论分析可以为算法改进提供方向,帮助开发者理解算法的局限性。

缺点:

  • 抽象性:理论估算往往较为抽象,可能难以被非专业人士理解。
  • 忽略实际因素:理论模型可能无法完全反映现实世界中的所有因素,如磁盘I/O、网络延迟等。
  • 可能不准确:理论估算基于假设,如果这些假设与实际情况不符,估算结果可能不准确。
  • 复杂度高:对于复杂算法,进行理论分析可能需要高级数学知识和复杂的推导过程。

总的来说,实际测试和理论估算是互补的。在实际应用中,通常会结合这两种方法来全面评估算法的效率。理论估算可以提供一个初步的指导,而实际测试则可以验证理论分析的结果,并发现实际应用中可能遇到的问题。

2.2 迭代与递归

两种基本的程序控制结构:迭代、递归。

2.2.1 迭代

迭代(Iteration)是一种在计算过程中重复执行一系列操作的方法或概念。在编程和算法设计中,迭代通常指的是通过循环结构来重复执行一段代码,直到满足某个终止条件。

  • for循环:当知道迭代的次数时使用。

  • while循环:当迭代的次数未知,但知道何时停止时使用。

  • do-while循环(某些语言中):至少执行一次循环体,然后根据条件决定是否继续迭代。

  • 嵌套循环:在一个循环结构内嵌套另一个循环结构

public class Fibonacci {

    public static void main(String[] args) {
        int n = 10; // 例如,计算斐波那契数列的第10个数
        int result = fibonacciIterative(n);
        System.out.println("斐波那契数列的第" + n + "个数是: " + result);
    }

    // 迭代方法计算斐波那契数列
    public static int fibonacciIterative(int n) {
        if (n <= 1) {
            return n;
        }
        int fib = 1;
        int prevFib = 1;

        for (int i = 2; i < n; i++) {
            int temp = fib;
            fib += prevFib;
            prevFib = temp;
        }
        return fib;
    }
}
2.2.2 递归

递归(Recursion)是一种编程和算法设计中的技术,它涉及函数或方法调用自身以解决一个更小或更简单的问题。递归通常用于解决那些可以分解为相似子问题的问题。

递归的基本要素:

  • 基线条件(Base Case):这是递归终止的条件。基线条件是递归算法必须达到的一个简单情况,它可以直接解决而无需进一步递归。(终止条件:用于决定什么时候由“递”转“归”。)

  • 递归步骤(Recursive Step):这是算法中递归调用的部分,它将问题分解为更小的子问题。(返回结果:对应“归”,将当前递归层级的结果返回至上一层。)

  • 递归调用(Recursive Call):这是函数或方法调用自身的操作,通常输入更小或更简化的参数。

以下是一个使用递归在Java中计算阶乘的案例。阶乘是一个经典的递归问题,其中n!(n的阶乘)定义为n * (n-1) * (n-2) * ... * 1,并且0!被定义为1

public class Factorial {

    // 递归方法计算阶乘
    public static int factorial(int n) {
        // 基线条件:如果n为0,返回1
        if (n == 0) {
            return 1;
        }
        // 递归步骤:n! = n * (n-1)!
        return n * factorial(n - 1);
    }

    public static void main(String[] args) {
        int number = 5; // 示例:计算5的阶乘
        int result = factorial(number);
        System.out.println(number + "! = " + result);
    }
}

迭代与递归可以得到相同的结果,但它们代表了两种完全不同的思考和解决问题的范式。

  • 迭代:“自下而上”地解决问题。从最基础的步骤开始,然后不断重复或累加这些步骤,直到任务完成。
  • 递归:“自上而下”地解决问题。将原问题分解为更小的子问题,这些子问题和原问题具有相同的形式。
  • 迭代:在循环中模拟求和过程,从 1 遍历到 𝑛 ,每轮执行求和操作,即可求得 𝑓(𝑛) 。
  • 递归:将问题分解为子问题 𝑓(𝑛) = 𝑛+𝑓(𝑛−1) ,不断(递归地)分解下去,直至基本情况 𝑓(1) = 1 时终止。

不同点:

  • 定义方式

    • 递归:函数自身调用自身。
    • 迭代:通过循环结构重复执行一系列操作。
  • 内存使用

    • 递归:通常使用更多的内存,因为每次函数调用都需要在调用栈上保存信息。
    • 迭代:通常使用更少的内存,因为它不需要额外的栈空间。
  • 性能

    • 递归:在某些情况下可能比迭代慢,因为它涉及更多的函数调用开销。
    • 迭代:通常在运行时更高效,因为它减少了函数调用的开销。
  • 代码简洁性

    • 递归:可以使代码更简洁,更易于理解,尤其是对于某些自然递归的问题,如树遍历、分治算法等。
    • 迭代:可能需要更多的代码来处理循环和状态变量,有时这会使代码更难理解。
  • 可读性和维护性

    • 递归:对于某些问题,递归解决方案更符合人的直观思维。
    • 迭代:有时迭代代码更直观,尤其是在简单的循环结构中。
  • 深度限制

    • 递归:可能会遇到调用栈深度限制,导致栈溢出错误。
    • 迭代:不会遇到栈深度限制问题。
  • 控制流程

    • 递归:控制流程的转移是通过函数调用和返回来实现的。
    • 迭代:控制流程的转移是通过循环条件来控制的。
2.2.3 尾递归

尾递归是一种特殊的递归形式,它在函数的末尾直接返回递归调用的结果,而不进行其他操作。尾递归与普通递归的不同之处在于,尾递归的递归调用是函数执行的最后一个动作。这意味着在递归调用之后,不需要执行任何额外的计算。

求和操作是在“递”的过程中执行的,“归”的过程只需层层返回。

特点:

  • 递归调用是最后一条执行语句:在尾递归中,递归调用是函数体中执行的最后一个操作,没有后续的操作需要执行。

  • 无额外状态:尾递归函数不需要在每次递归调用时保存额外的状态信息,因为递归调用后没有其他操作需要这些信息。

  • 优化可能性:某些编译器或解释器可以优化尾递归,将其转换为迭代,从而避免增加调用栈的深度,减少内存使用。

优点:

  • 节省内存:因为编译器可以优化尾递归,所以它不会像普通递归那样消耗调用栈空间,从而可以处理更大的输入而不会导致栈溢出。

  • 性能:尾递归通常比普通递归更高效,因为它可以避免额外的函数调用开销。

缺点:

  • 编写限制:并不是所有递归算法都可以轻易地转换为尾递归形式。

  • 编译器支持:尾递归优化不是所有编译器或解释器都支持的,如果编译器不支持尾递归优化,那么尾递归和普通递归在性能和内存使用上没有区别。

2.2.4 递归树
public class Fibonacci {

    public static void main(String[] args) {
        int n = 10; // 例如,计算斐波那契数列的第10个数
        int result = fibonacciRecursive(n);
        System.out.println("斐波那契数列的第" + n + "个数是: " + result);
    }

    // 递归方法计算斐波那契数列
    public static int fibonacciRecursive(int n) {
        if (n <= 1) {
            return n;
        }
        return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
    }
}

观察以上代码,我们在函数内递归调用了两个函数,这意味着从一个调用产生了两个调用分支。如图所示,这样不断递归调用下去,最终将产生一棵层数为 𝑛 的递归树(recursion tree)。

2.2.5 两者对比

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

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

相关文章

【python】PyQt5中QAbstractButton基类的特性详细分析与实战应用

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

聚水潭·奇门对接打通金蝶云星空订单查询接口与销售退货新增接口

聚水潭奇门对接打通金蝶云星空订单查询接口与销售退货新增接口 对接源平台:聚水潭奇门 聚水潭SaaSERP于2014年4月上线&#xff0c;目前累计超过2.5万商家注册使用&#xff0c;成为淘宝应用服务市场ERP类目商家数和商家月订单增速最快的ERP。2014年及2015年“双十一”当天&#…

TQSDRPI开发板教程:实现PL端的UDP回环与GPSDO

本教程将完成一个全面的UDP运行流程与GPSDO测试&#xff0c;从下载项目的源代码开始&#xff0c;通过编译过程&#xff0c;最终将项目部署到目标板卡上运行演示。此外&#xff0c;我们还介绍如何修改板卡的IP地址&#xff0c;以便更好地适应您的网络环境或项目需求。 首先从Gi…

【Java】:洗牌功能和杨辉三角的实现

洗牌 此操作包含的基本功能有&#xff1a; 组牌&#xff1a;组建 52 张扑克牌 四种花色&#xff1a;“♥️”&#xff0c;“♠️”&#xff0c;“⬛️”&#xff0c;“♣️”每种花色 13 张牌&#xff1a;1~13 洗牌&#xff1a;将 52 张扑克牌打乱顺序发牌&#xff1a;给三个人…

MybatisPlus设置动态表名

对于一些数据量比较大的表&#xff0c;为了提高查询性能&#xff0c;我们一般将表拆分成多张表&#xff0c;常见的是根据数据量&#xff0c;按年分表或者按月分表&#xff1b;分表虽然太高了查询性能&#xff0c;但是在查询的时候&#xff0c;如何才能查询执行分表数据呢&#…

谷粒商城实战笔记-45-商品服务-API-三级分类-查询-递归树形结构数据获取

文章目录 一&#xff0c;准备工作1&#xff0c;启动虚拟机2&#xff0c;启动mysql3&#xff0c;执行MySQL脚本插入分类数据4&#xff0c;关于三级分类 二&#xff0c;Controller层新增接口三&#xff0c;Service层新增接口1&#xff0c;代码实现2&#xff0c;测试 从这一节开始…

海康威视综合安防管理平台 detection 前台RCE漏洞复现

0x01 产品简介 海康威视综合安防管理平台是一套“集成化”、“智能化”的平台,通过接入视频监控、一卡通、停车场、报警检测等系统的设备。海康威视集成化综合管理软件平台,可以对接入的视频监控点集中管理,实现统一部署、统一配置、统一管理和统一调度。 0x02 漏洞概述 海康…

Stateflow中的状态转换表

状态转换表是表达顺序模态逻辑的另一种方式。不要在Stateflow图表中以图形方式绘制状态和转换&#xff0c;而是使用状态转换表以表格格式表示模态逻辑。 使用状态转换表的好处包括&#xff1a; 易于对类列车状态机进行建模&#xff0c;其中模态逻辑涉及从一个状态到其邻居的转换…

【Axure高保真原型】批量增加标签——中继器版

今天和大家分享批量增加标签——中继器版的原型模板&#xff0c;效果包括&#xff1a; 添加标签&#xff1a;在输入框了输入需要添加的标签信息&#xff0c;点击添加标签按钮或者按键盘回车键可以动态添加该标签 批量添加&#xff1a;可以一次性添加多个标签&#xff0c;在输入…

15现代循环神经网络—GRU与LSTM

目录 1.门控循环单元 GRU关注一个序列门候选隐状态(candidate hidden state)隐状态总结从零开始代码实现代码简洁实现2.长短期记忆网络 LSTM门候选记忆单元(candidate memory cell)记忆单元隐状态代码1.门控循环单元 GRU GRU 是最近几年提出来的,在 LSTM 之后,是一个稍微简…

FastAPI(六十六)实战开发《在线课程学习系统》接口开发--用户注册接口开发

源码见"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 在前面我们分析了接口的设计&#xff0c;那么我们接下来做接口的开发。 首先&#xff0c;我们先设计下pydantic用户参数的校验&#xff1a; """…

2024-07-20 Unity插件 Odin Serializer2 —— 序列化教程

文章目录 1 由根对象决定序列化2 实现 Odin 序列化器2.1 继承已有序列化类2.2 自定义序列化类 3 避免 Unity 无限深度警告4 指定序列化秘钥4.1 External String Reference Resolver4.2 External GUID Reference Resolver4.3 External Index Reference Resolver 4 功能与限制4.1…

物联网在电力行业的应用

作者主页: 知孤云出岫 这里写目录标题 作者主页:物联网在电力行业的应用简介主要应用领域代码案例分析1. 智能电表数据采集和分析2. 设备监控和预测性维护3. 能耗管理和优化4. 电力负载预测5. 分布式能源管理6. 电动汽车充电管理7. 电网安全与故障检测 物联网在电力行业的应用…

vue3-video-play 导入 以及解决报错

npm install vue3-video-play --save # 或者 yarn add vue3-video-play import Vue3VideoPlay from vue3-video-play; import vue3-video-play/dist/style.css; app.use(Vue3VideoPlay) <template><div id"main-container-part"><div class"al…

基于Qt的上位机通用框架

0.前言 最近一年多的时间一直在开发设备控制相关的软件&#xff0c;加上之前在聚光的两年时间&#xff0c;前前后后开发这种设备控制类型的上位机软件也有三年的时间了。总结出了一套基于Qt的上位机编程框架&#xff0c;核心思想类似于C#的依赖注入&#xff0c;对象的初始化都…

【启明智显分享】甲醛检测仪HMI方案:ESP32-S3方案4.3寸触摸串口屏,RS485、WIFI/蓝牙可选

今年&#xff0c;“串串房”一词频繁引发广大网友关注。“串串房”&#xff0c;也被称为“陷阱房”“贩子房”——炒房客以低价收购旧房子或者毛坯房&#xff0c;用极度节省成本的方式对房子进行装修&#xff0c;之后作为精修房高价租售&#xff0c;因甲醛等有害物质含量极高&a…

[Python库](5) rich库

作者制作不易&#xff0c;关注、点赞、收藏一下吧&#xff01; 目录 1.rich库简介 2.下载并导入rich库 2.1.下载 2.2.导入 3.使用 3.1.输出表情包 3.2.文本的样式 3.3.表格 3.4.日志 1.rich库简介 Rich 是一个 Python 库&#xff0c;用于在终端中添加丰富的文本&…

月影护眼大路灯怎么样?书客|月影|霍尼韦尔超硬核实力性能测评pk!

月影护眼大路灯怎么样&#xff1f;选到专业优质的护眼大路灯是真的可以使我们在用眼时减少疲劳感&#xff0c;达到护眼效果&#xff0c;但如果不慎买到劣质的护眼灯产品&#xff0c;不仅达不到健康的环境光&#xff0c;还越用越觉得眼睛疲劳感加重&#xff0c;在水深的护眼灯市…

数学建模(7)——Logistic模型

一、马尔萨斯人口模型 import numpy as np import matplotlib.pyplot as plt# 初始人口 N0 100 # 人口增长率 r 0.02 # 时间段&#xff08;年&#xff09; t np.linspace(0, 200, 200)# 马尔萨斯人口模型 N N0 * np.exp(r * t)# 绘图 plt.plot(t, N, labelPopulation) plt.…

适用于 Mac 或 MacBook 的最佳数据恢复软件

Apple 设计的电脑可靠且用户友好&#xff0c;但即使是最好的最新款 MacBook硬件也会出现故障。当您的存储出现问题时&#xff0c;数据恢复软件可以帮助您恢复丢失和损坏的文件。 数据丢失的另一个原因是有时会发生令人尴尬的错误。如果您不小心丢弃了所需的文件&#xff0c;然…