一、参数传递
总结一下: 在java语言中,不管参数的类型,是数组类型,基本数据类型,实际参数和形式参数进行值传递的方式只有一种: 实际参数的值 复制一份 赋值给形式参数 参数类型是基本数据类型 值传递 参数类型是引用数据类型(比如数组) 引用传递 所以,实参的值,其实就有两份,调用方法中一份(实际参数),被调用方法中一份(形式参数) 1. 当方法的参数是基本数据类型的参数的时候, 参数有两份,同时参数对应的数据的值,也有两份 2. 当方法的参数是引用数据类型的时候 参数值有两份,但是两个数组类型引用变量,对应的值(数组),只有一个
二、递归(汉诺塔问题)
package com.cskaoyan.recursion;
/*
1.有三根杆子A,B,C。A杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:
a.每次只能移动一个圆盘;
b.大盘不能叠在小盘上面。
在汉诺塔问题中N 64 亿年
提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则。
问:最少要移动多少次?如何移?
递归算法的核心思想:
在解决大规模问题的时候,可能因为问题的规模太大,无法直接解决这个问题,转而将大规模的问题,分解为一系列
小规模的子问题,当规模小到一定程度的时候,我们可以直接解决小规模的子问题,我们只要解决这一系列小规模的子问题,
就相当于解决了大规模的问题
分而治之
解决思路以N个圆盘为例:
1. 当我们要解决N个圆盘的搬运问题,对于N个圆盘,我们可能无法一次性得到结果,
于是,我们把N个圆盘的搬运问题, -> 最大一个的圆盘的搬运 & 最大圆盘上面的 n - 1
2. 对于规模为1那个待搬运的最大的圆盘,直接就知道如何搬运(一步搞定)
3. 在2的基础上,只需要,再解决 N - 1个圆盘搬运的问题
三个盘:
A--->C
A--->B
C--->B
A--->C
B--->A
B--->C
A--->C
f(n)表示n个圆盘搬运的总次数
f(n) = f(n - 1) + 1 + f(n - 2)
= 2 * f(n - 1) + 1
f(n) + 1 = 2 * f(n - 1) + 2 = 2 * (f(n-1) + 1)
f(1) + 1 = 2
f(n) + 1 = 2^n
f(n) = 2^n - 1
*/
public class Demo2Hanoi {
public static void main(String[] args) {
int n = 4;
hanoi(n, 'A', 'B', 'C');
// 计算hanoi搬运的次数
long count = countHanoi(n);
System.out.println(count);
}
/*
参数n: 表示带搬运的圆盘数量
返回值: 表示n个圆盘搬运的总次数
*/
public static long countHanoi(int n) {
if (n == 1) {
// 只有一个盘,一步就搬运完毕
return 1;
}
return 2 * countHanoi(n - 1) + 1;
}
/*
n:表示带待搬运的圆盘数量
start: 这n个盘当前所在的杆的名字
middle: 搬运过程中辅助杆的名字
end: 这n个盘要移动到的目标杆的名字
*/
public static void hanoi(long n, char start, char middle, char end) {
// 定义递归出口
if (n == 1) {
System.out.println(start + "--->" + end );
return;
}
// 将最大的盘上面n - 1盘,从start ——> middle, 以end为辅助
hanoi(n - 1, start, end, middle);
// 对于start杆上最大的那个盘 start —— end
System.out.println(start + "--->" + end);
// 将 middle杆上剩下的n-1 移动到 end杆
hanoi(n - 1, middle, start, end);
}
}