该题为腾讯mxg面试委员会二面试题,要求如下:
逐行打印n * n回型矩阵( 不可以在内存填好整个矩阵然后再打印)
n=3
1 2 3
8 9 4
7 6 5
n=4
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
不在内存中开辟二维数组,则应该寻找(i, j)与num的关系,达到O(1)计算(i, j)上应该填充的num
将二维数组看成一层一层的圈,如图。外层(红色)为第0圈,中间层(深蓝)为第1圈,内层(浅蓝)为第2层
以下均以n=6为例:
根据n的大小可计算(i, j)所处在第几个圈中,i_circle_index = Min(Min(i, j)-0, n-1-Max(i, j))
其实就是判断i, j中离0或n-1大小最小的那个就是当前圈,如(0, 3)->0,(1, 2)->1,(1, 5)->0,(2, 3)->2
根据n和(i, j)所处圈可计算当前圈中数字的个数i_circle_num = (n-1-(2*i_index))*4<=0?1:(n-1-(2*i_index))*4,这个比较好理解,就不做解释了
接下来就是求每个(i, j)所对应的值num了
我们将圈分为四个部分Top、Right、Bottom、Left,观察(i, j)可以发现,[Top、Right]中 i => j、[Bottom、Left]中i < j
我们规定[(0, 0)、...、(0, n-1)]为Top共有n-2*i_circle_index个数,[(1, n-1)、...、(n-1, n-1)]为Right共有n-2*i_circle_index-1个数,[(n-1, n-2)、...、(n-1, 0)]为Left共有n-2*i_circle_index-1个数,[(n-2)、...、(1)]为Left共有n-2*i_circle_index-2个数
ok其实计算到这里,很多东西都出来了,我们现在需要做的就是在输出每个(i, j)位置的时候,判断(i, j)属于第几个圈,之前的圈共有多少个数字,(i, j)在该圈中属于[Top、Right、Bottom、Left]的那个部分,在当前部分属于第几个元素,然后就能计算出当前位置(i, j)对应的值num了
num = 外层圈数字累加和+当前圈所处属性[op、Right、Bottom、Left]的数字个数+当前属性中的个数
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
using namespace std;
int Min(int a, int b){
return a>b?b:a;
}
int Max(int a, int b){
return a>b?a:b;
}
//计算当前i,j所处第几个圈
int getCircleIndex(int i, int j, int n){
return Min(Min(i, j)-0, n-1-Max(i, j));
}
//计算当前圈共有多少元素
int getCircleNum(int i_index, int n){
if(i_index < 0){
return 0;
}else{
return (n-1-(2*i_index))*4<=0?1:(n-1-(2*i_index))*4;
}
}
//环形打印二维数组
void PrintClockWiseMatrix(int n){
if(n <= 0){
return;
}
int i_acc_circle_num[n+1]; //存储该圈的起始大小(前i圈数字的累加和)
int i_circle = n/2;
if(n%2){
i_circle ++;
}
memset(i_acc_circle_num, 0, sizeof(i_acc_circle_num));
i_acc_circle_num[0] = 0;
for(int i = 1 ; i <= i_circle ; i ++){
i_acc_circle_num[i] = i_acc_circle_num[i-1] + getCircleNum(i-1, n);
}
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < n ; j ++){
int i_circle_index = getCircleIndex(i, j, n);
int i_circle_num = i_acc_circle_num[i_circle_index];
int i_num = 0;
if(i <= j){
if(i == i_circle_index){
//top
i_num = i_circle_num + j - i_circle_index + 1;
}else{
//right
i_num = i_circle_num + i - i_circle_index + n-2*i_circle_index/*top元素个数*/;
}
printf("%2.2d ", i_num);
}else{
if(i == n-1-i_circle_index){
//bottom
i_num = i_circle_num + n-i_circle_index-1-j + 2*(n-2*i_circle_index)-1;
}else{
//left
i_num = i_circle_num + n-i_circle_index-1-i + 3*(n-2*i_circle_index)-2;
}
printf("%2.2d ", i_num);
}
}
printf("\n");
}
}
int main(){
PrintClockWiseMatrix(10);
return 0;
}
输出结果:
n=5
n=6
n=10