控制台输出螺旋型数字

先上最终效果图

 

 

对输入的指定数组规模做一个螺旋型的数字输出:

假设输入3,输出如下:

1  2  3

8  9  4

7  6  5

 

 

按照这种顺序进行。

 

实现代码如下:

 1 #include <iostream>
 2 #include<iomanip>
 3 using namespace std;
 4 
 5 void inputGrid(int n,int *m)
 6 {//n表示规模,m为二维数组指针
 7     int row=0,line=0,flag=0;//row,line表示第几次行处理或列处理;
 8     int i=0,j=-1;
 9     for(int num=1;num<=n*n;)
10     {
11         if(!flag)
12         {
13             //行处理
14             int addnum;
15             if(row%2==0)addnum=1;//往前走
16             else addnum=-1;//往回走
17             int num_row=n-row;
18             while(num_row)
19             {//将本行剩余空白列全部填满
20                 num_row--;
21                 j+=addnum;
22                 *(m+n*i+j)=num;
23                 num++;
24             }
25             row++;
26             flag=1;
27 
28         }
29         else
30         {
31             //列处理
32             int addnum;
33             if(line%2==0)addnum=1;//往前走
34             else addnum=-1;//往回走
35             int num_line=n-line-1;
36             while(num_line)
37             {//将本列剩余空白项全部填满
38                 num_line--;
39                 i+=addnum;
40                 *(m+n*i+j)=num;
41                 num++;
42             }
43             line++;
44             flag=0;
45         }
46     }
47     /*for(int i=0;i<n*n;i++)
48     {
49         *(m+i)=i;
50     }*/
51 }
52 
53 int main()
54 {
55     int n=1;
56     int *m,*tm;
57     while(n!=-1)
58     {
59     cout<<"请输入回形数规模:(输入-1退出)";
60     cin>>n;
61     if(n==-1)
62         return 0;
63     m=(int *)malloc(n*n*sizeof(int));
64     inputGrid(n,m);
65     for(int i=0;i<n;i++)
66     {
67         tm=m+n*i;
68         for(int j=0;j<n;j++)
69         {
70             cout<<setw(3)<<*(tm+j)<<" ";
71         }
72         cout<<"\n";
73     }
74     }
75     //return 0;
76 }

 

 

posted @ 2010-03-11 01:48 elite_lcf 阅读(2126) 评论(22) 编辑 收藏

 回复 引用 查看   
#1楼[楼主] 2010-03-11 01:55 elite_lcf      
今天一个面试题,想了想,从被窝里爬起来写完它
坐了板凳,继续睡觉去

 回复 引用 查看   
#2楼 2010-03-11 08:08 温景良(Jason)      
牛啊
 回复 引用 查看   
#3楼 2010-03-11 08:54 徐少侠      
国家计算机等级考试里有的

不过最牛逼的做法是通过观察奇数和偶数矩阵的排列
找出规律

然后只要一个两重循环加上几个判定边界的语句就可以了
这个思路是我专利哦
网络上找不到实现代码的

 回复 引用 查看   
#4楼 2010-03-11 09:02 killkill      
移动光标,再打印.......
 回复 引用 查看   
#5楼 2010-03-11 09:38 liy      
实现出来简单,只是一个算法复杂度的问题,是谁的算法最好

 回复 引用 查看   
#6楼 2010-03-11 11:18 AutumnWinter      
时间复杂度应该不会小于O(n^2)
 回复 引用 查看   
