Bootstrap

Java基础算法50题(一)

文章目录

1、有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?

  对于此问题,可以先手动写出前几个月的兔子数量,来观察其总数增长规律。前10个月的的总数为:1、1、 2、3、5 、8 、13、21、34、55,从这些数字来看,发现其规律就是从第3个数字开始,每个数字的值等于前面紧邻的两个数字的和,所以这其实就是一个斐波那契数列。
  既然看出了这题目的本质是斐波那契数列,那编程实现就简单了。最常规的做法是递归,当月份为1或2时,总数为1,其他月份等于前面两个月数量相加。示例代码如下:

    public static int f(int month){
       if(month==1 || month==2)
          return 1;
       else
          return f(month-1)+f(month-2);
    }

  递归能不用就不用,因为:

1)造成大量的资源浪费
2)可能会造成栈溢出异常

  该问题除了可以用递归形式实现,还可以用循环方式实现。用循环实现的,我们只要用两个变量来表示所求的月份的前两个月的数量,然后不断迭代更新这两个月份的值,再相加这两个月份的值,也能求出该月份的兔子数量。示例代码如下:

    public static int num(int month){
    	int temp = 0;
    	int month1num = 1;
    	int month2num = 1;
    	for(int i =3;i <= month;i++){
    		temp = month2num;
    		month2num = month2num +month1num;
    		month1num = temp;
    	}
    	return month2num;
    }

2、判断101-200之间有多少个素数,并输出所有素数。

  要解决该问题,先了解什么是素数。素数一般指质数,质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数
  既然是求素数,也就是说求满足如下要求的一些数:这些数在除以1和本身之外的数字时,余数不为0即可。最常见的思路是双层for循环,挨个除从2到小于该数字-1,用一个boolean型变量标识该数字是否是素数,是的话则输出。示例代码如下:

    private static void primeNumber(){
    	for(int i=101;i<200;i++){
    		boolean isResult=true;
    		for(int j=2;j<i;j++){
    			if(i%j == 0){
    				/*代表该数字i不是素数*/
    				isResult=false;
    			}
    		}
    		if(isResult){
    			/*经过内层for循环的筛选后的,都是素数*/
    			System.out.print(i+" ");
    		}
    	}
    }

  关于在内层循环判断素数的逻辑,其实也可以不用boolean变量来实现。该方法没上面的那个方法那么容易想到,当除数从2到被除数-1全试完后,其实也就是说明这个数是个素数。此时,内层循环的控制变量j经历了j++,其值也被除数i是相等的!也就是说,将是否是素数的判断逻辑从内层for循环转移到了外层for循环。示例代码如下:

private static void primeNumber(){
	int j=0;
	for(int i=101;i<200;i++){
		for(j=2;j<i;j++){
			if(i%j == 0){
				/*代表该数字i不是素数*/
				break;
			}
		}
		if(j==i){
			/*当j和i相等时,这个数就是素数*/
			System.out.print(i+" ");
		}
	}
}

  上面的实现方式,能输出正确的答案,但却存在着许多不必要的计算。这个不是只代码方面的漏洞,而是数学方面的知识,即除数的选择范围,从2-被除数开方即可。示例代码如下:

    private static void primeNumber(){
    	int j=0;
    	int k=0;
    	for(int i=101;i<200;i++){
    		k=(int)Math.sqrt((double)i+1);
    		for(j=2;j<=k;j++){
    			if(i%j == 0){
    				/*代表该数字i不是素数*/
    				break;
    			}
    		}
    		if(j==(k+1)){
    			/*当j和i相等时,这个数就是素数*/
    			System.out.print(i+" ");
    		}
    	}
    }

