**
题目一
**
题目来源:洛谷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,这道题在本题题解里面有大佬说是卡特兰数。想要学深的小伙伴也可以继续往深学。(有错误的话还望指正,谢谢)