#7楼 2010-03-11 11:31 Alexis      
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入回行数的规模(-1:退出)");

            int number = int.Parse(Console.ReadLine());

            if (number == -1)//退出
            {

            }
            else
            {
                huixing(number);
            }
        }

        //生成回形数
        static void huixing(int number)
        {
            int[,] temp = new int[number, number];
            /*赋值回形数*/
            int col = 0, row = 0;
            int num = 1;
            int count;
            int tempRow;


            /* 

            按照顺时针的方式赋值数组 
            */

            for (int i = number; i >= 0; i = i - 2)
            {
                tempRow = row;
                count = 0;
                col = row;
                //i代表每行要赋值的个数 
                while (count < i)
                {
                    temp[row,col] = num;
                    count++;
                    num++;
                    col++;
                }
                col--;
                for (row++; row <= col; row++)
                {
                    temp[row,col] = num;
                    num++;
                }
                row--;
                for (col--; col >= tempRow; col--)
                {
                    temp[row,col] = num;
                    num++;
                }
                col++;
                for (row--; row > tempRow; row--)
                {

                    temp[row,col] = num;
                    num++;
                }
                row = tempRow;
                row++;
            }

            //output
            for (int i = 0; i < number; i++)
            {
                for (int j = 0; j < number; j++)
                {
                    Console.Write("{0,5}",temp[i, j]);
                    if (j == number - 1)
                        Console.WriteLine();
                }

            }
        }

    }
}


 回复 引用 查看   
#8楼 2010-03-11 11:33 Alexis      
刚刚那个是C#实现
 回复 引用 查看   
#9楼 2010-03-11 14:28 AutumnWinter      
C++实现
#include <iostream>
#include <iomanip>
using namespace std ;

void SpiralNum(int n)
{
	// Dynamic allocate a 2-d array to store the numbers
	int **a = new int*[n] ;
	for(int m = 0; m < n; m++)
	{
		a[m] = new int[n] ;
	}

	// Initilize all elements to -1
	for(int m = 0; m < n; m++)
	{
		for(int k = 0; k < n; k++)
		{
			a[m][k] = -1 ;
		}
	}

	// number to fill in
	int num = 1 ;

	// direction control flag
	// 1: left -> right
	// 2: up -> down
	// 3: right -> left
	// 4: down -> up
	int flag = 1 ;

	// array index
	int i = 0; 
	int j = 0 ;

	// fill in the array
	while(true)
	{
		// All numbers fill in?
		if(num > n * n)
			break ;

		// Only fill in when current position was not fill in yet
		if(a[i][j] == -1)
			a[i][j] = num++ ;
		
		// left -> right
		if(flag == 1)
		{
			j++ ;
			if(a[i][j] != -1)
			{
				j-- ;
				flag = 2 ;
			}
		}

		// up -> down
		if(flag == 2)
		{
			i++ ;
			if(i == n || a[i][j] != -1)
			{
				i-- ;
				flag = 3 ;
			}
		}

		// right -> left
		if(flag == 3)
		{
			j-- ;
			if(j == -1 || a[i][j] != -1)
			{
				j++ ;
				flag = 4 ;
			}
		}

		// down -> up
		if(flag == 4)
		{
			i-- ;
			if(a[i][j] != -1)
			{
				i++ ;
				flag = 1 ;
			}
		}
	}

	// Output the array
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
		{
			cout << right << setw(3) << a[i][j] << " " ;
		}
		cout << endl ;
	}
}

 回复 引用 查看   
#10楼 2010-03-11 16:11 徐少侠      
引用AutumnWinter:时间复杂度应该不会小于O(n^2)


10边长的矩阵,100个元素
n=10

最高效的做法是只要循环100次,每个坐标的值直接根据公式计算就可以了

 回复 引用 查看   
#11楼 2010-03-11 16:21 徐少侠      
当然,如果O(n)里面这个N就是那个10的意思么,的确是O(n^2)了
 回复 引用 查看   
#12楼 2010-03-11 16:26 徐少侠      
上面的实现都需要初始化数组内容
浪费了点时间

 回复 引用 查看   
