Java基础语法(递归练习,快速排序,斐波那契数列)
1 递归思想
1、什么是递归:
字面意思就是信息传递,然后归并。
递归可以大大缩短程序的代码,有意识的使用递归,可以用较短的代码解决一些复杂的问题。甚至有些问题非得使用递归解决不可。
2、递归的思想:
把规模大的、较难解决的问题变成规模较小的、易解决的同一问题。
规模较小的问题又变成规模更小的问题,并且小到一定程度可以直接得出它的解,从而得到原来问题的解。
3、何时用递归,满足一下三点:
- (1)解决某个问题时,可以把这个问题转化为一个新的问题,但解决方法仍与原问题的解法相同,只是所处理的对象有所不同,这些被处理的对象之间是有规律的,或递增或递减或交换等等;
- (2)通过转化过程是可以让问题得到解决的;
- (3)必定要有一个明确的结束递归的条件,否则递归将会无止境地进行下去,直到耗尽系统资源。也就是说必须有要某个终止递归的条件。
4、递归使用:
- 函数中调用函数自己(可多次调用)。
5、强调注意事项:
- 因为递归是函数自己调用自己,容易造成无限循环。
- 必须有要某个终止递归的条件。
- 能用循环轻松解决的就用循环。
2 求 N 的阶乘
1、阶乘计算规则:
1! = 1
2! = 2 * 1! = 2 * 1
3! = 3 * 2! = 3 * 2 * 1! = 3 * 2 * 1
N! = N * (N - 1)! = N * (N - 1) * (N - 2)! = ...... = N * (N - 1) * (N - 2) * ... * 1
2、通过递归实现 N 的阶乘:Factorial.java
/**
* @author zc
* @date 2021/11/25 10:46
* 通过递归实现 N 的阶乘
*
* main(String[] args):主程序入口。
* facN(int n):函数,递归求 n 的阶乘。
*/
public class Factorial {
/**
* 主程序入口
* @param args 系统参数
*/
public static void main(String[] args) {
int n = 4;
int flag = facN(n);
if (flag == -1) {
System.out.println("不符合阶乘计算规则");
} else {
System.out.println(n + " 的阶乘为:" + flag);
}
}
/**
* 函数,递归求 n 的阶乘
* @param n 阶乘参数
* @return 返回 n 的阶乘
*/
public static int facN(int n){
if (n < 1){
return -1;
} else if (n == 1) {
return 1;
} else {
return n * facN(n - 1);
}
}
}
3 快速排序
1、快速排序原理:
- (1)在数组中取一个基准点;
- (2)然后分别从数组的两端扫描数组,交换数据使基准点左边的数据比基准点小,右边数据比基准点大;
- (3)确定此时的基准点为第一个分界点,将数组分为两部分;
- (4)每部分又从每部分的两端开始从第 (1)步开始,一直找完分界点,就排序完了。
2、代码实现:QuickSort.java
import java.util.Arrays;
/**
* @author zc
* @date 2021/11/4 16:06
* 快速排序:QuickSort
*
* main(String[] args):主函数入口
* quickSort(int[] num, int left, int right):方法,递归快速排序
* getIndex(int[] num, int left, int right):方法,获取分界点
*
*/
public class QuickSort {
public static void main(String[] args) {
int[] num ={5,2,8,3,9,4,7};
System.out.println("原始数据:" + Arrays.toString(num));
quickSort(num,0,num.length-1);
System.out.println("快速排序:" + Arrays.toString(num));
}
/**
* 递归快速排序
* @param num 整型数组,数据存储容器
* @param left 排序范围左下标
* @param right 排序范围右下标
*/
public static void quickSort(int[] num, int left, int right) {
if(left > right) {
return;
} else {
// 获取分界点
int index = getIndex(num,left,right);
// 递归排左边
quickSort(num, left,index - 1);
//递归排右边
quickSort(num,index + 1, right);
}
}
/**
* 获取分界点
* @param num 整型数组,数据存储容器
* @param left 标志左下标扫描
* @param right 标志右下标扫描
* @return 返回分界点
*/
public static int getIndex(int[] num, int left, int right){
// 基准点
int key = num[left];
while(left < right){
// 扫描右边,右边的数都比基准点大
while (num[right] >= key && left < right){
// 右边下标往左移
right--;
}
// 循环完右边后,此时右边下标 right 的值是比基准点 key 小,或者此时 left = right,交换
num[left] = num[right];
// 扫描左边,左边的数都比基准点小
while (num[left] <= key && left < right){
// 左边下标往右移
left++;
}
// 循环完左边后,此时左边下标 left 的值是比基准点 key 大,或者此时 left = right,交换
num[right] = num[left];
}
// 基准点交换原值
num[left] = key;
// 返回此时分界点 left,此时的 left 左边值都比之小,右边值都比之大
return left;
}
}
4 斐波那契数列
1、什么是斐波那契数列?
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。
指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、55、89……
这个数列从第3项开始,每一项都等于前两项之和。
在数学上,斐波那契数列以如下被以递推的方法定义:
- F(0) = 0;
- F(1) = 1;
- F(n) = F(n - 1) + F(n - 2)(n ≥ 2,n ∈ N*)。
2、斐波那契数列算法:
- (1) 循环:输出第N个位置的元素;
- (2) 递归:输出第N个位置的元素。
4.1 循环:FiboFor.java
/**
* @author zc
* @date 2021/11/25 10:06
* 斐波那契数列:
* 循环:输出第N个位置的元素。
* mian(String[] args):主程序入口。
* fibo(int n):函数,循环求斐波那契数列第 N 个位置的元素。
*/
public class FiboFor {
/**
* 主程序入口
* @param args 系统参数
*/
public static void main(String[] args) {
int n = 9;
int flag = fibo(n);
if (flag == -1) {
System.out.println("斐波纳契数列给出的位置错误!!!!");
} else {
System.out.println("斐波纳契数列第 " + n + " 个位置的元素是:" + flag);
}
}
/**
* 函数,循环求斐波那契数列第 N 个位置的元素
* @param n 斐波那契数列第 N 个位置
* @return 返回斐波那契数列第 N 个位置的元素
*/
public static int fibo(int n){
if (n < 0){
return -1;
} else if (n == 0){
return 0;
} else if (n == 1){
return 1;
} else {
int n0 = 0, n1 = 1, sum = 0;
for (int i = 2; i <= n; i++) {
// sum 为 ni 的值
sum = n0 + n1;
// 数列向前移动一位
n0 = n1;
n1 = sum;
}
return sum;
}
}
}
4.2 递归:FiboRecursion.java
/**
* @author zc
* @date 2021/11/25 10:27
* 斐波那契数列:
* 递归:输出第N个位置的元素。
* mian(String[] args):主程序入口。
* fibo(int n):函数,递归求斐波那契数列第 N 个位置的元素。
*/
public class FiboRecursion {
/**
* 主程序入口
* @param args 系统参数
*/
public static void main(String[] args) {
int n = 10;
int flag = fibo(n);
if (flag == -1) {
System.out.println("斐波纳契数列给出的位置错误!!!!");
} else {
System.out.println("斐波纳契数列第 " + n + " 个位置的元素是:" + flag);
}
}
/**
* 函数,递归求斐波那契数列第 N 个位置的元素
* @param n 斐波那契数列第 N 个位置
* @return 返回斐波那契数列第 N 个位置的元素
*/
private static int fibo(int n) {
if (n < 0) {
return -1;
} else if (n == 0) {
return 0;
} else if (n == 1){
return 1;
} else {
return fibo(n - 1) + fibo( n - 2);
}
}
}