递归

  • 递归概念
  • 递归实现求和、斐波那契和求阶乘
  • 汉诺塔
  • n皇后
  • 递归实现单链表

一、递归概念

递归:
递归就是方法里调用自身
1.在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口
2.递归算法解题通常显得很简洁,但递归算法解题的运行效率较低
3.在递归调用的过程中,系统为每一层的返回点、局部变量等开辟了栈来存储。
4.递归次数过多容易造成栈溢出等
5.分治思想,递归就是运用这种思想------将更大的问题进行拆分,拆分成若干个较小的问题,就这样一直拆分,直至不能拆分为止
具体地说,如果递归函数调用自己,则被调用的函数也将调用自己,这将无限循环下 去,除非代码里有终止调用的语句。通常的方法是将递归调用放在if语句中。
6.递归的基本思想
是广义地把规模大的问题转化为规模小的相似的子问题或者相似的子问题集合来解决。 广义针对规模的,规模的缩小具体可以是指递归函数的参数,也可以是其参数之一。相似是 指解决大问题的方法和解决小问题的方法往往是同一个方法,还可以是指解决子问题集的各 子问题的方法是同一个方法。解决大问题的方法可以是由解决次规模问题的方法和解决剩余 部分的方法组成,也可以是由一系列解决次规模问题的方法组成。
迭代:
按照一个方向一个一个进行取值计算,如for循环…

二、递归实现求和、斐波那契和求阶乘

package org.yanan.递归;

public class test01 {
	public static void main(String[] args) {
		//求和:递归和迭代
		int sum1=getSum1(100);
		int sum2=getSum2(100);
		System.out.println(sum1);
		System.out.println(sum2);
		//前20项斐波那契数列:递归和迭代
		for(int i=1;i<=20;i++){//前20项斐波那契数列
			System.out.println(fibe1(i));
		}
		System.out.println(fibe2(3));
		//阶乘:递归和迭代:
		System.out.println(getJie1(5));
		System.out.println(getJie2(5));
	}

	private static long getJie2(int n) {
		if(n==1){
			return 1;
		}
		return getJie2(n-1)*n;
	}
	private static long getJie1(int n) {
		long res=1;
		for(int i=1;i<=n;i++){
			res=res*i;
		}
		return res;
	}

	private static int fibe1(int n) {
		if(n==1||n==2){
			return 1;
		}else{
			return fibe1(n-2)+fibe1(n-1);
		}
	}
private static long fibe2(int n) {
		if(n==1||n==2){
			return 1;
		}
		int first=1;
		int second=1;
		int third=0;
		for(int i=1;i<=n-2;i++){
			third=first+second;
			first=second;
			second=third;
		}
		return third;
	}


	private static int getSum2(int n) {
		int sum=0;
		for(int i=1;i<=n;i++){
			sum=sum+i;
		}
		return sum;
	}
	private static int getSum1(int n) {//表示第n项
		if(n==1){
			return 1;
		}
		return getSum1(n-1)+n;
	}
}

三、汉诺塔问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package org.yanan.递归;

import org.yanan.link.LinkedStack;

public class HanNuoTa {
	public static void main(String[] args) {
		//move("x","y","z",3);
		int N=3;
		LinkedStack<Integer> stackX=new LinkedStack<>();
		for(int i=N;i>=1;i--){//元素先进入X栈
			stackX.push(i);	
		}
		LinkedStack<Integer> stackY=new LinkedStack<>();
		LinkedStack<Integer> stackZ=new LinkedStack<>();
		move(stackX,stackY,stackZ,N);
		System.out.println(stackX);
		System.out.println(stackZ);
	}

//	private static void move(String x, String y, String z,int level) {
//		//递归结束条件
//		if(level==1){
//			System.out.println(x+"->"+z);//从源直接到目的,不借助任何
//		}else{
//			move(x,z,y,level-1);//前两个现在在x,它需要借助z到y
//			System.out.println(x+"->"+z);//第三个从源直接到目的,不借助任何
//			move(y,x,z,level-1);//后两个
//		}
//		
//		
//	}
	private static void move(LinkedStack<Integer> x,LinkedStack<Integer> y, LinkedStack<Integer> z, int level) {
		if(level==1){
			z.push(x.pop());
		}else{
			move(x,z,y,level-1);
			z.push(x.pop());
			move(y,x,z,level-1);
		}
	}

}

