hello algorithm chapter 2 / Iteration and recursion
Q: what is complexity?
A: 函数的操作数量与输入数据大小的数学关系。 例如,单循环函数的操作数量和输入操作数成正比,或者说成“线性关系”,单循环函数的复杂度就是 \(O(1)\)。
迭代与递归 代表了两种完全不同的思考和解决问题的范式。
- 迭代:“自下而上”地解决问题。从最基础的步骤开始,然后不断重复或累加这些步骤,直到任务完成。
- 递归:“自上而下”地解决问题。将原问题分解为更小的子问题,这些子问题和原问题具有相同的形式。接下来将子问题继续分解为更小的子问题,直到基本情况时停止(基本情况的解是已知的)。
features of recursion
- invoke stack
递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。这将导致两方面的结果。
- 函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归通常比迭代更加耗费内存空间。
- 递归调用函数会产生额外的开销。因此递归通常比循环的时间效率更低。
- tail recursion
- 普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下文。
- 尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无需继续执行其他操作,因此系统无需保存上一层函数的上下文。
normal recursion
we put operation in parameter table in tail recursion
1 |
|
tail recursion
1 |
|
Notes: 许多编译器或解释器并不支持尾递归优化。例如,Python 默认不支持尾递归优化,因此即使函数是尾递归形式,但仍然可能会遇到栈溢出问题。
Iteration | Recursion | |
---|---|---|
Implemention | 循环结构 | 函数调用自身 |
Time efficient | 效率通常较高,无函数调用开销 | 每次函数调用都会产生开销 |
Memory usage | 通常使用固定大小的内存空间 | 累积函数调用可能使用大量的栈帧空间 |
Applicable issue | 适用于简单循环任务,代码直观、可读性好 | 适用于子问题分解,如树、图、分治、回溯等,代码结构简洁、清晰 |
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!