3、打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个 水仙花数 ,因为153=1的三次方+5的三次方+3的三次方。

  从题目可以看出,水仙花数是三位数,所以考虑的范围从101-999即可。之所以从101开始,是因为三位数的起始数字100明显不是水仙花数。该功能的实现比较简单,就是求出百、十、个位数上的数字,然后再进行相关运算,和原数字比较即可。示例代码如下:

    private static void narcissus(){
    	for(int i =101;i<1000;i++){
    		/*百位数字*/
    		int hundredNum=i/100;
    		/*十位数字*/
    		int tenNum=i/10%10;
    		/*个位数字*/
    		int oneNum=i%10;
    		if(i == hundredNum*hundredNum*hundredNum+tenNum*tenNum*tenNum+oneNum*oneNum*oneNum){
    			System.out.println(i+" ");
    		}
    	}
    }

4、将一个正整数分解质因数。例如:输入90,打印出90=2 *3 *3 *5。

  该问题中,被除数固定,除数从2到自身(到自身是因为要考虑质数的存在),然后逐个除以每个除数,当余数不为0时,除数自增,这就是大致的解题思路。示例代码如下:

    private static void decompose(int num){
    	for(int i=2;i<=num;){
           if(i==num){
        	   /*当num和k相等的时候,代表已经分解到了被除数自身,输出n的值,结束循环*/
        	   System.out.println(num);
        	   break;
           }else if(num%i==0){
               System.out.print(i+"*");
               /*n除以i的商,作为新的正整数num,继续分解*/
               num = num/i;
           }else{
        	   /*如果num不能被i整除,则用i+1作为i的值*/
        	   i++;
           }
    	}
    }

  同时,很多能用循环解决的问题,用递归也能解决,本问题也不例外,只是将被除数/i的时候,调用自身方法即可。示例代码如下:

    private static void decompose(int num){
    	for(int i=2;i<=num;i++){
    		if(i==num){
    			/*当num和k相等的时候,代表已经分解到了被除数自身,输出n的值,结束循环*/
    			System.out.println(num);
    			break;
    		}else if(num%i==0){
        	   /*如果num != i,但n能被i整除,则应打印出i的值*/
    			System.out.print(i+"*");
    			/*n除以i的商,作为新的正整数num,继续分解*/
    			decompose(num/i);
    			break;
    		}
    	}
    }

5、利用条件运算符的嵌套来完成此题:学习成绩> =90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。

  Java中的条件运算符,也就是三元运算符,语法形式为: 布尔表达式 ? 表达式1 :表达式2,如果布尔表达式的值为 true ,则返回表达式1 的值,否则返回 表达式2 的值。从这个例子就可以看出,三元运算符其实可以看做if语句的一种简写,理解了这个,这个题目的实现就简单了。示例代码如下:

    private static void getGradeLevel(int grade){
    	System.out.println("该成绩对应的等级为:"+(grade>=90?'A':(grade>=60?'B':'C')));
    }

6、输入两个正整数m和n,求其最大公约数和最小公倍数。

  该问题的求解思路是先求最大公约数,假设数字m和n的最大公约数是a,则最小公倍数可以通过m*m/a来求出。对于最大公约数的求解,常用的辗转相除法。具体思路为:用两个数中的较大数除以较小的数,求出一个余数,然后将余数赋值给较小的数,将原来较小的数,赋值给较大的数,知道较小的数变成0为止,此时较大的数就是最大公约数。示例代码如下:

    private static int commonDivisor(int bigNum,int smallNum){
    	/*假设m为较大的数,n为较小的数,此处不再进行参数校验*/
    	while(smallNum!=0){
    		int temp=smallNum;
    		/*将此轮相除的余数作为下一轮的较小值*/
    		smallNum=bigNum%smallNum;
    		/*此轮的较小值作为下一轮的较大值*/
    		bigNum=temp;
    		
    	}
    	return bigNum;
    }

