算法学习系列(十六):二维数组填充数字问题

引言

关于这个二维数组填数问题我碰到过很多次,不管是找工作笔试面试,还是在算法竞赛,而且这种问题都有很多种变形,当初学算法的时候让我很是头疼,因为总是会了一道后,过了一段时间就忘了,又或者是这道会了,然后变了一下就不会了,我很是苦恼啊,不过当我某天在 q q qq qq 群中看到一个群友发的这种问题后,一下勾起了我的思考,然后不知道怎的,我就自己想出了一种方法,我觉得这个方法可以用在这种问题的任意一个地方,所以我觉得很好,然后我也就写篇博客总结一下吧,这个套路我是从 B F S BFS BFS 上汲取出来的,话不多说直接开始。

一、思路

我总结这些题的总体都是按照一定的方向循环填数的,然后就按照一个方向不断地前进,只要碰到了边界或者下一个位置已经被填充过了那就换一个方向继续走继续填充,直到达到 c n t cnt cnt 的大小

二、代码模板

int cnt = 1;
int dir[4][2] = {0,1,0,-1,1,0,-1,0};

int x = 0, y = 0;
matrix[x][y] = cnt++;  // matrix初始都置为0
while(cnt <= N)
{
	for(int i = 0; i < 4; ++i)
	{
		while(1)
		{
			int nx = x + dir[i][0];
			int ny = y + dir[i][1];
			
			if(x < 0 || x >= n || y < 0 || y >= n) break;  // 碰到边界
			if(matrix[x][y]) break;  // 已经填充过了
		
			x = nx, y = ny;
			matrix[x][y] = cnt++;
		}
	}
}

三、例题总结

1.回字蛇形矩阵

输入两个整数 n 和 m,输出一个 n 行 m 列的矩阵,将数字 1 到 n×m 按照回字蛇形填充至矩阵中。

具体矩阵形式可参考样例。

输入格式
输入共一行,包含两个整数 n 和 m。

输出格式
输出满足要求的矩阵。
矩阵占 n 行,每行包含 m 个空格隔开的整数。

数据范围
1≤n,m≤100
 
输入样例:
3 3

输出样例:
1 2 3
8 9 4
7 6 5
#include <cstdio>
#include <iostream>

using namespace std;

int dir[4][2] = {0,1,1,0,0,-1,-1,0};
const int N = 110;
int a[N][N];
int n, m, cnt = 1;


int main()
{
    scanf("%d%d", &n, &m);
    
    int x = 0, y = 0;
    a[x][y] = cnt++;
    while(cnt <= n * m)
    {
        for(int i = 0; i < 4; ++i)
        {
            while(1)
            {
                int nx = x + dir[i][0];
                int ny = y + dir[i][1];
                
                if(nx < 0 || nx >= n || ny < 0 || ny >= m) break;
                if(a[nx][ny]) break;
                
                x = nx, y = ny;
                a[x][y] = cnt++;
            }
        }
    }
    
    for(int i = 0; i < n; ++i)
    {
        for(int j = 0; j < m; ++j)
        {
            printf("%d ", a[i][j]);
        }
        puts("");
    }
    
    return 0;
}

可以看出是全部正确的
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.三角填充

这个是一种斜线的走,只要把方向变一下,就行了,然后其余的这种都是一样的,只不过是方向的不同而已,其他的都是一样的

方阵的主对角线之上称为“上三角”。

请你设计一个用于填充n阶方阵的上三角区域的程序。填充的规则是:使用1,2,3….的自然数列,从左上角开始,按照顺时针方向螺旋填充。

例如:当n=3时,输出:
1 2 3
6 4
5

当n=4时,输出:
1 2 3 4
9 10 5
8 6
7

当n=5时,输出:
1 2 3 4 5
12 13 14 6
11 15 7
10 8
9


程序运行时,要求用户输入整数n(3~20)
程序输出:方阵的上三角部分。
要求格式:每个数据宽度为4,右对齐。
#include <cstdio>
#include <iostream>

using namespace std;

const int N = 25;
int a[N][N];
int n, cnt = 1;

int dir[3][2] = {0,1,1,-1,-1,0};  // 右 左下 上

int main()
{
	scanf("%d", &n);

	int x = 0, y = 0;
	a[x][y] = cnt++;
	while(cnt <= (n+1) * n / 2)
	{
		for(int i = 0; i < 3; ++i)
		{
			while(1)
			{
				int nx = x + dir[i][0];
				int ny = y + dir[i][1];
				if(nx < 0 || nx >= n || nx < 0 || ny >= n) break;
				if(a[nx][ny]) break;

				x = nx, y = ny;
				a[x][y] = cnt++;
			}
		}
	}
	
	for(int i = 0; i < n; ++i)
	{
		for(int j = 0; j < n; ++j)
		{
			if(a[i][j]) printf("%4d",a[i][j]);
		}
		puts("");
	}
	
	return 0;
}

可以看出都是正确的
在这里插入图片描述

在这里插入图片描述

3.回文填充二

题目描述
给定两个数字 n 和 m,代表矩阵的大小。现有一个二维数组,需要对其进行填充。填充规律如下图:

在这里插入图片描述
在这里插入图片描述

输入描述
输入只有一行,第一个数字是 n,第二个数字是 m.

输出描述
请输出整个二维数组。每行末尾的数字后没有空格。

输入示例
3 4
输出示例

12 11 10 9
3 2 1 8
4 5 6 7

数据范围:
1 <= n <= 100;
1 <= m <= 100;
n 和 m 可能相等,也有可能不相等。

这个有点讨厌是从里到外一层一层填,我最初是按模板写的,发现不对,因为他是一层一层往外走的,不是走到边界或者碰到填过了的,就跟下图一样,这就麻烦得很,因为我不知道每一层的边界是多少,然后我就点开讨论区,看见了从外到内这四个字,一下就明白了,就从外向内跟那个回型填充一样,只不过cnt是从n*m开始了,见代码
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 110;
int matrix[N][N];
int n, m;
int dir[4][2] = {0,1, 1,0, 0,-1, -1,0};  // 分别为右 下 左 上
int cnt;

int main()
{
    scanf("%d%d", &n, &m);
    int x = 0, y = 0;
    cnt = n * m;
    matrix[x][y] = cnt--;
    
    
    while(cnt > 0)
    {
        for(int i = 0; i < 4; ++i)
        {
            while(1)
            {
                int nx = x + dir[i][0];
                int ny = y + dir[i][1];
                
                if(nx < 0 || nx >= n || ny < 0 || ny >= m) break;
                if(matrix[nx][ny]) break;
                
                x = nx, y = ny;
                matrix[x][y] = cnt--;
            }
        }
    }
    
    for(int i = 0; i < n; ++i)
    {
        for(int j = 0; j < m; ++j)
        {
            printf("%d ", matrix[i][j]);
        }
        puts("");
    }
    
    return 0;
}

可以看出样例是正确的,然后也AC了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 16
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lijiachang030718

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值