01 常见算法

  • 算法需要符合的条件
  1. input
  2. output
  3. definiteness 明确性
  4. effectiveness 有效性
  5. finiteness 有限性
  • 分治法 - Divide and Conquer
    把大规模问题 依照相同的概念 分解成多个小规模子问题,各个击破,最后在将各子问题的解合并得到原问题的解。
    快速排序、递归算法(recursion)、大整数乘法

  • 递归法 - Recursion
    一个可以反复执行的递归过程
    一个可以离开递归执行过程的出口

    • 尾归递归 - Tail Recursion
      函数或子程序的最后一条语句为递归调用,因为每次调用后,再回到前一次调用的第一条语句,就是 return 语句,所以不需要再进行任何运算工作。
    • 堆栈 - Stack
      一组相同数据类型的集合,所有的操作均在这个结构的顶端进行,LIFO。
    # 阶乘
    def factorial(i):
        if i == 0:
            return 1
        else:
            ans = i * factorial(i - 1)
        return ans
  • 贪心法 - Greed Method
    采取在当前状态下最有利或最优化的选择,不断地改进该解答,持续在每一步骤中选择最佳地方法,并且逐步逼近给定地目标,当达到某一步骤不能再继续前进时,算法就停止。
    虽然是把求解的问题分成若干个子问题,但是,并不能保证最后解是最佳的
    常用于 找出图的最小生成树MST、最短路径、哈夫曼编码等。

  • 动态规划法 - Dynamic Programming Algorithm
    如果一个问题的答案与子问题相关的话,就可能将大问题拆解成各个小问题。
    与分治法最大的不同点是:可以让每一个子问题的答案被存储起来,一共下次求解时直接取用。故而可解决重复计算的问题。

     def Fibonacci(n):
         result = output[n]
         
         if result == None:
             return 0
         elif n == 1:
             return 1
         else:
             return Fibonacci(n - 1) + Fibonacci(n - 2)
         output[n] = result
         return result
    
  • 迭代法 - Iterative Method
    无法使用公式一次求解,而需要使用迭代。
    变量初始值、循环条件判别式、调整变量增减值

      # 阶乘
      sum = 1
      n = 6
      for j in range(n, 0, -1):
          sum *= j
      print("%d!=%3d" % (n, sum))
      sum = 1
    
  • 枚举法
    列举所有的可能。

  • 回溯法 - Backtracking
    枚举法的一种。对某些问题而言,回溯法是可以找出所有(或一部分)解的一般性算法,同时避免枚举不正确的值。一旦发现不正确的值,就不再递归到下一层,而是回溯到上一层,以节省时间。是一种走不通就退回再走的方式。

    • 老鼠走迷宫

      (1) 一次只能走一格

      (2) 遇到墙无法再走时,则退回一步找找看是否有其他的路可以走

      (3) 走过的路不再走第二次
    • 如何在计算机中模拟迷宫?
      二维数组MAZE[ i ][ j ] = 1 表示有墙,无法通过; 0 表示无墙,可以通过。
      MAZE[ 1 ][ 1 ]是入口,MAZE[ m ][ n ] 是出口。
      可以使用链表来记录走过的位置,并将走过的位置对应数组元素内容标记为 2,然后将这个位置放入堆栈再进行下一次选择。如果进入死胡同并且没有达到终点,就退出上一个位置,并退回到上一个岔路口选择其他的路。堆栈顶端的指针所指的方格编号便是老鼠当前所在的位置。
      if 上一格可走:
          把方格编号加入到堆栈
          往上走
          判断是否为出口
      elif 下一个可走:
          把方格编号加入到堆栈
          往下走
          判断是否为出口
      elif 左一格可走:
          把方格编号加入到堆栈
          往左走
          判断是否为出口
      elif 右一格可走:
          把放个编号加入到堆栈
          往右走
          判断是否为出口
      else:
          从堆栈删除一个方格编号
          从堆栈中弹出一个方格编号
          往回走
    
原文地址:https://www.cnblogs.com/catyuang/p/11506117.html