7、输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。

  该问题的思路是将一个字符串拆分,然后判断拆分后的字符是属于哪个类别,在判断哪个类别时,有几种常用的方式:用ASCII码比较、字符比较和使用正则表达式进行匹配。本质上前两种方式是一样的,所以可简单认为有两种方式实现该功能。
  第一种是使用ASCII码值进行比较,ASCII码本质上来说是一种数字表示字符的办法,如下:
    
  该实现方式,直接与对应的ASCII码值区间比较,如判断某个字符是否属于数字,直接与数字0和数字9比较就行。示例代码如下:

	private static void judgeStr(String string){
		int number = 0,letter = 0,space = 0,other = 0;
	    char[] chars=string.toCharArray();
	    for (char c:chars){
	    	/*1:直接字符比较*/
	        //if ('0'<=c&&c<='9'){
	        //    number++;
	        //}else if (('a'<=c&&c<='z')||('A'<=c&&c<'Z')){
	        //    letter++;
	        //}else if (' '==c){
	        //    space++;
	        //}else {
	        //    other++;
	        //}
	    	/*2:使用ASCII码值进行比较*/
	        if (48<=c&&c<=57){
            	number++;
	        }else if ((97<=c&&c<=122)||(65<=c&&c<90)){
	        	letter++;
	        }else if (32==c){
	        	space++;
	        }else {
	        	other++;
	        }
	    }
	    System.out.print("字符个数:"+letter+" 空格个数:"+space+" 数字个数:"+number+" 其他个数:"+other);
	}

  第二种方式是使用正则表达式来匹配,这种方式在正式算法中用的也较多,因为在判断某个字符串是否合法等方面,使用正则表达式比直接字符比较方便的多。正则表达式使用时,需要定义一个匹配规则,如接下来的"[a-zA-Z]",表示的意思是从小写字母a到和小写字母z的集合与从大写字母A到和大写字母Z的集合的并集,即所有字母,然后再用一个字符串str去匹配这个规则,如果能匹配上,则返回true,否则返回false。示例代码如下:

	private static void judgeStr(String string){
		int number = 0,letter = 0,space = 0,other = 0;
		/*字母*/
        String expression1 = "[a-zA-Z]";
        /*数字*/
        String expression2 = "[0-9]";
        /*空格*/
        String expression3 = "\\s";
        String[] strings=string.split("");
        for(String s:strings){
            if (s.matches(expression1)){
                letter++;
            }else if (s.matches(expression2)){
                number++;
            }else if (s.matches(expression3)){
                space++;
            }else {
                other++;
            }
        }
        System.out.println("字符个数:"+letter+" 空格个数:"+space+" 数字个数:"+number+" 其他个数:"+other);
	}

8、求s=a+aa+aaa+aaaa+aa…a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制。

  此问题的关键在于第n个数怎么计算,计算出第n个数后,直接与前面的数累加就行。第n个数的求解也不难,就是前一个数字*10,再加上自身,然后累加1到n,即可求出答案。示例代码如下:

	/*exp:每个位数上的数字,即例子中的a;num代表求多少个数字的和*/
	private static int sum(int exp,int num){
		int sum = exp;
		int temp = exp;
		for(int i=1;i<num;i++){
			temp = temp*10;
			/*第i趟,temp就是该趟中第i+1个数字的值*/
			temp = temp+exp;
			/*此时的总和等于前面的值加上第i+1个数字的值*/
			sum = sum+temp;
		}
		return sum;
	}

9、一个数如果恰好等于它的因子之和,这个数就称为 "完数 "。例如6=1+2+3.编程 找出1000以内的所有完数。

  此问题的求解也比较容易理解,就是通过相除求余,然后将当余数等于0时,所有的除数相加,与原来的被除数比较即可。示例代码如下:

	private static void completeNum(){
		for(int i=2;i<1000;i++){
			int sum=0;
			for(int j=1;j<i;j++){
				if(i%j == 0){
					sum=sum+j;
				}
			}
			if(sum==i)
				System.out.print(sum+" ");
		}
	}

