数据结构与算法

1. 逻辑结构 & 存储结构

逻辑结构:

集合结构:数据元素之间的关系是属于同一个集合。关系松散。

线性结构:数据元素之间存在一对一关系。

树形结构:数据元素之间存在一对多关系。

图形结构:元素之间存在着多对多关系。

存储结构:

顺序存储:逻辑上相邻的元素存储在物理位置相邻的存储单元中。

链式:额外存储元素之间的关系,不要求物理相邻。

散列存储:Hash。

2. 时间复杂度

O(1) -> O(log2n) -> O(n) -> O(nlog2n) -> O(n2) -> O(n3) -> O(2n)

计算一个递归的复杂度:反向替代法得到执行次数的地推关系和初始条件,形成类似M(n) = M(n-i)+i 的公式,再把 i 替换为 n 得到复杂度 

3. 分治和递归

分治(Divide and Conquer)算法是一种解决问题的方法论,而递归(Recursion)是一种编程技巧或方法。它们之间有关联,但也有明显的区别:

分治算法:

  1. 定义:分治算法是一种算法设计范式,它通过将问题分解为更小的子问题来解决,然后递归地解决这些子问题,最后将子问题的解合并以形成原问题的解。

  2. 步骤:通常包括三个步骤:分解(Divide)、解决(Conquer)、合并(Combine)。

  3. 应用:分治算法常用于可以自然分解为相似子问题的问题,如排序算法(快速排序、归并排序)、二分搜索、矩阵乘法等。

递归算法:

  1. 定义:递归是一种编程技巧,其中一个函数直接或间接地调用自身。

  2. 基本形式:递归通常包括递归基本情况(base case)和递归步骤(recursive case)。

  3. 应用:递归可用于实现分治算法,也可用于实现其他需要回溯或重复调用相同逻辑的算法,如树和图的遍历、阶乘计算、斐波那契数列等。

区别:

  1. 概念层面:分治是一种解决问题的策略,而递归是一种实现算法的技术。

  2. 实现方式:分治算法不一定需要递归来实现,也可以通过迭代的方式(例如,使用循环)来实现;递归算法也不一定是分治算法。

  3. 重点:分治算法的重点在于问题的分解和子问题的解的合并;递归的重点在于函数自我调用的逻辑和终止条件。

  4. 效率问题:递归实现可能导致不必要的重复计算和高空间复杂度(由于调用栈),而迭代通常更高效,但可能难以表达某些问题。

联系:

  • 分治算法经常使用递归来实现,因为递归提供了一种自然的方式来分解问题和合并结果。

  • 递归可以视为分治策略的一种编程实现。

4. 动态规划

动态规划(Dynamic Programming,简称DP)算法是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

动态规划算法的特点:

  1. 最优子结构:动态规划算法依赖于问题具有最优子结构这一特点,即问题的最优解包含其子问题的最优解。

  2. 重叠子问题:动态规划算法通常用于解决那些具有重叠子问题的问题,即在递归算法中重复计算多次的子问题。

  3. 记忆化:动态规划通过存储子问题的解(通常是在表或数组中),避免重复计算,从而提高效率。这个过程称为“记忆化”。

  4. 自底向上:动态规划通常采用自底向上的方法,即先解决所有子问题,然后逐步构建原问题的解。

  5. 迭代与填表:动态规划算法通常使用迭代而非递归,通过填充一个表格(通常是一维或多维数组)来解决问题。

动态规划与分治算法的区别:

  1. 适用问题:分治算法适用于可以分解为独立子问题的问题,而动态规划适用于具有重叠子问题和最优子结构的问题。

  2. 存储子问题解:分治算法通常不需要存储所有子问题的解,而动态规划算法需要存储之前计算的子问题解以避免重复计算。

  3. 方法:分治算法可以递归实现,也可以迭代实现;动态规划通常迭代实现,通过填表方法逐步构建解。

  4. 重复工作:分治算法中,子问题通常不会重复出现;而动态规划算法中,子问题可能会被多次计算,因此需要记忆化来优化。

  5. 方向性:分治算法可以是递归的,从上到下进行;动态规划通常是自底向上,从最基本的子问题开始解决。

动态规划与递归的区别:

  1. 记忆化:递归可能不包含记忆化机制,而动态规划算法通过记忆化减少重复计算。

  2. 迭代 vs 递归:递归是一种调用自身的方法,而动态规划通常使用迭代方法,通过循环和数组来解决问题。

  3. 问题类型:递归可以用于实现分治算法,也可以用于实现动态规划算法,但动态规划算法通常不使用递归,而是使用迭代来避免栈溢出和重复计算。

 5. 回溯算法

回溯算法和递归是两种在编程中常用的技术,尤其是在解决复杂问题时。它们有一些相似之处,但也存在一些关键的区别:

相似之处

  1. 重复调用:两者都涉及到函数或方法的重复调用。

  2. 树形结构:很多问题可以通过树形结构来表示,递归和回溯算法都可以用来遍历这种结构。

  3. 基础和递归案例:在递归和回溯算法中,通常都有基础案例(base case)和递归案例(recursive case)。

区别

  1. 目的

    • 递归:递归的主要目的是通过将问题分解为更小的子问题来解决问题。递归函数通常有一个或多个基础案例,当达到这些案例时,递归会停止。

    • 回溯算法:回溯算法的主要目的是通过试错来找到问题的解决方案。它不仅需要找到解决方案,还需要在找到解决方案的过程中回溯,撤销之前的操作。

  2. 逻辑结构

    • 递归:递归逻辑通常是自上而下的,从问题的初始状态开始,逐步分解问题。

    • 回溯算法:回溯算法逻辑是自上而下的,但在找到解决方案的过程中,如果发现当前路径不可行,会回溯到上一步,尝试其他可能的路径。

  3. 存储空间

    • 递归:递归通常使用系统堆栈来存储中间状态,可能导致堆栈溢出。

    • 回溯算法:回溯算法通常使用显式的栈或数组来存储路径,可以更灵活地控制存储空间。

  4. 应用场景

    • 递归:适用于可以自然分解为子问题的问题,如树的遍历、图的搜索、阶乘计算等。

    • 回溯算法:适用于需要探索所有可能解决方案的问题,如八皇后问题、数独解、迷宫求解等。

  5. 效率

    • 递归:可能会重复计算相同的子问题,效率可能较低。

    • 回溯算法:通过剪枝(剪去不可行的路径)来提高效率,避免重复计算。

                                                 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值