一.题目需求
有一个充满水的8品脱的水壶和两个空水壶(容积分别是5品脱和3品脱)。
通过将水壶完全倒满水和将水壶的水完全倒空这两种方式,在其中的一个水壶中得到4品脱的水。
二、算法思想
1.算法分析
1.1. 采用的算法思想是将某个时刻水壶中水的数量看作一个状态,用一个长度为3的数组表示。
1.2. 初始状态便为[8,0,0],再拓展他的下一结点的可能结构。
1.3. 若下一结点的结构已经被拓展过了便放弃,若没有拓展过则加入拓展列表(new_list)中。然后递归上述操作。
1.4. 直到拓展列表(new_list)为空或者找到目标为止。
2.思想图解
这里的第一个数就代表着是那个8品脱的瓶子,依次分别是8品脱,5品脱,3品脱。
就如图一样,使用广度优先遍历(类似于层次遍历)一次一次递归扩展新的结点,知道找到4品脱的水或者无结点可扩展为止。
三、代码展示
1.创建树节点结构
节点包括两个属性,一个属性是数组类型的,存储当前三个水壶的容量状态,另一个属性是记录它是由哪个结点扩展过来的,以便找到解决路径:
2.实现倒水动作
由于这里只有三个壶,互相倾倒的方案可以枚举出来,所有我就没使用二重嵌套循环,而是使用一层循环:
这个算法的时间复杂度是O(n^2)。
时间复杂度分析:
2.1. 外层循环有6次,每次循环中都会进行一次内层循环,内层循环最多有6次。所以总共会进行36次循环。
2.2. 在内层循环中,有一个判断语句,用于检查当前的n_list状态是否已经被考虑过。这个判断语句的时间复杂度是O(n),因为它需要遍历old_list列表。
2.3. 因此,总的时间复杂度是O(6 * 36 * n) = O(n^2)。
3.广度优先遍历
主要算法:使用广度优先遍历算法(层次遍历算法)一次一次递归扩展新的结点,知道找到4品脱的水或者无结点可扩展为止:
这个算法是广度优先遍历(BFS)的实现。它从一个根节点开始,然后访问所有相邻的节点,然后再访问这些节点的相邻节点,以此类推。
这个过程会一直持续到没有更多的节点可以访问为止。
时间复杂度分析:
1. 初始化两个列表 old_list 和 new_list,它们的大小取决于树的宽度。在最坏的情况下,树可能是一个线性结构,即每个节点只有一个子节点。在这种情况下,new_list 的大小将等于树的宽度,即 O(n),其中 n 是树的节点数。
2. while 循环会执行直到 new_list 为空。在每次迭代中,它会从 new_list 中弹出一个节点,并将其添加到 old_list 中。这个过程的时间复杂度是 O(1)。由于 while 循环会执行 n 次,所以总的时间复杂度是 O(n)。
3. 在每次迭代中,还会调用 pour 函数来处理当前节点的状态。pour 倒水函数的时间复杂度是 O(n^2),那么总的时间复杂度将是 O(n)*O(n^2)。
综上所述,这个算法的时间复杂度是 O(n^3)。
4.实现主函数
5.运行结果
从运行结果可以看出,遍历到第7步即可得到含有4品脱的水壶。
==========结束==========