java递归
前言:
各位朋友们,大家好!
因为我最近接触的感觉有难度的算法题一部分可以用递归进行解决,并且递归对于数据结构的学习也很重要,所以我今天总结了一下最近对递归的学习总结!
一、递归的使用场景
一个问题可拆分为若干个子问题的解
拆分后的子问题与原问题除问题规模不同,解决思路相同
存在递归的起始条件(无起始条件就会陷入死循环)
注意: 所谓起始条件就是不借助任何其他方法,就能直接知道求出问题答案
二、递归的定义
计算机科学中,递归是一种解决计算问题的方法(但他只是方法之一),其中解决方案取决于同一类问题的更小子集(方法自己调用方法自己,而方法里面调用别的方法,就不是解决同一类问题了)
三、例题进行分析
示例1:

思路分析:

.所谓递归就是有递并且还会存在归,所谓递就是你在调用自身方法,而归就是你执行完毕通过起始条件来进行由递到归的转换
.递的次数和归的次数是一样的,并且递的顺序和归的顺序相反(比如上图递的过程是n(0-4) 而归的过程就是n(4-0) )
.上同为例,其中起始条件(由递到归的条件)是n==4,而递的过程就是0-4,归的过程就是4-0
.从栈的角度来看:递是进栈,而归就是出栈
package ITHeiMaTest;
/*
* 定义一个字符串进行反向打印
* */
public class Demo {
public static void main(String[] args) {
String str = "TSIzwza";
//方法一:利用字符缓冲
StringBuffer sb = new StringBuffer(str);
System.out.println(sb.reverse());
//第二种方法使用递归实现
reverse(0,str);
}
public static void reverse(int n ,String str){
if (n == str.length()){
return ;
}
reverse(n + 1,str);
System.out.print(str.charAt(n));
}
}
上题答案如上!(并且我也写了一个字符缓冲流的API进行了书写转换)
接下来我会通过几个例题来进行书写递归
1.单路递归
示例2:
递归解决冒泡排序
package ITHeiMaTest;
import java.util.Arrays;
/*
* 利用递归输出冒泡排序
* */
public class Demo {
public static void main(String[] args) {
int[] arr = {4,2,6,8,3};
bubble(arr, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
//j表示未排序区间的右边界
public static void bubble(int[] arr, int j){
//结束条件j左边无元素
if (j == 0){
return;
}
for (int i = 0; i arr[i + 1]){
int t = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = t;
}
}
bubble(arr, j - 1);
}
}
上述代码存在一些时间上的浪费

上述你在排第一次(2和1)过后就有序了,但是这轮冒泡结束后但是递归过程没有结束,因为你的j并没有=0,他会持续进行直到j=0,而你后面进行的递归完全就属于无用功,因此我下面会书写提前结束递归对冒泡排序的优化
思路分析:
只需要定义一个变量作为排序和未排序的分界线即可
1.赋值规则:定义一个变量x,如果发生交换就把i索引的值赋值给x,如果没有发生交换x的值保持不变
2.为什么x是有序和无序的边界:冒泡排序中俩个元素发生了交换就表示有无序的情况,那么没有发生交换就表示有序,如果最后一次发生交换就是意味着后面的都是有序的,因为你是最后一次交换,后面没有发生交换,此时最后一次交换时候的x就表示有序和无序的分界线,所以优化了上边的冒泡现在你只需要考虑x左边的了,右边的并不需要考虑,上面的是j–表示有边界,而优化后的就是x表示右边界
代码实现:
package ITHeiMaTest;
import java.util.Arrays;
/*
* 对于冒泡排序进行优化
* 引进一个变量x 来作为有序和无序的分界线
*
* */
public class DemoNice {
public static void main(String[] args) {
int[] arr = {4,2,6,8,3};
bubble(arr, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
//j表示未排序区间的右边界
public static void bubble(int[] arr, int j){
//结束条件j左边无元素
if (j == 0){
return;
}
//此时的x表示有序和无序的分界线 x的右边为有序 x的左边为无序
int x = 0;
for (int i = 0; i arr[i + 1]){
int t = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = t;
//只要发生了交换x就往前移动
//而x后面没发生交换的一定是有序的
x = i;
}
}
bubble(arr, j - 1);
}
}
2.多路递归

多路递归也就是会分叉的递归(包含多个自身调用)
多路递归一般都比较复杂,不建议使用,建议使用递推(多路递归执行的代码很多都是重复的)
因为一个路没有运行完,下个路根本执行不了(上述的f5中一条支路没有走完,另一条支路不会执行)
示例3:
起始条件和递推关系:

package ITHeiMaTest;
/*
* 用递归求斐波那契数列
* */
public class Demo1 {
//递归求斐波那契次数十分麻烦 (次数为:2 * f(n + 1) - 1)
//多路递归一般都比较复杂,主要原因就是一个路未执行完,另外一个路无法继续执行
//多路递归也就是(分叉递归)
public static void main(String[] args) {
int x = sum(16);
System.out.println(x);
}
private static int sum(int n) {
//递到归的转换条件
if (n == 0){
return 0;
}
if (n == 1){
return 1;
}
int x = sum(n - 1);
int y = sum(n - 2);
return x + y;
}
}
上述的斐波那契可以用空间的浪费代替时间的浪费(就是用数组进行优化)
利用一维数组进行优化(二维数组也可以优化同理)
package ITHeiMaTest;
import java.util.Arrays;
/*
* 对斐波那契数列进行优化
* */
public class Demo2 {
public static int fibonacci(int n){
int[] cache = new int[n + 1];
Arrays.fill(cache, -1);
cache[0] = 0;
cache[1] = 1;
return f(n,cache);
}
private static int f(int n, int[] cache) {
if (cache[n] != -1){
return cache[n];
}
int x = f(n - 1,cache);
int y = f(n - 2,cache);
cache[n] = x + y;
return cache[n];
}
public static void main(String[] args) {
System.out.println(fibonacci(5));
}
}
示例4:
这是我认为的一道很好的关于递归的题(汉罗塔)

package ITHeiMa;
/*
* 递归实现汉罗塔
* */
import java.util.Arrays;
import java.util.LinkedList;
public class Demo1 {
//a b c表示三个柱子
//a 表示 原柱子
//b 借助的柱子
//c 目标的柱子
static LinkedList a = new LinkedList();
static LinkedList b = new LinkedList();
static LinkedList c = new LinkedList();
public static void main(String[] args) {
init(3);
print();
move(3,a,b,c);
}
//添加元素(n圆盘的个数)
public static void init(int n){
for (int i = n; i >= 1; i--) {
a.addLast(i);
}
}
public static void move(int n, LinkedList a,
LinkedList b,
LinkedList c){
if (n == 0){
return;
}
//将盘子由a 借助 c 移动到 b
move(n - 1, a , c , b);
//表示最后一个盘子移动到c
c.addLast(a.removeLast());
//将盘子由b 借助 a 移动到 c
move(n-1, b , a , c);
print();
}
public static void print() {
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println("-------------");
}
}
今天是我第一次写博客,会有很大的问题,如有什么错误,欢迎大佬在评论区指错,我一定会虚心听取努力进行改正
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/e71f2ff4d8.html
