7-5 螺旋方阵

 

分数 20

全屏浏览题目

切换布局

作者 C课程组

单位 浙江大学

所谓“螺旋方阵”,是指对任意给定的N,将1到N×N的数字从左上角第1个格子开始,按顺时针螺旋方向顺序填入N×N的方阵里。本题要求构造这样的螺旋方阵。

输入格式:

输入在一行中给出一个正整数N(<10)。

输出格式:

输出N×N的螺旋方阵。每行N个数字,每个数字占3位。

输入样例:

5

输出样例:

  1  2  3  4  516 17 18 19  615 24 25 20  714 23 22 21  813 12 11 10  9

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

我的答案:

分析过程:

  1. 螺旋方阵的填充模式为:先向右,然后向下,接着向左,最后向上,循环这四个方向。
  2. 向右和向左时,行数保持不变;向下和向上时,列数保持不变。
  3. 每完成一个方向的填充后,要缩小填充的范围。
  4. 填充完成的条件是已填入的数目等于 N×N。

解题过程:

  1. 初始化一个 N×N 的数组 matrix。
  2. 初始化当前方向为“向右”,当前行和列为 (0, 0)。
  3. 初始化一个计数器 counter 从1开始,每填充一个数字后加1。
  4. 根据当前方向进行填充,完成后改变方向。
  5. 根据方向,更新行或列的值。
  6. 当计数器大于 N×N 时,结束填充。
  7. 打印结果。

接下来,我们用 C 和 C++ 语言实现上述算法:

好的,我明白你的疑问。螺旋方阵的填充过程确实有点特殊。当我们沿着一个方向填充时,该方向上可填充的格子数量不是每次都一样的。具体来说,每完成一个循环(四个方向:右、下、左、上),其中的两个方向上可填充的格子数量都会减少一个。

详细分析如下:

1. **向右**:开始时,我们从最左边向右填充,可填充的格子数量是 N。
2. **向下**:当我们完成向右的填充后,开始向下填充,此时可填充的格子数量是 N-1,因为上边的第一行已经被填充。
3. **向左**:接着,我们向左填充,此时可填充的格子数量也是 N-1,因为下边的最后一行也已经被填充。
4. **向上**:最后,当我们向上填充时,可填充的格子数量是 N-2,因为除了第一行外,第二行也已经被填充。

接下来,当我们开始新的循环(第二次的右、下、左、上方向填充),可填充的格子数量会进一步减少。

这是因为在向右或向左填充时,由于上次循环中向下和向上的填充,已经使得上下两行被填充,所以此次循环中向右或向左时的填充格子数量会减少两个。相应地,在向下或向上填充时,由于上次循环中向右和向左的填充,已经使得左右两列被填充,所以此次循环中向下或向上时的填充格子数量会减少两个。

在代码中,我们通过检查每个格子是否已经被填充(即值为0)来决定是否继续当前方向的填充。这样,即使我们的循环设定了 N 次迭代,由于已填充的格子检查,我们可以自然地结束当前方向的填充并转向下一个方向。

C语言:

#include <stdio.h>int main() {int N;scanf("%d", &N);int matrix[N][N];int row = 0, col = 0, num = 1, i;while (num <= N * N) {while (col < N && matrix[row][col] == 0) {matrix[row][col++] = num++;}col--; row++;while (row < N && matrix[row][col] == 0) {matrix[row++][col] = num++;}row--; col--;while (col >= 0 && matrix[row][col] == 0) {matrix[row][col--] = num++;}col++; row--;while (row >= 0 && matrix[row][col] == 0) {matrix[row--][col] = num++;}row++; col++;}for (i = 0; i < N; i++) {for (int j = 0; j < N; j++) {printf("%3d", matrix[i][j]);}printf("\n");}return 0;
}

C++:

