面试例题:输入n,求一个n x n矩阵,规定矩阵沿45度递增,形成一个zigzag数组(JPEG编码里取像素数据的排列顺序),请问如何用C++实现? (中国台湾著名硬件公司2007年11月面试题)



//题目:输入n 求一个n*n的矩阵,规定矩阵沿45度角线递增,
 //形成一个zigzag数组,请问如何用C++实现
 //如图:
 //
 //Please Input The Number!
 //8
 //     0     1     5     6    14    15    27    28
 //     2     4     7    13    16    26    29    42
 //     3     8    12    17    25    30    41    43
 //     9    11    18    24    31    40    44    53
 //    10    19    23    32    39    45    52    54
 //    20    22    33    38    46    51    55    60
 //    21    34    37    47    50    56    59    61
 //    35    36    48    49    57    58    62    63
 //
 //
 //分析:

//1.递增的方向只有2个:左下,右上。 如果之前是按左下递增,那么之后是按右上递增,再按左下方递增
//2.同一个斜线上数据的规律是:下标(i+j)的和都一样。

 //先看矩阵,发现矩阵对角线上部元素与下部对应元素之和为N^2-1
 //即为 Arr[i][j]+Arr[N-1-i][N-1-j]=N^2-1
 //
 //所以我们只需要处理上三角即可,下三角可推出。
 //观察上三角中。
 //数组各项横纵坐标与值的关系
 //0  0  0
 //0  1  1
 //1  0  2
 //2  0  3
 //1  1  4
 //0  2  5
 //0  3  6
 //1  2  7
 //2  1  8
 //3  0  9
 //4  0  10
 //从中分析 发现(i+j)的和与结果有关系
 //令 s=i+j
 //s=0  只有0 1个元素落在这个范围
 //s=1  有2个
 //s=2  有3个
 //s=3  有4个
 //s=4  。。。
 //这样
 //任意一项Arr[i][j],令s=i+j
 //则该项之前的s-1项有
 //1+2+...+s=s(s+1)/2这么多个数,那么该数位于哪个位置?
 //我们再看看 添加其前s-1项的和
 //0  0  0   0
 //0  1  1   1
 //1  0  2   1
 //2  0  3   3
 //1  1  4   3
 //0  2  5   3
 //0  3  6   6
 //1  2  7   6
 //2  1  8   6
 //3  0  9   6
 //4  0  10  10
 //从中我们可以看出 ,当s能够被2整除时 Arr[i][j]=s(s+1)/2+j
 //否则 Arr[i][j]=s(s+1)/2+i;

#include <iostream>
 #include <iomanip>
 using namespace std;
 
 int main()
 {
     int N;
     int s,i,j;
     cout<<"Please Input The Number!"<<endl;
     cin>>N;
     int** Arr=new int*[N];//int** Arr=(int **)malloc(N*sizeof(int));
     for(i=0;i<N;i++)
         Arr[i]=new int[N];//Arr[i]=(int*)malloc(N*sizeof(int));严格来讲这里应该加强防错处理。
     for(i=0;i<N;i++)
         for(j=0;j<N-i;j++)
         {
             s=i+j;
             if(s<N)
             {
                 Arr[i][j]=s*(s+1)/2+((s%2==0)? j:i);
             }
         }
         for(i=N-1;i>0;i--)
             for(j=N-i;j<N;j++)
             {
                 Arr[i][j]=N*N-1-Arr[N-1-i][N-1-j];
             }
     for(i=0;i<N;i++)
     {
         for(j=0;j<N;j++)
             cout<<setw(6)<<Arr[i][j];
         cout<<endl;
     }
     return 0;
 }

另外一种实现:

int **printnxn(int **pSpace, int N)
{
	int s, i, j;
	int squa;
	pSpace = (int **)malloc(N*sizeof(int *));
	if (pSpace == NULL)
		return 0;
	for (i = 0; i<N; i++)
	{
		if ((pSpace[i] = (int *)malloc(N*sizeof(int))) == NULL)
		{
			while (--i>0)
			{
				free(pSpace[i]);
			}
			free(pSpace);
			return 0;
		}
	}
	squa = N*N;
	for (i = 0; i<N; i++)
	{
		for (j = 0; j<N; j++)
		{
			s = i + j;
			if (s<N)//三角形,求面积,加上偏移
			{
				pSpace[i][j] = s*(s + 1) / 2 + (((i + j) % 2 == 1) ? i : j);
			}
			else//转换成上面的方式
			{
				s = (N - 1 - i) + (N - 1 - j);
				pSpace[i][j] = squa - s*(s + 1) / 2 - (N - (((i + j) % 2 == 1) ? i : j));
			}
		}
	}
	for (i = 0; i<N; i++)
	{
		for (j = 0; j<N; j++)
		{
			printf("%6d", pSpace[i][j]);
		}
		printf("\n");
	}
	return pSpace;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int N;
	scanf_s("%d", &N);
	int **p = NULL;
	printnxn(p, N);
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值