蛇形矩阵

开始了找工作的一年,刷题的过程中发现有时候好记性不如烂笔头,而且有时候找最好的解法并不容易,因此,陆续更新一些笔记,方便和我一样的小白们学习。

蛇形矩阵是很常见的题目,我在这里给出见到的几种变种题型及其较为简洁的解法。

1.首先,最常规的题目是让你输出一个大小为n的方阵:大概长这样:

这是一个边长为5的蛇形矩阵,按照对角线方向依次递增。

直接上代码:

#include <iostream>

using namespace std;


void snakeLikeMat(int **a, int n)
{
	int num = 1;
	int total = n*n;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j <= i; j++)
		{
			if (i % 2==1)
			{
				a[j][i - j] = num++;
			}
			else
			{
				a[i - j][j] = num++;
			}
		}

	}
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j <= i; j++)
		{
			if (i % 2==1)
			{
				a[n - 1 - j][n - 1 - i + j] = total--;
			}
			else
			{
				a[n - 1 - i + j][n - 1 - j] = total--;
			}
		}
	}
}


int main()
{

	int ha = 0;
	cin >> ha;
	int **a = new int*[ha];
	for (int i = 0; i < ha; i++)
	{
		a[i] = new int[ha];
	}
	snakeLikeMat(a, ha);
	for (int i = 0; i < ha; i++)
	{
		for (int j = 0; j < ha; j++)
		{
			if (a[i][j] > 0 && a[i][j] <= ha*ha){
				cout << a[i][j] << "\t";
			}
			else cout << " " << "\t";
		}
		cout << endl;
	}
	for (int i = 0; i < ha; i++)
	{
		delete[] a[i];
	}
	delete[] a;
	system("pause");

关键部分就是snakeLikeMat。它将整个矩阵分成对角线以上和对角线以下分别赋值。

我们知道,每个对角线上的元素的关系是,它们的横纵坐标之和相等,这也是a[j][i - j]的道理,左上角的一半,第i个对角线和为i。右下角的一半,和为2n-2+i,注意这里是从右下角开始的。

而i%2==1则是因为奇数对角线和偶数对角线的方向是相反的。

2.变种,半蛇形矩阵,这时候只要去掉那个嵌套循环就行,上半角就去掉第二个,下半角去掉第一个

3.变种,第一个值首先向下还是向右发展。这时候改成i%2==0就行

4.变种,有时候有些题也会把螺旋矩阵叫成蛇形矩阵,大概长这样:


直接上代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
const int maxn = 10;
int a[maxn][maxn];
int main()
{
	int n,m;
	cin >> n>>m;
	int tot, x, y;

	memset(a, 0, sizeof(a));
	tot = a[x = 0][y = 0] = 1;
	while (tot<n*m)
	{
		while (y + 1<n&&!a[x][y + 1])a[x][++y] = ++tot;
		while (x + 1<m&&!a[x + 1][y])a[++x][y] = ++tot;
		while (y - 1 >= 0 && !a[x][y - 1])a[x][--y] = ++tot;
		while (x - 1 >= 0 && !a[x - 1][y])a[--x][y] = ++tot;
	}
	for (x = 0; x<m; x++)
	{
		for (y = 0; y<n; y++)
			printf("%3d", a[x][y]);
		cout << endl;
	}
	system("pause");
}

代码是改编过的,可以不是一个方阵,同时这也并不是常规写法。

首先,用memset函数设置了一个m*n的全0矩阵,并将a[0][0]赋值为1。

然后用一个嵌套循环,让其赋值。按照一圈,从左上到右上,从右上到右下,从右下到左下,从左下到左上的顺序完成一圈。里面的while检验两个条件:一是即将赋值的这个位置是否还在矩阵范围内,二是这个位置是否已经被赋值过了,其中第二个条件的存在使得其循环完最外圈后开始循环次外圈,然后一直循环,直到某个赋值是该矩阵中的最后一个值:m*n。

5.变种,让你按照螺旋的顺序输出某个矩阵,与4类似,这里用常规思路写

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
                int row = matrix.size();
        int col = matrix[0].size();
        vector<int> res;
         
        // 输入的二维数组非法,返回空的数组
        if (row == 0 || col == 0)  return res;
         
        // 定义四个关键变量,表示左上和右下的打印范围
        int left = 0, top = 0, right = col - 1, bottom = row - 1;
        while (left <= right && top <= bottom)
        {
            // left to right
            for (int i = left; i <= right; ++i)  res.push_back(matrix[top][i]);
            // top to bottom
            for (int i = top + 1; i <= bottom; ++i)  res.push_back(matrix[i][right]);
            // right to left
            if (top != bottom)
            for (int i = right - 1; i >= left; --i)  res.push_back(matrix[bottom][i]);
            // bottom to top
            if (left != right)
            for (int i = bottom - 1; i > top; --i)  res.push_back(matrix[i][left]);
            left++,top++,right--,bottom--;
        }
        return res;
    }
};

简单来说,定义了四个值:左、右、上、下,每过一次循环,则左+1、右-1、上+1、下-1,进行下一圈,和上面的写法不同,这里进入下一圈是由四个值控制的。

其中的重点是两个if语句,if (top != bottom)以及if (left != right)用来判断是否需要再循环,因为奇数情况下最内层的循环可能只有半圈或者四分之一圈,不要重复。比如3*3矩阵,最外面的循环包含了八个数,最里面的数其实只需要左上到右上就行了。四分之一圈。


综上,这就是我遇到的蛇形矩阵的几种变种,比较简单。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值