有趣的回字形数

今天群里的一个朋友出了一道有趣的题目(在此感谢“IT小农民”发布题目):

原文

 

33333
32223
32123
32223
33333

回字形数,打一下吧

 

注:他也好像是从CSDN某个博客上拿到的题目,不过我具体也没查证,我想实现这个算法应该不会遇到什么版权问题吧。如果本文发布有什么不合理的地方,请和我联系。

我给出两种解决方法:

第一种:

是我自己分析行特征得出的,设初始数为n(每行第一个数),一共有2n-1行,第i行的表示如下:

共有2n-1个数字

i行:  n n-1 ...n-i+1 n-i...... n-i+1 ...n-1 n

分析:1.前面n到n-i+1是i个从n递减的数列,中间有2n-1-2i个相同的n-1,最后是从n-i+1到n的递增数列。

            2.当i大于n是2n-1-2i为负,但当i大于n-1时,这行都是前面已经出现过的行,所以我把i=n行视作是第n-2行,i=n+1行视作是第n-3行,得到规律:当i大于n时,第i行相当于上面的第2n-2-i行。

 

根据上面两个关键关系,写出程序如下:

  1. package com.sunrise;
  2. import java.util.*;
  3. /**输出回形数
  4.  * 
  5.  * @author sunbin
  6.  * @version 0.0.1
  7.  */
  8. public class CircleFormNumber {
  9.     public static void main(String[] args){
  10.         System.out.println("请输入一个数字开始回形数运算,按回车结束输入");
  11.         //输入初始数,即每行的第一个数字
  12.         Scanner reader = new Scanner(System.in);
  13.         //获得初始数
  14.         int beginNumber = reader.nextInt();
  15.         //parallelNum 一行输出中,中间重复数字的个数
  16.         int parallelNum = 0;
  17.         //算法开始执行的时间
  18.         Long beginMillis = System.currentTimeMillis();
  19.         //计算输出的总行数
  20.         int totalLines = 2*beginNumber - 1;
  21.         //--算法部分--
  22.         //从地0行开始,一共有totalLines行(totalLines = 2*beginNumber - 1),也有totalLines列
  23.         for(int i = 0; i < totalLines; i++){
  24.             if(i < beginNumber){
  25.                 //当行数小于初始数时,totalLines - 2 * i是正值
  26.                 parallelNum = totalLines - 2 * i;
  27.                 //一行一行地输出,j表示第j个位置上的数
  28.                 for(int j = 0; j < totalLines; j++){            
  29.                     //当j
  30.                     if(j < i){
  31.                         System.out.print(beginNumber - j);
  32.                     }
  33.                     //当j > i - 1 && j < i + parallelNum的时候,重复输出该行最小值
  34.                     else if(j > i - 1 && j < i + parallelNum){
  35.                         System.out.print(beginNumber - i); 
  36.                     }
  37.                     //当j > i + parallelNum - 1 && j < totalLines的时候,输出递增1的数值
  38.                     else if(j > i + parallelNum - 1 && j < totalLines){
  39.                         System.out.print(j - beginNumber + 2);
  40.                     }
  41.                 }
  42.             }
  43.             else{
  44.                 //当行数大于初始数时,将该行转换为上面对应输出相同的行。如地i行的对应行数k为:k = 2 * beginNumber - 2 - i
  45.                 int k = 2 * beginNumber - 2 - i;
  46.                 //重新计算一行输出中,中间重复数字的个数
  47.                 parallelNum = totalLines - 2 * k;
  48.                 //一行一行地输出,j表示第j个位置上的数
  49.                 for(int j = 0; j < totalLines; j++){    
  50.                     //当j
  51.                     if(j < k){
  52.                         System.out.print(beginNumber - j);
  53.                     }
  54.                     //当j > k - 1 && j < k + parallelNum的时候,重复输出该行最小值
  55.                     else if(j > k - 1 && j < k + parallelNum){
  56.                         System.out.print(beginNumber - k); 
  57.                     }
  58.                     //当j > k + parallelNum - 1 && j < totalLines的时候,输出递增1的数值
  59.                     else if(j > k + parallelNum - 1 && j < totalLines){
  60.                         System.out.print(j - beginNumber + 2);
  61.                     }
  62.                 }
  63.             }
  64.             //换下一行输出
  65.             System.out.println();
  66.         }
  67.         //算法结束执行时间
  68.         Long endMillis = System.currentTimeMillis();
  69.         //算法消耗时间
  70.         long executeTime = endMillis - beginMillis;
  71.         //打印算法消耗时间
  72.         System.out.println("算法从开始执行到结束共用了 " + executeTime + "毫秒");
  73.     }
  74. }

执行结果:

  1. 请输入一个数字开始回形数运算,按回车结束输入
  2. 5
  3. 555555555
  4. 544444445
  5. 543333345
  6. 543222345
  7. 543212345
  8. 543222345
  9. 543333345
  10. 544444445
  11. 555555555
  12. 算法从开始执行到结束共用了 15毫秒

 

第二种方法算法要简单一些,容易理解,不过效率要低一些:

设想如下:

一圈一圈地生成,而不是一行一行的生成,将生成的值付给二维数组int[][] array。

比如3
得到一个三角矩阵

3 3 3 3 3
3 0 0 0 0
3 0 0 0 0
3 0 0 0 0
3 0 0 0 0
将三角矩阵映射到下班部分:
得到结果:
3 3 3 3 3
3 0 0 0 3
3 0 0 0 3
3 0 0 0 3
3 3 3 3 3
这样就完成了一圈,然后采用递归调用,将圈缩小一圈就可以了。
思路清晰,缺点是效率不是很高。

代码实现如下:

  1. package com.sunrise;
  2. import java.util.Scanner;
  3. class CircleNumber1 {
  4.     
  5.     //num代表一共几圈,n代表当前第几圈
  6.     
  7.     void f(int num,int n,int[][] array,int length){
  8.         for(int i=n;i
  9.             array[n][i] = num;
  10.             array[i][n] = num;
  11.             array[length - 1][i] = num;
  12.             array[i][length - 1] = num;
  13.         }
  14.         if(num>0){
  15.             f(num-1,n+1,array,length-1);
  16.         }else{
  17.             printArr(array);
  18.         }
  19.     }
  20.     void printArr(int[][] array){
  21.         for (int i = 0; i < array.length; i++) {
  22.             for (int j = 0; j < array[i].length; j++) {
  23.                 System.out.print(array[i][j]+"  ");
  24.             }
  25.             System.out.println();
  26.         }
  27.     }
  28.     public static void main(String[] args) {
  29.         CircleNumber1 t=new CircleNumber1();
  30.         System.out.print("请输入一个整数:");
  31.         Scanner scn=new Scanner(System.in);
  32.         int num=0;
  33.         num=scn.nextInt();
  34.         int[][] array=new int[2*num-1][2*num-1];
  35.         int length=array.length;
  36.         t.f(num,0, array,length);
  37.     }
  38. }

运行结果如下:

  1. 请输入一个整数:4
  2. 4  4  4  4  4  4  4  
  3. 4  3  3  3  3  3  4  
  4. 4  3  2  2  2  3  4  
  5. 4  3  2  1  2  3  4  
  6. 4  3  2  2  2  3  4  
  7. 4  3  3  3  3  3  4  
  8. 4  4  4  4  4  4  4  

这是道挺有意思的小题目,群里出题的朋友说是在CSDN博客上看到的,希望原作者看到的话指出算法以及程序中的缺点,错误,和有待改进的地方。

你可能感兴趣的:(J2SE技术探讨)