#13楼 2010-03-11 18:00 福州小熊      
C#版本

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int input = 1;
            while (input > 0)
            {
                Console.Write("请输入大于1的数字,否则退出:");
                input = Convert.ToInt32(Console.ReadLine());
                Console.WriteLine();
                int[,] groups = SetGroups(input);
                for (int i = 0; i < input; i++)
                {
                    for (int j = 0; j < input; j++)
                    {
                        Console.Write(groups[i, j] + "\t");
                    }
                    Console.WriteLine();
                }
                Console.WriteLine();
            }
            Console.WriteLine("退出程序成功,按任意键关闭!");
            Console.ReadLine();
        }

        static int[,] SetGroups(int Size)
        {
            int[,] Groups = new int[Size,Size];
            int max = Size - 1;
            int rowIndex = 0;//行编号
            int colIndex = 0;//列编号
            int count = Size * Size;
            int type = 1;//右开始
            //bool colCheck = true;//判断列是否到最大值
            for (int index = 1; index <= count; index++)
            {
                Groups[rowIndex,colIndex] = index;
                switch (type)
                {
                    case 1:
                        if (colIndex == max || Groups[rowIndex, colIndex + 1] != 0)
                        {
                            type++;
                            rowIndex++;
                        }
                        else
                            colIndex++;
                        break;
                    case 2:

                        if (rowIndex == max || Groups[rowIndex + 1, colIndex] != 0)
                        {
                            type++;
                            colIndex--;
                        }
                        else
                            rowIndex++;
                        break;
                    case 3:

                        if (colIndex == 0 || Groups[rowIndex, colIndex - 1] != 0)
                        {
                            type++;
                            rowIndex--;
                        }
                        else
                            colIndex--;
                        break;
                    case 4:

                        if (rowIndex == max || Groups[rowIndex - 1, colIndex] != 0)
                        {
                            type = 1;
                            colIndex++;
                        }
                        else
                            rowIndex--;
                        break;
                }
            }
            return Groups;
        }
    }
}


 回复 引用 查看   
#15楼 2010-03-11 19:59 庄园      
Delphi版本的,循环次数大概等于X*Y

program Project21;

{$APPTYPE CONSOLE}

uses
  SysUtils;

procedure Draw(Size:Integer);
var
  Arr:Array of Array of Integer;
  Flag:(GoRight,GoButtom,GoLeft,GoTop);
  X,Y,N,Step,Rang:Integer;
  procedure Output;
  begin
    Inc(N);
    Arr[Y,X]:=N;
    Dec(Step);
  end;
begin
  N:=0; X:=0; Y:=0;
  Rang:=Size-1; Step:=Rang;
  SetLength(Arr,Size,Size);
  while N<Size*Size do begin
    case Flag of
      GoRight:
      begin
        if Step=0 then begin
          Step:=Rang;
          Flag:=GoButtom;
        end else begin
          Output;
          Inc(X);
        end;
      end;
      GoButtom:
      begin
        if Step=0 then begin
          Step:=Rang;
          Flag:=GoLeft;
        end else begin
          Output;
          Inc(Y);
        end;
      end;
      GoLeft:
      begin
        if Step=0 then begin
          Step:=Rang;
          Flag:=GoTop;
        end else begin
          Output;
          Dec(X);
        end;
      end;
      GoTop:
      begin
        if Step=0 then begin
          Dec(Rang,2);
          Step:=Rang;
          Flag:=GoRight;
          Inc(X);
          Inc(Y);
          if Rang<=0 then begin
            Output;
            Break;
          end;
        end else begin
          Output;
          Dec(Y);
        end;
      end;
    end;
  end;
  for Y := 0 to Size-1 do begin
    for X := 0 to Size-1 do
      Write(Format('%4d',[Arr[Y,X]]));
    Writeln('');
  end;
end;

var
  Size:String;
label
  Start;
begin
  try
    Start:
    Write('输入阵列的规模:');
    Readln(Size);
    Draw(StrToIntDef(Size,0));
    goto Start;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

 回复 引用 查看   
#16楼 2010-03-12 08:56 AutumnWinter      
引用徐少侠:
引用AutumnWinter:时间复杂度应该不会小于O(n^2)


10边长的矩阵,100个元素
n=10

最高效的做法是只要循环100次,每个坐标的值直接根据公式计算就可以了