#include <iostream>
#include <vector>
using namespace std;int main() {int N;cin >> N;vector<vector<int>> matrix(N, vector<int>(N, 0));int row = 0, col = 0, num = 1;while (num <= N * N) {while (col < N && matrix[row][col] == 0) {matrix[row][col++] = num++;}col--; row++;while (row < N && matrix[row][col] == 0) {matrix[row++][col] = num++;}row--; col--;while (col >= 0 && matrix[row][col] == 0) {matrix[row][col--] = num++;}col++; row--;while (row >= 0 && matrix[row][col] == 0) {matrix[row--][col] = num++;}row++; col++;}for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {cout.width(3);cout << matrix[i][j];}cout << endl;}return 0;
}

注意:两种实现都采用了简单的嵌套循环,其中内层循环负责向某一方向填充,外层循环则负责切换方向。

C语言循环体详细解释:

首先,外部的 `while (num <= N * N)` 代表当我们填入的数字没有超过 `N*N` 时,我们就继续填充矩阵。

接下来是四个内部的 while 循环,分别代表向右、向下、向左、向上四个方向的填充。

1. **向右**:
    ```c
    while (col < N && matrix[row][col] == 0) {
        matrix[row][col++] = num++;
    }
    col--; row++;
    ```
    - `col < N` 保证列数没有超出范围。
    - `matrix[row][col] == 0` 检查当前格子是否为空(即值为0)。
    - `matrix[row][col++] = num++` 将数字填入当前格子,列数加1准备填充下一个格子,填入的数字加1。
    - 最后 `col--` 和 `row++` 是调整到下一个方向的起始点。

2. **向下**:
    ```c
    while (row < N && matrix[row][col] == 0) {
        matrix[row++][col] = num++;
    }
    row--; col--;
    ```
    - `row < N` 保证行数没有超出范围。
    - `matrix[row][col] == 0` 检查当前格子是否为空。
    - `matrix[row++][col] = num++` 将数字填入当前格子,行数加1准备填充下一个格子,填入的数字加1。
    - 最后 `row--` 和 `col--` 是调整到下一个方向的起始点。

3. **向左**:
    ```c
    while (col >= 0 && matrix[row][col] == 0) {
        matrix[row][col--] = num++;
    }
    col++; row--;
    ```
    - `col >= 0` 保证列数没有变为负数。
    - `matrix[row][col] == 0` 检查当前格子是否为空。
    - `matrix[row][col--] = num++` 将数字填入当前格子,列数减1准备填充下一个格子,填入的数字加1。
    - 最后 `col++` 和 `row--` 是调整到下一个方向的起始点。

4. **向上**:
    ```c
    while (row >= 0 && matrix[row][col] == 0) {
        matrix[row--][col] = num++;
    }
    row++; col++;
    ```
    - `row >= 0` 保证行数没有变为负数。
    - `matrix[row][col] == 0` 检查当前格子是否为空。
    - `matrix[row--][col] = num++` 将数字填入当前格子,行数减1准备填充下一个格子,填入的数字加1。
    - 最后 `row++` 和 `col++` 是调整到下一个循环开始的起始点。

这四个内部循环结束后,如果整个矩阵还没填满,那么整个外部循环会再次执行,继续从当前位置开始螺旋填充。

总结:

从这道关于螺旋方阵的题目中,我们可以学到很多有用的知识和技能:

1. **问题分析**:在开始编码之前,我们需要首先分析和理解题目。对于一些问题,如果没有明确的解题思路,直接编写代码可能会陷入混乱。通过深入地分析题目,我们可以识别出问题的核心要点,并形成一个清晰的解题策略。

2. **数组操作**:这题涉及到了二维数组的操作。对于新手来说,熟练掌握二维数组的初始化、访问和修改是非常基础的。

3. **循环控制**:题目中多层循环的使用,尤其是内部的四个方向的循环,帮助我们理解如何在循环中适时改变方向、跟踪状态并作出决策。

4. **边界条件处理**:处理数组时经常需要处理边界情况,例如确保索引没有超出数组的边界。这道题很好地体现了这一点。

