递归原来可以so easy|-连载(5)

对递归进行优化–剪枝

上文讲述了递归的一个优化手段:记忆化。

本文将讲述递归的另一个优化手段:剪枝。

如前文所述,递归的一个缺点是执行步数或者说路径狠长,导致运行时间长。

那么有没有什么办法减少执行次数呢?

剪枝就是这么一个手段。

当在递归过程中,已经明确知道当前不会是最优解,或者说再往下走不会得到正确结果,则可以不再往下递归,从而减少执行次数。

下面以一个示例来进行演示如何进行剪枝。

示例:任意输入10个数,从这10个数中任取8个数(不重复)并求和,求和的最小值。

比如:10个数为1 2 3 4 5 6 7 8 9 10,则最小和为36 (即1+2+3+4+5+6+7+8).

先用不剪枝的递归来实现:

package hello;

import java.util.Scanner;

public class Hello {
	static int count=0; //递归调用的次数
	static int mmin=Integer.MAX_VALUE; //最小的和
	boolean s[]=new boolean[10]; //标记某个数是否被使用过
	
	//不剪枝的递归
	void bujz(int[] a,int ci,int sum){
		count++; //计算递归调用的次数
		if(ci==8){ //已经达到8个数,递归结束
			if(sum<mmin){ //如果比当前的mmin小,则更新mmin
				mmin=sum; 
			}
			return ;
		}
		for(int i=0;i<10;i++){
			if(s[i]==false){
				s[i]=true; //标记是否使用过
				bujz(a,ci+1,sum+a[i]); //累加和,次数加1,并递归调用
				s[i]=false;
			}
		}
		return ;
	}
	
	public static void main(String[] args) {
		int a[]=new int[10];
		Scanner sc=new Scanner(System.in);
		for(int i=0;i<10;i++){
			a[i]=sc.nextInt();
		}
		Hello h=new Hello();
		h.bujz(a,0,0); //不剪枝
		System.out.println("最小的和为:"+mmin+",次数:"+count);
	}
}

程序运行结果:

在这里插入图片描述

从运算结果可以看到: 递归调用了 260万次。

下面我们用剪枝来优化一下:

package hello;

import java.util.Scanner;

public class Hello {
	static int count=0; //递归调用的次数
	static int mmin=Integer.MAX_VALUE; //最小的和
	boolean s[]=new boolean[10]; //标记某个数是否被使用过

	//剪枝的递归,可以减少递归调用的次数
	void jz(int[] a,int ci,int sum){
		count++; //计算递归调用的次数
		//下面这个if语句,完成剪枝
		if(sum>=mmin){ //在未达到8个数之前,和已经大于mmin,没有必要再往下递归了
			return ;
		}
		if(ci==8){
			mmin=sum;
			return ;
		}
		for(int i=0;i<10;i++){
			if(s[i]==false){
				s[i]=true;
				jz(a,ci+1,sum+a[i]);
				s[i]=false;
			}
		}
		return ;
	}
	
	public static void main(String[] args) {
		int a[]=new int[10];
		Scanner sc=new Scanner(System.in);
		for(int i=0;i<10;i++){
			a[i]=sc.nextInt();
		}
		Hello h=new Hello();
		h.jz(a,0,0); //剪枝
		System.out.println("最小的和为:"+mmin+",次数:"+count);
	}
}

在这里插入图片描述

从运算结果可以看到: 递归调用了 107万次。

减少了50%多的运行次数,效果还是很可观的。

这个剪枝的技巧,在递归中经常被使用,可以明显提高递归效率。

大家可以在以后的开发过程中尝试使用。

源码、更多资深讲师相关课程资料、学习笔记请入群后向管理员免费获取,更有专业知识答疑解惑。入群即送价值499元在线课程一份。
QQ群号:560819979
敲门砖(验证信息):高山流水

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值