四、n皇后

在这里插入图片描述
在这里插入图片描述

/*
 * 第1行
 * 		1
 * 		第2行
 * 			3
 * 			第3行
 * 				5
 * 				第4行
 * 					2	X
 * 					第5行
 * 						4	X
 * 						第6行
 * 							X
 * 						8	X
 * 						第6行
 * 							X
 * 					7
 * 					第5行
 * 						2	X
 * 						第6行	X
 * 							4	X
 * 							第7行
 * 								6	X
 * 								第8行
 * 									X
 * 						4
 * 						...
 * 						
 * 					8
 * 				6
 *				7
 *				8
 * 			4
 * 			5
 * 			6
 * 			7
 * 			8
 * 		2
 * 		3
 * 		4
 * 		5
 * 		6
 * 		7
 * 		8
 * */
public class EightQueen {
	private static int count=0;	//记录第几种可能
	private static int N=8;
	public static void main(String[] args) {
		int[][] arr=new int[N][N];	//数组中默认元素为0,1当皇后
		eightQueen(0,arr);	//打印八皇后所有可能的解 并且从第一行开始 0
	}
	//row [0,7]
	private static void eightQueen(int row, int[][] arr) {
		if(row==N){//递归出口,并打印,找寻每一种可能,如果走到第九行代表前8行没问题
			count++;
			System.out.println("第"+count+"种:");
			for(int i=0;i<arr.length;i++){//打印数组的每种可能
				for(int j=0;j<arr[i].length;j++){
					System.out.print(arr[i][j]+" ");
				}
				System.out.println();
			}
		}else{
			//做一个数组备份
			int[][] newArr=new int[N][N];
			for(int i=0;i<arr.length;i++){//将原数组的数据赋给新数组
				for(int j=0;j<arr[i].length;j++){
					newArr[i][j]=arr[i][j];
				}
			}
			for(int col=0;col<N;col++){
				if(noDangerous(row,col,newArr)){
					for(int c=0;c<N;c++){//找寻下一个元素之前将记录清空
						newArr[row][c]=0;
					}
					newArr[row][col]=1;
					eightQueen(row+1, newArr);
				}
			}
		}	
	} 
	private static boolean noDangerous(int row, int col, int[][] newArr) {
		//正上
		for(int r=row-1;r>=0;r--){
			if(newArr[r][col]==1){
				return false;
			}
		}
		//左上
		for(int r=row-1,c=col-1;r>=0&&c>=0;r--,c--){
			if(newArr[r][c]==1){
				return false;
			}
		}
		//右上
		for(int r=row-1,c=col+1;r>=0&&c<N;r--,c++){
			if(newArr[r][c]==1){
				return false;
			}
		}
		return true;
	}
}

五、递归实现单链表

package p03.递归;
//递归实现的链表
public class LinkedListRecursion {
	private class ListNode{
		int data;
		ListNode next;
	}
	private int size=0;
	private ListNode head;
	public LinkedListRecursion(){
		head=new ListNode();
	}
	public void add(int e){	//默认在尾部添加元素
		add(head,e);
	}
	//以当前node为头结点 添加元素e 
	private void add(ListNode node, int e) {
		if(node.next==null){
			ListNode n=new ListNode();
			n.data=e;
			n.next=node.next;
			node.next=n;
			size++;
		}else{
			add(node.next,e);
		}
	}
	public int getSize(){
		return size;
	}
	public void remove(){	//默认删除最后一个元素
		remove(head);
	}
	private ListNode remove(ListNode node) {
		if(node.next==null){
			return null;
		}
		node.next=remove(node.next);
		return node;
	}
	@Override
	public String toString() {
		StringBuilder sb=new StringBuilder("[");
		toString(head.next,sb);
		return sb.toString();
	}
	private void toString(ListNode node, StringBuilder sb) {
		if(node==null){
			sb.append("]");
		}else{
			sb.append(node.data+" ");
			toString(node.next,sb);
		}
	}
	public static void main(String[] args) {
		LinkedListRecursion list=new LinkedListRecursion();
		list.add(1);
		list.add(2);
		list.add(3);
		list.remove();
		list.remove();
		System.out.println(list);
	}
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值