蛇形矩阵

常见蛇形矩阵解法

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;
		}
	}



  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值