【算法设计与分析】第一讲 算法基础(上)

(不确定考不考,所以就都学了吧 心里踏实())

重点

1.算法的定义

算法是求解特定问题 的一系列定义良好的步骤,其核心在于解决"做什么"和"怎么做"的设计过程,而不仅仅是得到计算结果。

算法正确性:一个正确的算法必须对每一个输入实例 都能输出正确结果并终止。

算法里的每一步操作,都必须是可以被人(或计算机)直接、明确执行的"原子操作",不能是模糊的、需要依赖额外"智能判断"的复杂步骤。

换句话说:你不能在算法里写一句"想个办法算出答案",必须写清每一步怎么算。

2.算法的性质

算法必须具备五个重要特性:(可根据这几个特性判断一个进程是否是算法)

①输入:0个或多个输入

②输出:1个或多个输出

③确定性:每步运算必须确切定义 ,无二义性。

④能行性:运算必须是基本的 ,可在有限时间内 用纸笔完成。

⑤有穷性:必须在执行有穷步后终止。

3.算法的表示

介绍了三种表示方法及其优劣:

1)自然语言表示:直观但易冗长、歧义,不严谨

2)编程语言表示:精确无歧义,但受语法细节束缚,可能成为理解障碍

3)伪代码表示(推荐):兼顾自然语言的易懂和编程语言的严谨;以SPARKS语言为例,介绍了其基本语法规则(如数据类型、控制结构、函数定义),但强调不必死板套用,应以清晰简洁地表达算法本质为目标。

SPARKS语言基本语法规则

数据类型:四种基本类型

  • 整型
  • 实型
  • 字符型
  • 布尔型

变量定义与C语言类似写法

  • integer x,y
  • float a,b
  • boolean c

SPARKS语言基本语法规则

  • 赋值运算:(变量)<-(表达式)
    x<-y:将y赋值给x
  • 逻辑运算:and or not
  • 关系运算:< ≤ = ≠ ≥ >
  • 数组定义:integer A(1:5,1:20):int A[5][20](这里是一次翻译和对照。在写代码时,你需要处理索引起始点的不同,即伪代码习惯从1开始,C语言从0开始)
    //integer是数据类型,表示这个数组里的每个元素都是整数。
    //A是数组变量的名字
    //1:5:
    表示数组的第一维 (通常可以理解为"行")。
    索引范围从 1 到 5(包含1和5)。
    这意味着第一维有 5 - 1 + 1 = 5个可用的索引位置,分别是 1, 2, 3, 4, 5。
    1:20:
    表示数组的第二维 (通常可以理解为"列")。
    索引范围从 1 到 20(包含1和20)。
    这意味着第二维有 20 - 1 + 1 = 20个可用的索引位置。

    两路分支语句:
    if cond then
    S1
    else
    S2
    endif

多路分支语句:

case

:cond1:S1;

:cond2:S2;

:cond3:S3

:else:S4;

endcase

循环结构:

(1)类似C的while循环的表示:

· while cond do

S

repeat

1.结构解读:

while:循环开始的关键字

cond:一个条件表达式,其值为布尔型(真或假)。

do:关键字,标志着循环条件之后,循环体开始

S:循环体,可以是一条或多条要重复执行的语句

repeat:关键字,标志着循环体的结束,并与while配对,形成一个完整的循环块

复制代码
2.执行流程(先判断,后执行)
1)计算条件cond
2)如果cond为假,则跳过整个循环(不执行S),直接执行repeat之后的语句
3)如果cond为真,则执行循环体S
4)执行完S后,控制流跳转回while处,重新计算条件cond,并重复上述步骤(直到cond为假的时候停)

(2)类似C的do...while循环的表示:

· loop

S

until cond repeat

(3)类似C的for循环的表示:

· for vble←start to finish by increment do

S

repeat

4.算法的分析

1.分析的目标与基本原则

这是分析的指导思想。

1)分析目标:比较不同算法的性能,主要衡量:

