1.算法类
1.1.枚举算法[1-3]
就是把所有可能的情况都一一列举出来,然后从中找到符合要求的答案。
比如从 1 到 100 找能被 5 整除的数,就一个一个试,这就是枚举。
1.2.排序算法
冒泡排序[2]
像气泡往上冒一样,每次比较相邻的两个数,如果顺序不对就交换,一趟一趟地把最大(或最小)的数 “浮” 到最后。
选择排序[3]
每次从剩下的数中选一个最小(或最大)的,放到已经排好序的序列后面。
插入排序[3]
就像抓扑克牌理牌一样,每次拿到一张新牌,都把它插入到已经理好的牌中合适的位置。
归并排序[4-5]
就像把一堆混乱的书分成两堆,然后对这两堆书分别进行排序,排好后再把这两堆有序的书合并成一堆,合并的时候要保证合并后的书还是有序的。不断重复这个分堆和合并的过程,最终所有的书就都排好序了。这种方法利用了分治的思想,把大问题分解成小问题来解决。
快速排序[4-5]
先从数组中选一个数作为基准数,然后把数组中比基准数小的数都放到基准数左边,比基准数大的数都放到基准数右边,这样基准数就处在了它最终排序后的正确位置。接着对基准数左边和右边的数组分别重复这个过程,直到整个数组都排好序。快速排序平均情况下效率很高,但在某些特殊情况下可能会表现不佳。
桶排序[4]
假设有一些不同大小的球,要把它们按大小顺序排列。桶排序就是先准备一些不同大小范围的桶,比如小桶放小的球,大桶放大的球,然后把球按照大小分别放到对应的桶里。每个桶里的球相对较少,再对每个桶里的球进行简单排序,最后把各个桶里排好序的球依次取出来,就得到了一个有序的序列。
堆排序[4]
堆是一种特殊的数据结构,可以想象成一个完全二叉树,并且每个节点的值都满足一定的大小关系(大顶堆:父节点的值大于子节点;小顶堆:父节点的值小于子节点)。堆排序就是先把数组构建成一个堆(比如大顶堆),然后每次把堆顶的元素(最大的数)取出来,放到数组末尾,接着调整堆,使得剩下的元素仍然构成一个堆,再取出新的堆顶元素,重复这个过程,直到数组全部排好序。
基数排序[4~5]
以对一组整数进行排序为例,从个位开始,把所有数按照个位数字的大小放到 0 - 9 这 10 个 “桶” 里,然后按照桶的顺序依次把数取出来,再按照十位数字重复这个过程,接着是百位、千位…… 直到所有数的最高位都处理完,这样数组就排好序了。基数排序适合处理位数固定且数据范围不是特别大的情况。
1.3.搜索算法
广度优先搜索(BFS)[1 - 5]
想象你在一个迷宫里,BFS 就像从起点开始,一层一层地向外探索,每一层的所有位置都探索完了,再去探索下一层。就像水波纹一样,一圈一圈地扩散。这种方法可以保证找到的路径是从起点到目标点的最短路径(如果路径长度是按照步数计算的话)。
深度优先搜索(DFS)[1 - 5]
还是在迷宫里,DFS 则是沿着一条路一直走下去,直到走不通了才回退,然后换一条路再继续走,直到找到目标或者把所有可能的路都走完。它会尽可能深入地探索,有点像走迷宫时一条道走到黑的感觉。
剪枝[4 - 6]
在搜索过程中,有时候我们能提前知道某些分支肯定不会得到我们想要的结果,就像在迷宫里,你看到某条路前面是死胡同,就没必要再走下去了。这种提前排除掉不可能的情况,减少不必要搜索的操作就叫剪枝。通过剪枝可以大大提高搜索效率。
双向 BFS[5 - 6]
普通 BFS 是从起点开始向目标点搜索,双向 BFS 则是从起点和目标点同时开始搜索,就像两个人分别从迷宫的入口和出口同时出发,这样相遇的速度会更快,从而减少搜索的时间和空间复杂度。但双向 BFS 实现起来相对复杂一些,需要同时维护两个搜索队列。
记忆化搜索[5]
在搜索过程中,有些状态可能会被重复计算,比如在计算一个复杂的数学问题时,可能会多次遇到相同的子问题。记忆化搜索就是把已经计算过的状态及其结果记录下来,下次再遇到相同的状态时,直接从记录中取结果,而不需要重新计算,这样可以避免重复计算,提高效率。
迭代加深搜索[5 - 6]
迭代加深搜索结合了 DFS 和 BFS 的优点。它先设定一个搜索深度限制,在这个深度内进行 DFS 搜索,如果没有找到目标,就增加深度限制,重新进行 DFS 搜索。这样既像 DFS 一样简单直接,又能像 BFS 一样保证在有限深度内找到最优解(如果存在的话),适用于不知道解的深度范围,但又希望尽快找到较优解的情况。
启发式搜索[7]
在搜索过程中,根据一些启发信息来选择下一步搜索的方向,而不是盲目地进行搜索。比如在迷宫中,你可以根据目标点大致的方向信息,优先选择朝着目标方向的路径进行探索,这样可以更快地找到目标。启发式搜索通过利用启发函数来评估每个状态到目标状态的 “距离” 或 “优