10、一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?

  对于该问题的求解,可以采用以下思路:将每次下落–>弹起当做一个阶段,这样考虑的话,第10次落地时经过的总距离就是前九个阶段的距离和+第十次下落的距离。第十次反弹的距离等于第十次下落距离的一半。所以在实现该功能时,至少需要两个变量:总距离和,每次下落/弹起的距离。示例代码如下:

	private static void fall(int num){
		/*下落的总距离*/
		int sum=0;
		/*每次下落的高度*/
		int high=100;
		for(int i=1;i<=num;i++){
			sum=sum+high;
			high=high/2;
		}
		System.out.println("第"+num+"次下落时的总距离:"+sum);
		System.out.println("第"+num+"次下落后反弹的高度:"+high);
	}

11、有1、2、3、4四个数字,能组成多少个互不相同且一个数字中无重复数字的三位数?并把他们都输入。

  该问题主要考察for循环的使用,其解决思路是对百、十、个位,分别生成1-4的数字,然后在组成数字时判断一下,去除不同位数上相等数字的情况。示例代码如下:

	private static int generateNum(){
		int count=0;
		for(int i=1;i<5;i++){
			for(int j=1;j<5;j++){
				for(int k=1;k<5;k++){
				    /*判断百、十、个位上的数字均不相等*/
					if(i!=j && j!=k && k!=i){
						count++;
						System.out.println(i*100+j*10+k);
					}
				}
			}
		}
		return count;
	}

12、企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润,求应发放奖金总数?

  该问题主要考察多重if语句的使用,其解决思路是对输入的利润进行判断,将利润划分到不同的区间,这样不同的区间会计算出不同的奖金,将这些不同区间的奖金加起来,就是最后的奖金总额。示例代码如下:

	private static double profit(double num){ 
		double result=0.0;
		if(num<=10){
			result=num*0.1;
		}else if(num<=20){
			result=10*0.1+(num-10)*0.75;
		}else if(num<=40){
			result=10*0.1+10*0.75+(num-20)*0.05;
		}else if(num<=60){
			result=10*0.1+10*0.75+20*0.05+(num-40)*0.03;
		}else if(num<100){
			result=10*0.1+10*0.75+20*0.05+20*0.03+(num-60)*0.015;
		}else{
			result=10*0.1+10*0.75+20*0.05+20*0.03+40*0.015+(num-100)*0.01;
		}
		return result;
	}

13、一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

  要解此问题,需要了解什么是完全平方数,完全平方数指的是一个数可以由某个数字的平方计算得到。解该问题需要考虑两个方面的问题:
   1>怎么保证这个数字能够完全开方?在Math中有和方法sqrt是求某个数的开方的,当某个数的开方%1结果为0时,其实就代表了这个数字是个整数。
   2>结果的取值范围,该题并没有指定结果一定要是正整数,所以有可能不是正整数,直观上来看,我们可以从-100开始,进行遍历计算。
  示例代码如下:

	private static void printNum(){
		for(int i=-100;i<10000;i++){
			if((Math.sqrt(i+100)%1 == 0)
					&& Math.sqrt(i+100+168)%1 == 0){
				System.out.println(i+" ");
			}
		}
	}