时间复杂度:运行时间如何随输入规模n增长。

空间复杂度:内存消耗如何随n增长。

2)核心原则

时间代价归一化:将赋值、比较、算术运算等基本操作的时间代价设为1.这消除了软硬件差异,让我们只关注算法本身的逻辑。

关注最坏情况运行时间:

最好情况下不具普遍性

平均情况分析复杂,难以计算

最坏情况给出了算法运行时间的上界 ,是一个性能保证,更具一般性和实用性。因此,我们默认分析最坏情况。

2.渐进分析------核心的数学工具

当输入规模n很大时,我们并不需要精确的运算次数公式

1)核心思想:当n充分大时:

忽略低阶项(如3n,-4)

忽略最高阶项的常数系数(如2n²里的2)。

只关心运行时间随n增长的**"阶"或"增长率"**

2)三种渐进记号

O(Big-Oh):渐进上界

表示算法运行时间的最坏 情况增长率。

例如,插入排序的最坏情况时间为 O(n²)。这是我们最常用的记号。

Ω(Big-Omega):渐进下界

表示算法运行时间的最佳情况增长率。

Θ(Big-Theta):渐进紧确界

当算法运行时间的最佳和最坏增长率相同时使用(即上下界重合)。

3)算法的时间复杂度分类

多项式时间算法(通常高效):

O(1)< O(log n)< O(n)< O(n log n)< O(n²)< O(n³)

指数时间算法(通常低效,n大时不实用):

O(2ⁿ)< O(n!)< O(nⁿ)

重要结论:PPT中的表格清晰展示,对于大规模问题,降低算法复杂度(如从O(n²)到O(n log n))比单纯提高计算机速度有效得多。

对于大规模问题,任何多项式算法在理论上都优于指数算法。这就是为什么在算法设计中,我们拼命想把指数级问题转化为多项式问题(如动态规划),哪怕增加一点多项式阶数也是巨大的胜利。

3.上界表达式

什么是上界表达式:"上界表达式"描述的是某个函数(通常是算法的运行时间)增长速率的"最高天花板"。它告诉我们,当输入规模n变得非常大时,这个函数的增长率不会超过某个特定的函数。

1.常数C是什么?

大O表示法的核心定义是:若存在正常数C和正整数n0,使得当n≥n0时,|f(n)|≤C*|g(n)|,则称f(n)=O(g(n))。

5.例题+考点

1.如何求函数的上界表达式

第一步:写出T(n)的完整表达式(如果没给,先推导)

例如:

T(n) = 3n² + 5n + 7

T(n) = 2n log n + n² + 100

T(n) = 1000n + 1

T(n) = ½ n³ - 2n² + 4n

2.找"最高阶项"(主导增长的那一项)

->看哪一项随着n增大,"增长得最快"。

常见增长速度排序(从小到大):

常数 < log n < n < n log n < n² < n³ < 2ⁿ < n!

有点忘记怎么求自然对数的导数了,复习一下:

所以:




相关推荐
从负无穷开始的三次元代码生活14 分钟前
算法零碎灵感点分享
算法
染指111019 分钟前
9.LangChain框架(实现RAG)
数据库·人工智能·算法·机器学习·ai·大模型
大数据三康25 分钟前
在spyder进行的遗传算法练习
开发语言·python·算法
Gene_202229 分钟前
轮式底盘的微分平坦
算法
吴佳浩1 小时前
现代多模态大模型的核心基础:Unified Self-Attention
人工智能·算法·llm
小小编程路2 小时前
C++ 常用逻辑运算符
开发语言·c++·算法
Hali_Botebie2 小时前
两种子词分词算法BPE (Byte-Pair Encoding) 和Unigram 区别
人工智能·算法
he___H2 小时前
leetcode100-普通数组
java·数据结构·算法·leetcode
Struggle_97552 小时前
算法知识-堆相关知识
java·开发语言·算法
李伟_Li慢慢2 小时前
从惯性和矩详解惯性矩
人工智能·算法·机器人