5. **模拟问题解决**:这道题要求我们模拟螺旋填充的过程,这种模拟类的问题在实际编程和算法竞赛中都非常常见。通过解决此类问题,我们可以加强对复杂过程模拟的能力。

6. **代码整洁和结构**:良好的代码应当具备清晰的结构和易读性。这道题给了我们一个机会,让我们思考如何组织代码,使其不仅能够工作,而且具有良好的可读性和可维护性。

7. **调试与测试**:完成代码编写后,我们需要进行测试。设计一些测试用例,特别是一些边界情况,可以帮助我们发现并修复代码中的错误。

总的来说,这道题目为我们提供了一个综合练习的机会,让我们运用和巩固在数据结构、算法和编程中学到的知识和技能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/99509.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 CubeMX (第一步Freertos任务管理:创建、删除、挂起、恢复)

STM32 CubeMX Freertos STM32 CubeMX &#xff08;Freertos任务&#xff1a;创建、删除、挂起、恢复&#xff09; STM32 CubeMX Freertos前言一、STM32 CubeMX 配置时钟树配置HAL时基选择TIM1&#xff08;不要选择滴答定时器&#xff1b;滴答定时器留给OS系统做时基&#xff09…

css学习1

1、样式定义如何显示元素。 2、样式通常保存至外部的css文件中。 3、样式可以使内容与表现分离。 4、css主要有两部分组成&#xff1a;选择器与一条或多条声明。 选择器通常为要改变的html元素&#xff0c;每条声明由一个属性和一个值组成。每个属性有一个值&#xff0c;属性…

网络通信原理UDP协议(第五十课)

UDP协议:用户数据包协议,无连接、不可靠,效率高 字段长度描述Source Port2字节标识哪个应用程序发送(发送进程)。Destination Port2字节标识哪个应用程序接收(接收进程)。Length2字节UDP首部加上UDP数据的字节数,最小为8。Checksum2字节覆盖UDP首部和UDP数据,是可…

[Docker] Windows 下基于WSL2 安装

Docker 必须部署在 Linux 内核的系统上。如果其他系统想部署 Docker 就必须安装一个虚拟 Linux 环境。 1. 开启虚拟化 进入系统BIOS&#xff08;AMD 为 SVM&#xff1b;Intel 为 Intel-vt&#xff09;改为启用(enable) 2. 开启WSL 系统设置->应用->程序和功能->…

浅拷贝与深拷贝

作者简介&#xff1a; zoro-1&#xff0c;目前大一&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; 浅拷贝与深拷贝 浅拷贝浅拷贝定义浅拷贝代码演示浅…

《Linux运维总结:Centos7.6之OpenSSH7.4p1升级版本至9.4p1》

Centos通过yum升级OpenSSH 在官方支持更新的CentOS版本&#xff0c;如果出现漏洞&#xff0c;都会通过更新版本来修复漏洞。这时候直接使用yum update就可以升级版本。 yum -y update openssh 但是&#xff0c;CentOS更新需要有一段时间&#xff0c;不能在漏洞刚出来的时候就有…

最长公共子序列——力扣1143