14、输入某年某月某日,判断这一天是这一年的第几天?

  这道题目其实也是在考查多重条件下的编程能力,不过此题中的多重条件月份是整数,此时就可以使用switch…case…来替换if语句。具体到此题,有两种解法:
   1>将每月的之前的月份的所有日期进行累加,这样最后再加上当月的天数,就能求出最终答案。示例代码如下:

	private static int dayNum(int year,int month,int day){
		int result=0;
		switch(month){
			case 1:
				result=0;
				break;
			case 2:
				result=31;
				break;
			case 3:
				result=59;
				break;
			case 4:
				result=90;
				break;
			case 5:
				result=120;
				break;
			case 6:
				result=151;
				break;
			case 7:
				result=181;
				break;
			case 8:
				result=212;
				break;
			case 9:
				result=243;
				break;
			case 10:
				result=273;
				break;
			case 11:
				result=304;
				break;
			case 12:
				result=334;
				break;
		}
		/*如果是闰年,则2月是29天,需要在原来默认的28天基础上+1*/
		if((year%4==0 && year%100!=0) || year%400==0){
			if(month>=3){
				result++;
			}
		}
		/*再加上当月的天数*/
		result=result+day;
		return result;
	}

   2>上一种写法能实现功能,但是却不够好,因为需要计算出月份累加后的天数,这种较为复杂的计算尽量扔给计算机进行实现就行,因此,就有了第二种实现方式。就是我们给出每个月的天数,让程序自动累加。示例代码如下:

	private static int dayNum(int year,int month,int day){
		int result=0;
		int monthDay=0;
		for(int i=1;i<=month;i++){
			switch(month){
				case 1:
				case 3:
				case 5:			
				case 7:
				case 8:
				case 10:
				case 12:
					monthDay=31;
					break;		
				case 2:
					monthDay=28;
					break;
				case 4:
				case 6:
				case 9:
				case 11:
					monthDay=30;
					break;
	
			}
			result=result+monthDay;
		}
		
		/*如果是闰年,则2月是29天*/
		if((year%4==0 && year%100!=0) || year%400==0){
			if(month>=3){
				result++;
			}
		}
		/*再加上当月的天数*/
		result=result+day;
		return result;
	}

15、输入三个整数x,y,z,请把这三个数由小到大输出。

  此处考察的是排序逻辑(暂不考虑线性排序算法),最容易想到的就是需要比较两趟的挨个排序,也就是冒泡排序。第一趟比较时将最大的值放在最后一位,第二趟比较时将最小值放在第一位,排序就完成了。因为这三个数组不是在一个序列(数组或链表中),所以就不用常见的双层for循环来完成该题目,直接用几个if语句来实现就行,如果元素过多的话,就需要考虑双层for循环了。示例代码如下:

	private static void sort(int x,int y,int z){
		int temp=0;
		if(x>y){
			temp=x;
			x=y;
			y=temp;
		}
		if(y>z){
			temp=y;
			y=z;
			z=temp;
		}
		/*程序运行到此处,最大值已经处于z位置*/
		if(x>y){
			temp=x;
			x=y;
			y=temp;
		}
		System.out.println("排列后的三个数是:"+x+","+y+","+z);
	}

16、输出9*9口诀。

  该题考的是双层for循环的使用,也就是当一个题目中有两个相关的变量,且需要进行自增、自减等遍历操作时,往往用双层for循环来解决问题。在此题中,外层for循环时前一个乘数,内层for循环是第二个乘数。示例代码如下:

		for(int i=1;i<=9;i++){
			for(int j=1;j<=i;j++){
				System.out.print(i+"*"+j+"="+i*j+" ");
			}
			System.out.println();
		}
	}

17、猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。

  该题目考的是同样变化条件下的处理,该类问题一般有递归和非递归两种处理方式, 该题目比较简单,就用非递归的方式实现,从题目可以看出,循环体总共执行了9次,也就是需要创建一个能执行9次的for循环。示例代码如下:

	private static int countNum(){
		int num=1;
		for(int i=10;i>1;i--){
			num=(num+1)*2;
		}
		return num;
	}

18、两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。

  该题考的是如何在for循环中,正确地使用条件判断。此题的判断条件有如下几个,在for循环中进行规避即可:
   1>a不和z比。
   2>当c不和x、z比,隐含的条件是:c只能和y比,所以a、b都不能和y比。
   3>这个条件是隐含最深的条件,需要对每个安排过赛程的人,进行重复性判断,不让一个人和多个人比。
  示例代码如下:

	private static void printList(){
		char[] teamA={'a','b','c'};
		char[] teamB={'x','y','z'};
		char tempA='d';
		char tempB='d';
		
		for(int i=0;i<teamA.length;i++){
			for(int j=0;j<teamB.length;j++){
				/*题目要求:a不和z比*/
				if(teamA[i]=='a' && teamB[j]=='x'){
					continue;
				/*题目要求:c不和x、z比*/
				}else if((teamA[i]=='c' && teamB[j]=='x') || (teamA[i]=='c' && teamB[j]=='z')){
					continue;
				/*题目要求:当c不和x、z比时,只能和y比,所以a、b都不能和y比*/
				}else if((teamA[i]=='a' && teamB[j]=='y') || (teamA[i]=='b' && teamB[j]=='y')){
					continue;
				}else{
					/*此处是为了防止出现一个人重复和多人比的情况*/
					if(tempA!=teamA[i] || tempB==teamB[j]){
					    System.out.println(teamA[i]+" VS "+teamB[j]);
					    tempA=teamA[i];
					    tempB=teamB[j];
					}
				}
			}
		}
	}

