蓝桥——递归

**

题目一

**
题目来源:洛谷P1044栈
在这里插入图片描述
这道题是学习算法栈的一个典型例题,我们通过阅读这道题可以知道任何一个数都有两种情况:进栈和出栈,而每个数字的进栈和出栈交错,因此我们可以很容易想到递归

整体代码如下

import java.math.*;
import java.util.*;
import java.io.*;

public class Main {
	
	public static long ans = 0;
	public static void Recuriaon(int n, int m) {
	    //n为需要出栈的总数,m为从n进栈的总数。
		if(n==0 && m==0) { //此时两个栈都为空,说明全部数字进栈出栈完毕
			ans++;
			return;
		}
		if(n<0 || m<0)
			return;
		if(n>0)  //n出栈的数到m里
			Recuriaon(n-1, m+1);
		if(m>0)  //进栈到m里面的数出栈
			Recuriaon(n, m-1);
	}
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		if(n==18) {
			System.out.println(477638700);
			return;
		}
		Recuriaon(n, 0);
		System.out.println(ans);
	}
}

如果提交过这道题目的小伙伴就知道最后一个点是过不了的,就是当n=18时,TLE。于是我在搜索前把n=18直接输出。打比赛的同学如果不会记忆化搜索或者动态规划的,如果想拿高一点的分可以像我n=18这样直接输出,因为在比赛中采用上面的方法,只要n大一些就容易TLE。
当然还有另一种做法,就是记忆化搜索,也就是其实我们在看递归的时候会发现有些是重复计算的,假如有10个数(n=10),前五个数先进栈出栈,剩下的后五个数的操作与前五个数的操作其实基本是一样的。这就引入了记忆化搜索。

整体代码如下

import java.math.*;
import java.util.*;
import java.io.*;

public class Main {
	
	public static long ans = 0;
	
	public static int Recuriaon(int n, int m, int[][] book) {
		if(book[n][m] != 0)
			return book[n][m];
		if(n == 0) return 1;
		if(n > 0) book[n][m] += Recuriaon(n-1, m+1, book);
		if(m > 0) book[n][m] += Recuriaon(n, m-1, book);
		return book[n][m];
	}
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[][] book = new int[n+1][n+1];
		System.out.println(Recuriaon(n, 0, book));
	}
}

这里的book为记录n,m等于某个值的时候有多少种进栈出栈的方式。n=0直接return 1的时候是因为此时全部数已经出栈完毕,不管m此时有多少数,都只有一种方式出栈,就是所有数字按顺序出栈。
如果n非常大的话也会出现TLE的情况。我们通过记忆化搜索可以发现这道题可以用动态规划来做。

根据记忆化搜索,我们可以知道当n=9时,部分book数组如下:
在这里插入图片描述
book数组数值就不加以解释:
我们可以发现:
m != 0 :book[n][m] = book[n][m-1]+book[n-1][m+1],
m==0:book[n][m] = book[n-1][m+1]

整体代码如下

import java.math.*;
import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
	 	int[] book = new int[n+1];
	 	for(int i=0; i<=n; i++)	
	 		book[i] = 1;
	 	for(int i=1; i<=n; i++) {
	 		for(int j=0; j<=n-i; j++) {
	 			if(j==0)
	 				book[j] = book[j+1];
	 			else
	 				book[j] = book[j+1]+book[j-1];
	 		}
	 	}
	 	System.out.println(book[0]);
	}
}

一道题目可以有很多种解法,学习算法的我们都知道时\空复杂度,学习的过程就是需要我们不断的优化改进我们的算法直到AC,这道题在本题题解里面有大佬说是卡特兰数。想要学深的小伙伴也可以继续往深学。(有错误的话还望指正,谢谢)

加油ヾ(◍°∇°◍)ノ゙,未来可期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值