这不就是O(n^2)么? 你说每个坐标值可以根据公式直接计算,能否给出代码看看?

 回复 引用 查看   
#17楼[楼主] 2010-03-12 11:14 elite_lcf      
@AutumnWinter
他的意思是用坐标法,每一圈的末尾数是n^2,根据这个可以把此圈剩下的全部推导出来。少侠兄,我说的可对?

 回复 引用 查看   
#18楼 2010-03-12 13:01 蒙奇Boy      
哈哈~这算法很有意思!
 回复 引用 查看   
#19楼 2010-03-12 13:22 非常笑      
小弟不才,有个这样的想法,如下:
1 2
4 3

1 2 3
8 9 4
7 6 5
其实有两个模板,如上。定义m:模板的规模数
不难看出,任意规模的回型矩阵最外面一圈我们可以算出来。形式如下:
1 。。。 m
。 。
。 。
。 。
(3m-2) 。。。 (2m-1)其中。。。为省略,皆可计算出来。
说到这里就清晰了,是个递归问题。
假设m为偶数6
初始化循环m/2(例子为3)次可以得到如下矩阵
1 2 3 4 5 6
20 1 2 3 4 7
19 12 1 2 5 8
18 11 4 3 6 9
17 10 9 8 7 10
16 15 14 13 12 11
应该没什么问题吧,然后就是(m/2-1)次循环,这里为2次。做什么呢?别着急。请注意两个粗体的1。从内到外,分别加上左边的那个数,这里详细的解释下:
第一次循环,我们要做的是最内层的1+12替换1,2+12替换2,以此类推,很容易算出如下矩阵
1 2 3 4 5 6
20 1 2 3 4 7
19 12 13 14 5 8
18 11 16 15 6 9
17 10 9 8 7 10
16 15 14 13 12 11
第二次循环,我要做的是将粗体1+20替换1,注意,是内层所有的值都要加上20这个值(包括上一个循环计算出来的值),这样便得到正确的矩阵
1 2 3 4 5 6
20 21 21 23 24 7
19 32 33 34 25 8
18 31 36 35 26 9
17 30 29 28 27 10
16 15 14 13 12 11

 回复 引用 查看   
#20楼 2010-03-12 16:16 AutumnWinter      
引用elite_lcf:
@AutumnWinter
他的意思是用坐标法,每一圈的末尾数是n^2,根据这个可以把此圈剩下的全部推导出来。少侠兄,我说的可对?

晕,每一圈末尾的数是n^2?想好了再说不迟。和没说一样:(怎么推导?

 回复 引用 查看   
#21楼 2010-03-12 16:18 AutumnWinter      
递归解:


void SpiralNum(int *a[], int startNum, int n, int x, int y)
{
	if(n <= 0)
		return ;
	else
	{
		int i = x;
		int j = y ;

		while(j < x + n)
			a[i][j++] = startNum++ ;
		j-- ;
		i++ ;

		while(i < y + n)
			a[i++][j] = startNum++ ;
		i-- ;
		j-- ;

		while(j >= x)
			a[i][j--] = startNum++ ;
		j++ ;
		i-- ;

		while(i >= y + 1)
			a[i--][j] = startNum++ ;
	}

	SpiralNum(a, startNum, n - 2, x + 1, y + 1) ;
}


int main(void)
{

	int n ;

	cout << "Input n: " << endl ;
	cin >> n ;

	// Dynamic allocate a 2-d array to store the numbers
	int **a = new int*[n] ;
	for(int m = 0; m < n; m++)
	{
		a[m] = new int[n] ;
	}

	SpiralNum(a, 1, n, 0, 0) ;

	// Output
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
		{
			cout << right << setw(3) << a[i][j] << "  " ;
		}
		cout << endl ;
	}
	cout << endl ;

	system("pause") ;
	return 0 ;
}

 回复 引用 查看   
#22楼 2010-03-13 14:49 冰玉之魂      
不错啊,学习下啦!
知识共享许可协议
本博客采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。