递归练习题:求解n阶螺旋矩阵问题(经典)

【问题描述】
创建n阶螺旋矩阵并输出。

输入样例:
4

输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7

【思路】:
二月份的最后一天了,今天一定要多刷点题。好,言归正传。本题其实没那么简单,首先,你得看明白题,它要求的是创建n阶螺旋矩阵并输出,而不是我一开始想的直接用递归函数输出。也就是说,我们是先用递归函数将螺旋矩阵放入到一个二维数组中去之后再输出 !如果像我一样想成直接输出,那么本题将变得非常不好做!因为你要考虑很多的空格输出换行输出,很麻烦!

我觉得递归题跟动规题分析其实差不多,我们可以先自己手动的把几种情况画出来,然后找找递归结构。
在这里插入图片描述
我们发现,实际上,每一个大的螺旋矩阵里面都是包含着一个小的螺旋矩阵的!那么递归结构不就出来了吗,我们要解决一个大的螺旋矩阵问题,只用把它四周的“边框”填充起来,然后内部实际上就成了一个规模小一点的螺旋矩阵问题,递归解决就可以了!

经过分析所以我们的递归式大概是:f (大规模) = 填充四个边框 + f (小规模)
至于是什么参数,那就由你来设了。我设了四个参数:1.螺旋矩阵起始数字s。2.螺旋矩阵终止数字e(其实这个不需要)
3.螺旋矩阵的长度len(要用来做边界判断的)
4.表示当前是第几个螺旋矩阵,数字k

参考代码:

#include<iostream>
using namespace std;

const int maxn = 60;
int n;
int a[maxn][maxn];

//len表示矩阵的边长,也属于一个问题参量 , k表示当前是第几个矩阵 
void f(int s, int e, int len, int k)			//将i---j的螺旋矩阵装到二维数组中 
{
	//递归边界 
	if(len == 1)
	{
		a[k][k] = s;
		return ;
	}
	else if(len == 2)
	{
		a[k][k] = s++;
		a[k][k + 1] = s++;
		a[k + 1][k + 1] = s;
		a[k + 1][k] = e;
		return ;
	}
	
	//矩阵上边框 
	int col = n + 1 - k;			//表示右边框的列号和下边框的行号 
	int x = s;
	for(int j = k;j <= col;j++)		//这里循环条件之前手误写成j <= len了,导致错误 
	{
		a[k][j] = x;
		x++;
	} 
	//矩阵右边框
	for(int i = k + 1;i <= col;i++)
	{
		a[i][col] = x;
		x++;
	} 
	//矩阵下边框
	for(int j = col - 1;j >= k;j--) 
	{
		a[col][j] = x;
		x++;
	}
	//矩阵左边框
	for(int i = col - 1;i >= k + 1;i--)
	{
		a[i][k] = x;
		x++;
	}
	f(x, n * n, len - 2, k + 1);		//递归,填充小螺旋矩阵
}

int main()
{
	cin >> n;
	f(1, n * n, n, 1);			//从k = 1开始,第一个矩阵 
	//print a
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= n;j++)
		{
			printf("%5d", a[i][j]);			//输出右对齐
		}
		cout << endl;
	}
	return 0;
}

运行结果:
(n == 9)
在这里插入图片描述


【Leetcode例题】

在这里插入图片描述

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]


上面的c语言代码是好几年前写的了,这回用js重写一遍,思想都是一样的。如果上面看不懂,可以看下下面这个js的代码,简洁一点。

/**
 * @param {number} n
 * @return {number[][]}
 */

var fun = function(start, matx,n, x, y){
    //base case
    if(n == 1){
        matx[x][y] = start;
        return ;
    }
    if(n == 0)  return ;

    var num = start;
    //最上面一列
    for(let i = y;i < y + n;i++){
        matx[x][i] = num;
        num++;
    }
    //最右边一列
    for(let i = x + 1;i < x + n;i++){
        matx[i][y + n - 1] = num;
        num++;
    }
    //最底下一列
    for(let i = y + n - 2;i >= y;i--){
        matx[x + n - 1][i] = num;
        num++;
    }
    //最左边一列
    for(let i = x + n - 2;i >= x + 1;i--){
        matx[i][y] = num;
        num++;
    }
    //递归解决
    fun(num, matx, n - 2, x + 1, y + 1);

}

var generateMatrix = function(n) {
    var matx = new Array(n).fill().map(()=>Array(n).fill(0));
    fun(1, matx, n, 0, 0);
    return matx;
};
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值