hello算法,简单讲(1)

文章目录

  • 第一章,简单介绍
  • 递归、迭代以及复杂度分析
    • [1️⃣ 递归与迭代的概念](#1️⃣ 递归与迭代的概念)
    • [2️⃣ 时间复杂度与空间复杂度](#2️⃣ 时间复杂度与空间复杂度)
    • [3️⃣ Python 示例](#3️⃣ Python 示例)
      • [(A) 递归阶乘](#(A) 递归阶乘)
      • [(B) 迭代阶乘](#(B) 迭代阶乘)
    • [4️⃣ 初学者理解小技巧](#4️⃣ 初学者理解小技巧)
    • [5️⃣ 总结](#5️⃣ 总结)
  • 练习题以及答案
    • [**Day 1:算法与数据结构练习**](#Day 1:算法与数据结构练习)
      • [练习题 1️⃣:插入排序(扑克整理)](#练习题 1️⃣:插入排序(扑克整理))
      • [练习题 2️⃣:贪婪找零](#练习题 2️⃣:贪婪找零)
    • [**Day 2:递归与迭代练习**](#Day 2:递归与迭代练习)
      • [练习题 3️⃣:递归阶乘](#练习题 3️⃣:递归阶乘)
      • [练习题 4️⃣:迭代阶乘](#练习题 4️⃣:迭代阶乘)

第一章,简单介绍


1️⃣ 什么是算法?

算法就是一套明确的步骤,用来解决问题,特点:

  • 输入输出明确:明确知道算法处理什么输入,输出什么结果。
  • 步骤可行且有限:每一步操作可以执行,并且算法总会在有限步骤内完成。
  • 相同输入总是得到相同输出:保证结果可预测。

生活中的例子

  1. 查字典(二分搜索算法)

    • 想查拼音首字母为 R 的字
    • 翻到中间,判断字母是前还是后
    • 逐步缩小查找范围,直到找到
      → 数据结构是已排序的数组,算法是二分搜索。
  2. 整理扑克牌(插入排序算法)

    • 把手牌分为有序和无序部分
    • 每次从无序部分抽一张牌,插入到有序部分正确位置
    • 重复,直到牌全部有序
  3. 找零问题(贪婪算法)

    • 买东西找钱,每次选当前能用的最大面额,直到凑够总额
    • 每一步都选"当前最优方案"

2️⃣ 数据结构与算法的关系

  • 数据结构:组织和存储数据的方法(数组、链表、树、哈希表等)
  • 算法:操作这些数据结构的步骤

关系:

  • 数据结构是算法的基础
  • 算法为数据结构赋能
  • 选择合适的数据结构能显著提高效率

类比积木

  • 积木块 → 数据
  • 积木的形状和连接方式 → 数据结构
  • 拼装步骤 → 算法
  • 最终积木模型 → 输出结果

3️⃣ Python 示例

插入排序(整理扑克牌)

python 复制代码
def insertion_sort(arr):
    """
    插入排序算法:将列表从小到大排序
    思路:
    1. 从第二个元素开始,取当前元素 key
    2. 将 key 插入到左边已排序部分的正确位置
    3. 重复直到整个列表有序
    """
    for i in range(1, len(arr)):
        key = arr[i]        # 当前要插入的元素
        j = i - 1
        # 向左扫描已排序部分,如果大于 key,则右移
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]  # 数据右移
            j -= 1
        arr[j + 1] = key    # 插入 key
    return arr

# 测试
cards = [5, 3, 6, 2, 4]
print(insertion_sort(cards))  # 输出:[2, 3, 4, 5, 6]

贪婪找零算法

python 复制代码
def greedy_change(amount, coins):
    """
    贪婪找零算法
    参数:
    - amount: 需要找的总金额
    - coins: 可用的硬币面额列表
    返回:
    - 一个列表,表示找零方案
    思路:
    1. 将硬币从大到小排序
    2. 每次使用当前最大面额的硬币,直到凑够总额
    """
    coins.sort(reverse=True)  # 从大到小排序
    result = []
    for coin in coins:
        while amount >= coin:
            amount -= coin
            result.append(coin)
    return result

# 测试
coins = [20, 10, 5, 1]
amount = 31
print(greedy_change(amount, coins))  # 输出:[20, 10, 1]

4️⃣ 学习建议

  1. 理解概念:先理解算法逻辑,再看代码实现。
  2. 动手实践:敲代码、调试输出,观察算法如何改变数据。
  3. 联系生活:把查字典、整理扑克牌、找零问题想成生活小任务。

递归、迭代以及复杂度分析


1️⃣ 递归与迭代的概念

迭代(Iteration)

迭代是通过重复执行一段代码来完成任务,通常用 forwhile 循环实现。每一步都是显式的"循环操作",非常直观。

递归(Recursion)

递归是函数自己调用自己来完成任务。递归通常有两个部分:

  1. 终止条件(Base case):当问题规模最小或满足条件时,不再递归。
  2. 递归步骤(Recursive step):将问题拆解为更小的子问题,并通过函数自身求解。

💡 核心区别:迭代用循环显式推进,递归通过函数调用隐式推进。


2️⃣ 时间复杂度与空间复杂度

  • 时间复杂度:算法执行所需时间的增长量。比如阶乘函数对 n 的计算量:

    • 迭代:O(n)
    • 递归:O(n)
  • 空间复杂度:算法执行所需额外空间:

    • 迭代:O(1)(常量空间)
    • 递归:O(n)(递归调用会占用栈空间)

所以递归虽然逻辑简洁,但可能占用更多内存,需要注意"栈溢出"问题。


3️⃣ Python 示例

(A) 递归阶乘

python 复制代码
def factorial_recursive(n):
    """
    递归实现阶乘
    阶乘 n! = n * (n-1)!, 0! = 1
    """
    if n == 0 or n == 1:  # 终止条件
        return 1
    return n * factorial_recursive(n - 1)  # 递归调用

# 测试
print(factorial_recursive(5))  # 输出: 120

(B) 迭代阶乘

python 复制代码
def factorial_iterative(n):
    """
    迭代实现阶乘
    通过循环累乘
    """
    result = 1
    for i in range(2, n + 1):
        result *= i  # 累乘
    return result

# 测试
print(factorial_iterative(5))  # 输出: 120

4️⃣ 初学者理解小技巧

  1. 手动演算

    • factorial_recursive(4),手动画出函数调用栈:

      复制代码
      factorial_recursive(4)
        -> 4 * factorial_recursive(3)
             -> 3 * factorial_recursive(2)
                  -> 2 * factorial_recursive(1)
                       -> 1

      然后从栈底向上计算:1 → 2 → 6 → 24

  2. 对比迭代

    • 用循环累乘:2 → 6 → 24,过程更直观,但没有"函数栈"的概念。
  3. 复杂度分析

    • 两者时间复杂度相同 O(n)
    • 递归额外消耗栈空间 O(n),迭代只需要一个变量 O(1)

5️⃣ 总结

  • 递归适合逻辑清晰、可分解为相似子问题的场景(如树遍历、分治问题)。
  • 迭代适合对空间敏感或者操作简单的线性任务。
  • 复杂度分析帮助你理解算法在大规模输入下的性能表现,是算法设计的基础。

练习题以及答案


Day 1:算法与数据结构练习

练习题 1️⃣:插入排序(扑克整理)

题目 :给定列表 [7, 2, 5, 3, 4],用插入排序将它从小到大排序,并画出每一步元素移动的变化过程。

参考代码

python 复制代码
def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]  # 元素右移
            j -= 1
        arr[j + 1] = key
    return arr

cards = [7, 2, 5, 3, 4]
print(insertion_sort(cards))  # 输出: [2, 3, 4, 5, 7]

讲解

  1. 从第二个元素 2 开始,向左扫描 [7],发现 7>2,右移 7,插入 2[2,7,5,3,4]
  2. 5,扫描 [2,7],右移 7,插入 5[2,5,7,3,4]
  3. 3,扫描 [2,5,7],右移 7,5,插入 3[2,3,5,7,4]
  4. 4,扫描 [2,3,5,7],右移 7,5,插入 4[2,3,4,5,7]

每一步都是把"未排序的元素"插入到"已排序部分"的正确位置。


练习题 2️⃣:贪婪找零

题目 :超市买东西找零,硬币面额 [10,5,2,1],总金额 18,每次选择最大可用面额的硬币,计算找零方案。

参考代码

python 复制代码
def greedy_change(amount, coins):
    coins.sort(reverse=True)
    result = []
    for coin in coins:
        while amount >= coin:
            amount -= coin
            result.append(coin)
    return result

coins = [10, 5, 2, 1]
amount = 18
print(greedy_change(amount, coins))  # 输出: [10,5,2,1]

讲解

  • 贪婪策略:每一步都选择当前能用的最大面额。

  • 步骤:

    1. 10 → 剩余 8
    2. 5 → 剩余 3
    3. 2 → 剩余 1
    4. 1 → 剩余 0
  • 优点:逻辑简单,效率高。缺点:在某些面额组合下可能不是最优(此例最优)。


Day 2:递归与迭代练习

练习题 3️⃣:递归阶乘

题目 :实现函数 factorial_recursive(n),用递归计算阶乘 n!,测试 n=5

参考代码

python 复制代码
def factorial_recursive(n):
    if n == 0 or n == 1:  # 终止条件
        return 1
    return n * factorial_recursive(n - 1)

print(factorial_recursive(5))  # 输出: 120

讲解

  • 核心思路:n! = n * (n-1)!

  • 调用栈展开过程:

    复制代码
    factorial_recursive(5)
      -> 5 * factorial_recursive(4)
          -> 4 * factorial_recursive(3)
              -> 3 * factorial_recursive(2)
                  -> 2 * factorial_recursive(1)
                      -> 1
  • 从栈底开始返回计算结果:1 → 2 → 6 → 24 → 120


练习题 4️⃣:迭代阶乘

题目 :实现函数 factorial_iterative(n),用循环计算阶乘,测试 n=5

参考代码

python 复制代码
def factorial_iterative(n):
    result = 1
    for i in range(2, n+1):
        result *= i
    return result

print(factorial_iterative(5))  # 输出: 120

讲解

  • 通过循环依次累乘 2*3*4*5,直观且节省递归栈空间。
  • 时间复杂度与递归相同 O(n),但空间复杂度更低 O(1)。

💡 学习提示

  • 对插入排序和贪婪找零,可以画出每一步元素移动或找零选择过程,更直观理解算法逻辑。
  • 对递归阶乘,建议手动画调用栈,理解"从终止条件返回结果"的顺序。
  • 可尝试对比迭代与递归,观察时间和空间消耗差异,加深复杂度分析理解。
相关推荐
智者知已应修善业23 分钟前
【51单片机8位数码管同时倒计时从9999】2024-1-25
c++·经验分享·笔记·算法·51单片机
洛水水26 分钟前
【力扣100题】86.柱状图中最大的矩形
算法·leetcode·职场和发展
渡之33 分钟前
GRiM-Net 深度解析 | 无人机 GNSS 拒止场景下两阶段跨视角视觉定位框架
深度学习·算法·动态规划·无人机
测试仪器廖生135902563851 小时前
罗德与施瓦茨 FSP13频谱分析仪FSP30
网络·人工智能·算法
happymaker06261 小时前
LeetCodeHot100——560.和为K的子数组
算法
dtq04241 小时前
C语言刷题数组5,6(求平均值,求最大值)
c语言·数据结构·算法
郭梧悠1 小时前
Hash算法入门Hash冲突解决方案
算法·哈希算法
洛水水2 小时前
【力扣100题】81.寻找两个正序数组的中位数
数据结构·算法·leetcode
happymaker06263 小时前
LeetCodeHot100——155.最小栈
算法
洛水水3 小时前
【力扣100题】85.每日温度
算法·leetcode·职场和发展