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

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

重点

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!

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

所以:




相关推荐
阿Y加油吧1 小时前
二刷 LeetCode:62. 不同路径 & 64. 最小路径和 复盘笔记
笔记·算法·leetcode
生成论实验室1 小时前
《源·觉·知·行·事·物:生成论视域下的统一认知语法》导论:在破碎的世界寻找统一语法
人工智能·科技·算法·架构·创业创新
承渊政道1 小时前
【动态规划算法】(两个数组的DP问题深度剖析与求解方法)
数据结构·c++·学习·算法·leetcode·动态规划·哈希算法
杨连江2 小时前
原子级平面限域协同晶核诱导定向生长单层鳞片石墨的研究
算法
MATLAB代码顾问2 小时前
混合粒子群-模拟退火算法(HPSO-SA)求解作业车间调度问题——附MATLAB代码
算法·matlab·模拟退火算法
Felven2 小时前
C. Prefix Min and Suffix Max
算法
加农炮手Jinx2 小时前
LeetCode 26. Remove Duplicates from Sorted Array 题解
算法·leetcode·力扣
加农炮手Jinx2 小时前
LeetCode 88. Merge Sorted Array 题解
算法·leetcode·力扣
格林威2 小时前
线阵工业相机:如何计算线阵相机的行频(Line Rate)?公式+实例
开发语言·人工智能·数码相机·算法·计算机视觉·工业相机·线阵相机