19、打印出如下图案(菱形)。

  该题目依然在考双层for循环的使用,在使用双层for循环时,一般外层循环变量控制次数/趟数,内层循环控制具体的业务逻辑。本题也是一样的,将7层图形分成4和3两部分,所以用了两个外层for循环,在内层for循环的处理上,有不同的方式。
   1>在前4层,每层的图形分为三个部分,*前面的空格、后面的空格。在第一层,*前面的空格有三个,和次数的关系是4-i,为1个,和次数的关系是2n-1,*后面的空格,直接随循环输出即可,所以前4层示例代码:

		/*打印出前4行*/
		for(i=1;i<=4;i++){
			/*打印出每排*前面的空格*/
			for(int k=1; k<=4-i;k++)
				System.out.print(" ");
			/*打印出每排中间的*/
			for(j=1;j<=2*i-1;j++)
				System.out.print("*");
			/*打印出每排*后面的空格*/
			System.out.println("");
		}

    后3层的处理也是类似,分别找出每层中三部分与次数的关系,不再赘述,示例代码如下:

		for(i=4;i>=1;i--){
			for(int k=1; k<=5-i;k++)
				System.out.print(" ");
			for(j=1;j<=2*i-3;j++)
				System.out.print("*");
			System.out.println("");
		}

   2>变换循环的起始数字,也能达到输出该图形的效果,只要保证每层三个部分内容的正常打印就行。示例代码如下:

    	/*高和宽必须是相等的奇数*/
        int H = 7, W = 7;
        for(int i=0; i<(H+1)/2; i++){
        	for(int j=0; j<W/2-i; j++) 
        		System.out.print(" ");
        	for(int k=1; k<(i+1)*2; k++)
        		System.out.print('*');
        	System.out.println();
        }
        for(int i=1; i<=H/2; i++) {
        	for(int j=1; j<=i; j++)
        		System.out.print(" ");
        	for(int k=1; k<=W-2*i; k++)
        		System.out.print('*');
        	System.out.println();
        }

20、有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13…求出这个数列的前20项之和。

  该问题和问题10有些相似,都是在每次循环中先求出一个数,在求出总和或总积,做这类题时,单个的数好球,要注意的是起始变量和循环次数的控制(即边界)。从该数列可以看出,每个数后一个数的分母是前一个数的分母和分子相加,由此就可以求出前二十个数,进而求出他们的和。示例代码如下:

    private static double sum(int num){
    	double sum=0.0;
    	int num1=1;
    	int num2=2;
    	int tempNum=0;
    	for(int i=1;i<=20;i++){
    	    /*这里要注意,num2/num1后要转换成double类型,要不默认是int型,造成计算结果变小*/
    		sum=sum+(double)num2/num1;
    		tempNum=num2;
    		num2=num2+num1;
    		num1=tempNum;
    	}
    	return sum;
    }

21、求1+2!+3!+…+20!的和。

  该题和之前的有些题相似,都是在每次循环时,求出一个数,然后求他们的和或积。示例代码如下:

	private static int sum(int num){
		int sum=0;
		int temp=1;
		for(int i=1;i<=20;i++){
			temp=temp*i;
			sum=sum+temp;
		}
		return sum;
	}