解法:动态规划 int longestCommonSubsequence(string text1, string text2){int m=text1.size(), n=text2.size

【微服务】一文了解 Nacos

一文了解 Nacos Nacos 在阿里巴巴起源于 2008 2008 2008 年五彩石项目&#xff08;完成微服务拆分和业务中台建设&#xff09;&#xff0c;成长于十年双十一的洪峰考验&#xff0c;沉淀了简单易用、稳定可靠、性能卓越的核心竞争力。 随着云计算兴起&#xff0c; 2018 2018 20…

opencv进阶03-图像与鼠标的交互示例

在处理图像时&#xff0c;可能需要与当前正在处理的图像进行交互。OpenCV 提供了鼠标事件&#xff0c;使用户可以通过鼠标与图像交互。鼠标事件能够识别常用的鼠标操作&#xff0c;例如&#xff1a;针对不同按键的单击、双击&#xff0c;鼠标的滑动、拖曳等。 例如&#xff0c;…

【Windows系统编程】06.HotFixHook与进程通信(详解HotFixHook)

上一讲讲到的InlineHook&#xff0c;每次Hook的时候&#xff0c;都要读写两次内存&#xff08;先Hook&#xff0c;再还原&#xff09;这种Hook方式&#xff0c;性能比较低&#xff0c;今天我们讲的这种Hook方式&#xff0c;可以说是InlineHook的升级版本 HotFix&#xff08;热…

Android3:布局

一。线性布局 创建项目Linear Layout Example activity_main.xml <?xml version"1.0" encoding"utf-8"?><LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"an…

‘VB6EXT.OLB’ could not be registered

打开VB6提示&#xff1a;‘VB6EXT.OLB’ could not be registered 解决办法&#xff1a; 用管理员打开。 实测可行。 参考&#xff1a;VB6 Error please help-VBForums

uni-app引入sortable列表拖拽,兼容App和H5,拖拽排序。

效果: 拖拽排序 背景&#xff1a; 作为一名前端开发人员&#xff0c;在工作中难免会遇到拖拽功能&#xff0c;分享一个github上一个不错的拖拽js库&#xff0c;能满足我们在项目开发中的需要&#xff0c;下面是我在uniapp中使用SortableJS的使用详细流程&#xff1b; vue开发…

TCP定制协议,序列化和反序列化

目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现&#xff1a; 2.4编译测试 总结 前言 在之前的文章中&#xff0c;我们说TCP是面向字节流的&#xff0c;但是可能对于面向字节流这个概念&#xff0c;其实并不理解的&#xff0c;今天我们要介…

派森 #P122. 峰值查找

描述 给定一个长度为n的列表nums&#xff0c;请你找到峰值并返回其索引。数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回任何一个所在位置即可。 &#xff08;1&#xff09;峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于&#xff1b; &…

docker的资源控制及数据管理

docker的资源控制及docker数据管理 一.docker的资源控制 1.CPU 资源控制 1.1 资源控制工具 cgroups&#xff0c;是一个非常强大的linux内核工具&#xff0c;他不仅可以限制被 namespace 隔离起来的资源&#xff0c; 还可以为资源设置权重、计算使用量、操控进程启停等等。 …

kafka晋升之路-理论+场景

kafka晋升之路 一&#xff1a;故事背景二&#xff1a;核心概念2.1 系统架构2.2 生产者&#xff08;Producer&#xff09;2.2.1 生产者分区2.2.2 生产者分区策略 2.3 经纪人&#xff08;Broker&#xff09;2.3.1 主题&#xff08;Topic&#xff09;2.3.2 分区&#xff08;Partit…

07 - 查看、创建、切换和删除分支

查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;GIT常用场景- 目录 文章目录 1. 查看分支2. 创建和切换分支3. 删除分支 1. 查看分支 git branch -va2. 创建和切换分支 第一种&#xff1a; 创建分支&#xff1a; git branch new_branch切换分支&#xff1a; …

代码生成综述

代码生成大模型属于LLM模型的一个子类&#xff0c;理论来讲也是属于语言模型的一种特例。代码本身其实也是一种特殊的语言表示&#xff0c;所以代码模型的实现应该是具备通用自然语言和代码两部分的能力。实际的代码模型也是有两条路径来实现&#xff0c;让训练好的NLP LLM模型…

【2023年11月第四版教材】《第5章-信息系统工程之软件工程(第二部分)》

《第5章-信息系统工程之软件工程&#xff08;第二部分&#xff09;》 1.3 软件设计1.4 软件实现&#xff3b;补充第三版教材内容&#xff3d; 1.5 部署交付 1.3 软件设计 1、结构化设计SD是一种面向数据流的方法&#xff0c;它以SRS和SA阶段所产生的DFD和数据字 典等文档为基础…