常见蛇形矩阵解法
1综述
在“华为在线训练与测试平台”遇到一蛇形矩阵题目,2016年4月份网易实习生招聘时也遇到类似的问题,在此总结一下。
常见的蛇形矩阵题目包括以下几种:
1、上三角2、环状
3、对角线走法
1、上三角类型
建模:
//第k行元素的起始元素为 a=1+(0+1+...+k)
//第k行元素的个数为m=Num-k
//第k行的起始间距为:k+2
代码如下:
template<typename T>
inline T get_sum(T n) { //返回值包括n
T sum = 0;
for (T i = 0; i <= n; i++)
sum += i;
return sum;
}
//第k行元素的起始元素为 a=1+(0+1+...+k)
//第k行元素的个数为m=Num-k
//第k行的起始间距为:k+2
static void get_snake_matrix(int Num, int * pResult) {
int i, j, index = 0, start, gap, num;
for (i = 0; i < Num; i++)
{
start = get_sum<int>(i) + 1;
num = Num - i;
gap = i + 2;
pResult[index++] = start;
for (j = 1; j < num; j++)
{
pResult[index] = pResult[index - 1] + gap;
index++;
gap++;
}
}
}
static void test_snake_matrix() {
int Num, i, j, length, num, index = 0;
std::cin >> Num;
length = Num*Num;
int *presult = new int[length];
memset(presult, -1, sizeof(int)*length);
get_snake_matrix(Num, presult);
for (i = 0; i < Num; i++)
{
num = Num - i;
for (j = 0; j < num - 1; j++)
std::cout << presult[index++] << " ";
std::cout << presult[index++] << std::endl;
}
delete[] presult;
presult = NULL;
}
2、环状
可根据1-49数值递增的顺序进行寻路,代码较简单:
//表示纵向循环
static void get_loop_y_matrix(int *presult, int n)
{
memset(presult, -1, sizeof(int)*n*n);
int num, x, y, xdir, ydir;
for (num = 1, x = 0, y = 0, xdir = 1, ydir = 0; num <= n*n; num++)
{
presult[x + y*n] = num;
if ((x + xdir < 0) || (x + xdir == n) || (y + ydir < 0) || (y + ydir == n) || (presult[x + xdir + (y + ydir)*n] != -1))
{
if (xdir != 0)
{
ydir = xdir;
xdir = 0;
}
else {
xdir = -ydir;
ydir = 0;
}
}
x = x + xdir;
y = y + ydir;
}
}
//表示首先进行横向循环
static void get_loop_x_matrix(int *presult, int n)
{
memset(presult, -1, sizeof(int)*n*n);
int num, x, y, xdir, ydir;
for (num = 1, x = 0, y = 0, xdir = 0, ydir = 1; num <= n*n; num++)
{
presult[x + y*n] = num;
if ((x + xdir < 0) || (x + xdir == n) || (y + ydir < 0) || (y + ydir == n) || (presult[x + xdir + (y + ydir)*n] != -1))
{
if (xdir != 0)
{
ydir = -xdir;
xdir = 0;
}
else {
xdir = ydir;
ydir = 0;
}
}
x = x + xdir;
y = y + ydir;
}
}
void static test() {
int n;
std::cin >> n;
int *pmatrix = new int[n*n];
get_loop_y_matrix(pmatrix, n);
int j, i;
for (i = 0; i < n; i++) {
for (j = 0; j < n - 1; j++)
std::cout << pmatrix[j*n + i] << " ";
std::cout << pmatrix[j*n + i] << std::endl;
}
std::cout << std::endl;
get_loop_x_matrix(pmatrix, n);
for (i = 0; i < n; i++) {
for (j = 0; j < n - 1; j++)
std::cout << pmatrix[j*n + i] << " ";
std::cout << pmatrix[j*n + i] << std::endl;
}
delete[] pmatrix;
pmatrix = NULL;
}
3、对角线走法
同2、环状矩阵的思路一样,根据1-49数值递增的顺序进行寻路,本文在寻路时利用了goto语句, 代码如下:
static void get_snake_x_my(int n, int *pmatrix) {
//memset(pmatrix, -1, sizeof(int)*n*n);
int index = 1, x = 0, y = 0;
pmatrix[x + y*n] = index++;
while (true) {
step1: //往右走
x = x + 1;
pmatrix[x + y*n] = index++;
if (y == n - 1) {
if (x == n - 1)
break;
else
goto step2;
}
else if (y == 0)
goto step4;
step2: //往右上走
while (x < n - 1 && y>0) {
x = x + 1;
y = y - 1;
pmatrix[x + y*n] = index++;
}
if (x == n - 1)
goto step3;
else if (y == 0)
goto step1;
step3: //往下走
//如果y不是最后一行,则往下走
y = y + 1;
pmatrix[x + y*n] = index++;
if (x == 0)
goto step2;
else if (x == n - 1)
goto step4;
step4: //往左下走
while (y < n - 1 && x>0)
{
x = x - 1;
y = y + 1;
pmatrix[x + y*n] = index++;
}
if (y == n - 1)
goto step1;
else if (x == 0)
goto step3;
}
}
static void get_snake_y_my(int n, int *pmatrix) {
//memset(pmatrix, -1, sizeof(int)*n*n);
int index = 1, x = 0, y = 0;
pmatrix[x + y*n] = index++;
while (true) {
step1: //往下走
//如果y不是最后一行,则往下走
y = y + 1;
pmatrix[x + y*n] = index++;
if (x == 0)
goto step2;
else if (x == n - 1) {
if (y == n - 1)
break;
else
goto step4;
}
step2: //往右上走
while (x < n - 1 && y>0) {
x = x + 1;
y = y - 1;
pmatrix[x + y*n] = index++;
}
if (x == n - 1)
goto step1;
else if (y == 0)
goto step3;
step3: //往右走
x = x + 1;
pmatrix[x + y*n] = index++;
if (y == n - 1)
goto step2;
else if (y == 0)
goto step4;
step4: //往左下走
while (y < n - 1 && x>0)
{
x = x - 1;
y = y + 1;
pmatrix[x + y*n] = index++;
}
if (y == n - 1)
goto step3;
else if (x == 0)
goto step1;
}
}
static void test_get_snake()
{
int n;
std::cin >> n;
int *pmatrix = new int[n*n]{ -1 };//花括号初始化是C++11的新标准
clock_t begin, end;
begin = clock();
get_snake_x_my(n, pmatrix);
end = clock();
//std::cout << static_cast<double>(end - begin) / CLOCKS_PER_SEC << std::endl;
//begin = clock();
//get_snake(n, pmatrix);
//end = clock();
//std::cout << static_cast<double>(end - begin) / CLOCKS_PER_SEC << std::endl;
int j, i;
for (i = 0; i < n; i++) {
for (j = 0; j < n - 1; j++)
std::cout << std::setw(3) << pmatrix[i*n + j] << " ";
std::cout << std::setw(3) << pmatrix[i*n + j] << std::endl;
}
std::cout << std::endl;
begin = clock();
get_snake_y_my(n, pmatrix);
end = clock();
//std::cout << static_cast<double>(end - begin) / CLOCKS_PER_SEC << std::endl;
for (i = 0; i < n; i++) {
for (j = 0; j < n - 1; j++)
std::cout << std::setw(3) << pmatrix[i*n + j] << " ";
std::cout << std::setw(3) << pmatrix[i*n + j] << std::endl;
}
delete[] pmatrix;
pmatrix = NULL;
}
此外,在网上找到一种比较简练的解法,但是没有看懂,代码也贴出来:
static void get_snake(int n, int *pmatrix)
{
//memset(pmatrix, -1, sizeof(int)*n*n);
int x = 0, y = 0, m = 1;
bool isRow = true;
for (int i = 0; i < (2 * n - 1); i++) {
x = i;
while (x >= ((i < n) ? 0 : i - n + 1)) {
if (x > (n - 1))
x = n - 1;
y = i - x;
if (isRow)
pmatrix[x + y*n] = m;
else {
pmatrix[x *n + y] = m;
}
m++;
x--;
}
isRow = !isRow;
}
}