【集合专题】—— 深入理解汉诺塔的递归算法

一、对于集合的基础认识

1.List 是一个集合的接口。允许存在重复的元素,主要有两种实现类。
ArrayList 与 LinkedList
2.一些常用的方法:

List<Integer> list = new ArrayList<>;
//向集合中添加元素
list.add(element);
//获取元素
list.get(index);
//获取集合的长度
list.size();
//删除集合的元素
list.remove(index);
//清空集合中的元素
list.clear();
//判断集合是否为空
list.isEmpty();
二、LeetCode 面试题 08.06. 汉诺塔问题

【集合专题】—— 深入理解汉诺塔的递归算法_第1张图片
核心思想:
(1)汉诺塔问题是一个经典的递归问题,属于分治算法的一种。

(2)将n个盘子从某个柱子上移动到指定的柱子上,将其变为将n-1个盘子移动到辅助的柱子上,把最后一个盘子直接移动到目标柱上。

(3)此时问题的规模就缩小到了这 n-1 个盘子移动到目标数上。

(4)问题的规模为: H(n) = H(n - 1) + 1 + H(n - 1)

代码部分:

class Solution {
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        //获取源柱上盘子的个数[对于获取集合中元素的个数通过size方法来完成]
        int n = A.size();

        //调用移动盘子的方法
        move(n, A, B, C);
    }

    public void move(int n, List<Integer> A, List<Integer> B, List<Integer> C){
        if(n == 0){
            return;
        }
        //将n-1个盘子移动到辅助柱上
        move(n-1, A, C, B);
        C.add(0, A.remove(0));
		//再将n-1个盘子移动到目标柱上
        move(n-1, B, A, C);
    }
}

对于代码的执行流程与内存机制分析:

(1)对于递归调用一次,就会生成一个方法栈。

(2)当递归结束后,会返回并销毁方法栈。在返回时会执行整个方法。

(3)具体的执行流程:

假设有3个盘子,有A、B、C三个柱子

(1)在第一次调用move()方法时,对其中两个盘子进行递归处理
move(2, a, c, b)
第二次调用move()方法时,再对一个盘子进行处理
move(1, a, b, c)
第三次调用move()方法时,再次进入递归调用
move(0, a, c, b)
此时 n == 0, 递归调用结束。

(2)函数返回,继续执行下面的代码

n = 1时,此时会执行 C.add(0, A.remove(0));
A = a, B = b, C = c 此时执行该代码会让A盘最上面的盘子放到目标柱C上
继续执行下面对剩余n - 1个在原来辅助柱上的盘子移动到目标柱上
move(0, b, a, c) 执行到上面的递归调用,因为n = 0时什么都不会返回,在接下来也不对其考虑了。

函数继续返回,返回 n = 2时,此时会执行 C.add(0, A.remove(0));
A = a, B = c, C = b,此时执行该代码会让A盘最上面的盘子放到目标柱B上
继续执行下面的递归调用,move(1, c, a, b),进入move方法中还会递归调用一次n= 0,所以不展开讨论,继续向下执行,此时会执行 C.add(0, A.remove(0));,将C柱最上边的盘子移动到B柱上,然后执行下面的递归调用,此时传入的参数也为0了,所以不返回任何信息

递归继续返回,返回到move(3, a, b, c),此时会执行 C.add(0, A.remove(0));, A = a、B = b、C = c,所以就将A柱最上边的盘子移动到C柱上。
执行下面的递归调用remove(2, b, a, c),进入上边的递归调用remove(1, b, c, a) 再次执行调用传入的参数为0了,所以从参数为1开始返回,此时会执行 C.add(0, A.remove(0));,代表将B柱最上边的移动到A柱上,执行下边的递归调用时参数为0了,所以继续返回。
此时参数为2,执行此时会执行 C.add(0, A.remove(0));,代表将B柱最上边的盘子移动到C柱上,执行下边的的递归调用remove(1, a, b, c),此时执行上边的递归调用,参数为零不考虑,之后会执行 C.add(0, A.remove(0));,代表将A柱上边的盘子移动到C柱上。

此时整个递归程序就执行并返回完毕啦

你可能感兴趣的:(算法,java,leetcode,算法)