22、利用递归方法求5!。

  这道题和前一道题类似,不过要求用递归完成。使用递归也不难,因为在上道题的解法中有个在循环中反复使用乘法和加法的操作,把这些在for循环中重复的操作拿出来,放到一个方法中,每次调用一下就是递归。示例代码如下:

	private static int multi(int num){
		int result=1;
		if(num==1){
			return result;
		}else{
			result=num*multi(num-1);
		}
		return result;
	}

23、有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大?

  这道题和之前的猴子吃桃问题如出一辙,需要使用循环或递归的方式求解。在该题中,最后的10就是循环的初始条件,接下来只要找出循环的次数或停止递归的条件(边界条件)即可。循环方式示例代码如下:

	private static int age(int num){
		int result=10;
		for(int i=1;i<num;i++){
			result=result+2;
		}
		return result;
	}

  递归方式实现如下:

	private static int age(int num){
		int result=10;
		if(num==1){
			return result;
		}else{
			result=age(num-1)+2;
		}
		return result;
	}

24、给一个不多于5位的正整数,要求:一、求它是几位数,二、逆序打印出各位数字。

  该问题有两个要求,需要先解第一问,才能做第二问。要解第一问,有不同的做法,将数字转换为字符数组,该问题第一问和第二问都会较简单的解决。示例代码如下:

	private static int digitCapacity(int num){
		char[] ch=String.valueOf(num).toCharArray();
		return ch.length;
	}
	
	private static void print(int num){
		char[] ch=String.valueOf(num).toCharArray();
		for(int i=ch.length-1;i>=0;i--){
			System.out.print(ch[i]);
		}
	}

  当然,在判断数字位数功能的实现上,也可以使用简单的if…else来实现。示例代码如下:

	private static int digitCapacity(int num){
		int result=0;
		if(num>=0 && num<=9){
			result=1;
		}else if(num>=10 && num<=99){
			result=2;
		}else if(num>=100 && num<=999){
			result=3;
		}else if(num>=1000 && num<=9999){
			result=4;
		}else if(num>=10000 && num<=99999){
			result=5;
		}
		return result;
	}

  不使用char数组,纯用数字的方式,也可以实现逆序输出功能。示例代码如下:

	private static void print(int num){
		int length=digitCapacity(num);
		System.out.println(num%((int)Math.pow(10, length)));
	}

25、一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。

  该题目类似前一道题,也有使用char数组和直接运算两种做法。使用char数组的话,直接比较对应位置上的数字即可。示例代码如下:

	private static boolean isHuiwen(int num){
		if((num<10000 || num>99999)){
			System.out.println("输入的数字不是五位数,请重新输入");
			return false;
		}
		char[] ch=String.valueOf(num).toCharArray();
		if(ch[0]==ch[4] &&ch[1]==ch[3])
			return true;
		return false;
	}

  直接运算的方式,是求出万、千、十、个位置上对应的数字,然后比较即可。示例代码如下:

	private static boolean isHuiwen(int num){
		if((num<10000 || num>99999)){
			System.out.println("输入的数字不是五位数,请重新输入");
			return false;
		}
		/*个位上的数字*/
		int num1=num%10;
		/*十位上的数字*/
		int num2=num%100/10;
		/*百位上的数字*/
		int num3=num%1000/100;
		/*千位上的数字*/
		int num4=num%10000/1000;
		/*万位上的数字*/
		int num5=num/10000;
		
		if(num1==num5 && num2==num4)
			return true;
		return false;
	}

  同时,可以将这道题延伸为不限位数。此时,转换为数组的方式就比较方便了,具体的做法是:将数字转换为char数组,然后比较对应位置上的数字。示例代码如下:

	private static boolean isHuiwen(int num){
		if((num<10000 || num>99999)){
			System.out.println("输入的数字不是五位数,请重新输入");
			return false;
		}
		char[] ch=String.valueOf(num).toCharArray();
		for(int i=0;i<ch.length;i++){
			if(ch[i]!=ch[ch.length-1-i]){
				return false;
			}
		}
		return true;
	}
;