JAVA递归试题库.docx
《JAVA递归试题库.docx》由会员分享,可在线阅读,更多相关《JAVA递归试题库.docx(72页珍藏版)》请在冰豆网上搜索。
![JAVA递归试题库.docx](https://file1.bdocx.com/fileroot1/2023-2/8/ba4f3b1f-11e9-4ede-a934-486b4f1af9f7/ba4f3b1f-11e9-4ede-a934-486b4f1af9f71.gif)
JAVA递归试题库
递归
一基础知识
<1>递归中每次循环都必须使问题规模有所缩小。
<2>递归操作的每两步都是有紧密的联系,如在“递归”的“归操作时”,前一次的输出就是后一次的输入。
<3>当子问题的规模足够小时,必须能够直接求出该规模问题的解,其实也就是必须要有结束递归的条件。
二递归要解决什么问题呢?
1不同的方法体之间的传递
publicstaticvoidmain(String[]args){
g();
}
privatestaticvoidg(){
f(3);
}
privatestaticintf(inti){
returni+k(i);
}
privatestaticintk(inti){
returni;
}
2相同的方法体不同方法名之间的传递
publicstaticvoidmain(String[]args){
inti=g(4);
System.out.println(i);
}
privatestaticintg(inti){
returni*g1(3);
}
privatestaticintg1(inti){
returni+g2
(2);
}
privatestaticintg2(inti){
returni*g3
(1);
}
privatestaticintg3(inti){
returni;
}
3看一看得出其实功能相同所以直接使用递归
publicstaticvoidmain(String[]args){
inti=g(4);
System.out.println(i);
}
privatestaticintg(inti){
if(i==1){
returni;
}
returni*g(i-1);
}
根据2与3的比较明显的看得出使用递归明显的缩短了代码的使用量
4递归的使用框架
返回值类型f(形参){
if(终止条件){
return结果;
}
else{
returnf(形参递减或者递增);
}
}
5递归算法一般用于解决三类问题:
(1)数据的定义是按递归定义的。
(Fibonacci函数)
(2)问题解法按递归算法实现。
这类问题虽则本身没有明显的递归结构,
但用递归求解比迭代求解更简单,如汉诺塔
(3)数据的结构形式是按递归定义的。
如二叉树、广义表等,
由于结构本身固有的递归特性,则它们的操作可递归地描述。
三经典案例
1斐波纳契数列
斐波那契数列(Fibonaccisequence),又称黄金分割数列、因数学家列昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:
0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:
F(0)=0,F
(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)
publicstaticintf(intx){
if(x==0){
return0;
}
if(x==1||x==2){
return1;
}
returnf(x-1)+f(x-2);
}
2阶乘
publicstaticintf(intx){
if(x==1){
return1;
}else{
returnx*f(x-1);
}
}
3全排列
4汉诺塔
publicstaticvoidhanoi(intn,charorigin,charassist,chardestination){
if(n==1){
System.out.println("Direction:
"+origin+"--->"+destination);
}else{
hanoi(n-1,origin,destination,assist);
System.out.println("Direction:
"+origin+"--->"+destination);
hanoi(n-1,assist,origin,destination);
}
}
四试题:
I递归定义
33.递归的框架题意试数字符串反转
/*
我们把“cba”称为“abc”的反转串。
题意就是对字符串的反转
求一个串的反转串的方法很多。
下面就是其中的一种方法,代码十分简洁(甚至有些神秘),
请聪明的你通过给出的一点点线索补充缺少的代码。
把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
*/
思路就是每次保存最后一位并且放在第一个上返回
或者每次保存第一个并且放在最后一个
publicclassDemo03{
publicstaticStringreverseString(Strings){
if(s.length()<2||s==null)returns;
//每一次将第一位放在最后,将第二位放在倒数第二位然后进行递归
returnreverseString(s.substring
(1))+s.charAt(0);
//returns.charAt(s.length()-1)+reverseString(s.substring(0,s.length()-1));}
publicstaticvoidmain(String[]args){
Strings="123456";
Stringss=reverseString(s);
System.out.println(ss);
}
}
运行结果:
654321
132、递归把串s中第一个出现的数字的值返回。
如果找不到数字,返回-1例如:
s="abc24us43"则返回2
s="82445adb5"则返回8
s="ab"则返回-1
publicstaticintgetFirstNum(Strings)
{
if(s==null||s.length()==0)return-1;
charc=s.charAt(0);
if(c>='0'&&c<='9')returnc-'0';//填空
returngetFirstNum(s.substring
(1));//填空
}
publicstaticvoidmain(String[]args){
Strings="abs7c24us43";
System.out.println(getFirstNum(s));
}
102.递归的定义试数连续数
以下程序打印出0~9的数字,请补充缺少的代码。
*/
publicclass递归连续数{
publicstaticvoidf(intbegin,intend){
if(begin>end)return;//填空
System.out.println(begin);
f(begin+1,end);
}
publicstaticvoidmain(String[]args){
f(0,9);
}
}
运行结果:
0
1
2
3
4
5
6
7
8
9
113.递归定义题意理解公交车标价
*公交车票价为5角。
假设每位乘客只持有两种币值的货币:
5角、1元。
*再假设持有5角的乘客有m人,持有1元的乘客有n人。
由于特殊情况,开始的时候,售票员没有零钱可找。
*我们想知道这m+n名乘客以什么样的顺序购票则可以顺利完成购票过程。
*显然,m=n的时候,有些情况也不行。
比如,第一个购票的乘客就持有1元。
*下面的程序计算出这m+n名乘客所有可能顺利完成购票的不同情况的组合数目。
*注意:
只关心5角和1元交替出现的次序的不同排列,持有同样币值的两名乘客交换位置并不算做一种新的情况来计数。
*/
publicclass公交车票价{
//m:
持有5角币的人数
//n:
持有1元币的人数
//返回:
所有顺利完成购票过程的购票次序的种类数
publicstaticintf(intm,intn){
if(mreturn0;
if(n==0)
return1;
returnf(m-1,n)+f(m,n-1);//填空
}
publicstaticvoidmain(String[]args){
System.out.println(f(10,8));
}
运行结果:
11934
147递归以下程序打印出0~9的数字,请补充缺少的代码。
publicclassMyTest
{
publicstaticvoidf(intbegin,intend)
{
If(begin>end)return;
System.out.println(begin);
f(begin+1,end);
}
publicstaticvoidmain(String[]args)
{
f(0,9);
}
}
II排列普通
1字符排序全排列
算法是这样的,如果给定N个不同字符,将这N个字符全排列,最终的结果将会是N!
种。
如:
给定A、B、C三个不同的字符,则结果为:
ABC、ACB、BAC、BCA、CAB、CBA一共3!
=3*2=6种情况。
publicclassAllPermutation
{
publicstaticvoidmain(String[]args)
{
//使用递归完成全排列
char[]source=newchar[]{'A','B','C'};
char[]result=newchar[source.length];
allPermutation(0,source,result);
}
/**
*
*@paramindex当前考虑的数的下标(从0开始)
*@paramsource
*@paramresult
*/
publicstaticvoidallPermutation(intindex,char[]source,char[]result){
//当源数据中只有一个字符时,将该字符加入结果数组,并输出
if(source.length==1){
result[index]=source[0];
show(result);
return;
}
//
for(inti=0;iresult[index]=source[i];
char[]newSource=getNewSource(source,source[i]);
allPermutation(index+1,newSource,result);
}
}
publicstaticvoidshow(char[]result){
System.out.println(result);
}
/**
*生成去掉指定字符的新源数据数组
*@paramsource原来的源数据数组
*@paramc指定去掉的字符
*@return
*/
publicstaticchar[]getNewSource(char[]source,charc){
char[]newSource=newchar[source.length-1];
for(inti=0,j=0;iif(source[i]!
=c){
newSource[j]=source[i];
j++;
}
}
returnnewSource;
}
}
42.全排列递归Stringbuffer警察智力训练
匪警请拨110,即使手机欠费也可拨通!
为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练!
某批警察叔叔正在进行智力训练:
123456789=110;
请看上边的算式,为了使等式成立,需要在数字间填入加号或者减号(可以不填,但不能填入其它符号)。
之间没有填入符号的数字组合成一个数,
例如:
12+34+56+7-8+9就是一种合格的填法;123+4+5+67-89是另一个可能的答案。
请你利用计算机的优势,帮助警察叔叔快速找到所有答案。
每个答案占一行。
形如:
12+34+56+7-8+9123+4+5+67-89......
已知的两个答案可以输出,但不计分。
各个答案的前后顺序不重要。
//遍历所有情况
publicstaticvoidfun(Stringv,intn){
if(n==9){//修改到最后一位符号时输出
check(v);
}else{//递归向后修改,数字变为数字加符号
fun(v.replace(n+"",n+"+"),n+1);
fun(v.replace(n+"",n+"-"),n+1);
fun(v,n+1);
}
}
//验证并输出
publicstaticvoidcheck(Stringstr){
String[]s=str.split("[\\+]");
intsum=0;
for(Stringt:
s){
String[]sub=t.split("[\\-]");
intnum=Integer.parseInt(sub[0]);
//计算负数
for(inti=1;inum-=Integer.parseInt(sub[i]);
}
sum+=num;//正数或负数结果加到总和上
}
if(sum==110){
System.out.println(str);
}
}
publicstaticvoidmain(String[]args){
Stringstr="123456789";
fun(str,1);//调用函数,从1开始修改
}
46算法实现全排列
递归算法:
将数据分为两部分,递归将数据从左侧移右侧实现全排列
importjava.util.Arrays;
importjava.util.List;
importjava.util.ArrayList;
publicclassT06{
//输出
publicstaticvoidprint(Listtarget){
for(Objecto:
target){
System.out.print(o);
}
System.out.println();
}
//递归排列
publicstaticvoidsort(Listdatas,Listtarget,intn){
if(target.size()==n){
print(target);
return;
}
for(inti=0;iListnewDatas=newArrayList(datas);
ListnewTarget=newArrayList(target);
newTarget.add(newDatas.get(i));
newDatas.remove(i);
sort(newDatas,newTarget,n);
}
}
//主函数
publicstaticvoidmain(String[]args){
String[]s={"a","b","c"};
sort(Arrays.asList(s),newArrayList(),s.length);
}
}
运行结果:
abc
acb
bac
bca
cab
cba
方法二:
publicclassAllSort{
publicstaticvoidperm(String[]buf,intstart,intend){
if(start==end){//当只要求对数组中一个字母进行全排列时,只要按该数组输出即可
for(inti=0;i<=end;i++){
System.out.print(buf[i]);
}
System.out.println();
}
else{//多个字母全排列
for(inti=start;i<=end;i++){
Stringtemp=buf[start];//交换数组第一个元素与后续的元素
buf[start]=buf[i];
buf[i]=temp;
perm(buf,start+1,end);//后续元素递归全排列
temp=buf[start];//将交换后的数组还原
buf[start]=buf[i];
buf[i]=temp;
}
}
}
publicstaticvoidmain(String[]args){
Stringbuf[]={"a","b","c"};
perm(buf,0,buf.length-1);
}
}
运行结果:
abc
acb
bac
bca
cba
cab
47.递归字符串全排列
字符串全排列
publicclassT03{
//输出字符数组
publicstaticvoidprint(char[]arr){
for(inti=0;iSystem.out.print(arr[i]);
}
System.out.println();
}
//递归遍历
publicstaticvoidperm(char[]arr,intstart,intend){
if(start==end){
print(arr);//输出
}else{
for(inti=start;i<=end;i++){
//换位
charc=arr[start];
arr[start]=arr[i];
arr[i]=c;
//递归
perm(arr,start+1,end);
//恢复数组原位
c=arr[start];
arr[start]=arr[i];
arr[i]=c;
}
}
}
//字符串转字符数组
publicstaticvoidf(Strings){
char[]arr=s.toCharArray();
perm(arr,0,arr.length-1);
}
publicstaticvoidmain(String[]args){
Strings="abc";
f(s);
}
}
运行结果:
abc
acb
bac
bca
cba
cab
58.递归全排列带分数
100可以表示为带分数的形式:
100=3+69258/714
还可以表示为:
100=82+3546/197
注意特征:
带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100有11种表示法。
题目要求:
从标准输入读入一个正整数N(N<1000*1000)
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:
不要求输出每个表示,只统计有多少表示法!
例如:
用户输入:
100
程序输出:
11
再例如:
用户输入:
105
程序输出:
6
资源约定:
峰值内存消耗(含虚拟机)<64M
CPU消耗<3000ms
请严格按要求输出,不要画蛇添足地打印类似:
“请您输入...”的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
publicclassMyTest{
privatestaticSetall=newHashSet();
privatestaticSettemp1=newHashSet();
privatestaticSettemp2=newHashSet();
publicstaticvoidmain(String[]args){
for(inti=1;i<9876;i++){
all.clear();
if(isDuplicate(i,temp1)){
continue;
}
for(intj=2;j<100;j++){
if(!
isDuplicate(j*i,temp1)){
inty=100-j;
if(!
isDuplicate(y,temp2)&&all.size()==9){
System.out.println(100+"="+y+"+"+j*i+"/"+i);
}else{
all.removeAll(temp1);
}
}
}
}
}
privatestaticbooleanisDuplicate(intn,Settemp){
temp.clear();
inti=0;
booleanflag=false;
while(n>0){
intx=n%10;
temp.add(x)