这道题耗费了蛮时间,但彻底理解后感觉也不过尔尔,涉及到了一些不太了解的知识点,算是查漏补缺吧,哦不,是补缺,没有查漏哈哈哈!小菜鸡呜呜。
那么来说一下这道题的题目大意先,题目意思就是给出一个数n,然后输出一个n²的矩阵,按顺时针在矩阵里排列。
题目:
给你一个正整数n ,生成一个包含 1到n2的平方所有元素,且元素按顺时针顺序螺旋排列的
n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
思路
这道题没什么算法在其中,其实就是硬考查你的代码能力,所以敲代码敲得比较少就对这道题很头疼,即使有思路也不好用代码实现。所以有事没事要多写写代码,增强自己的代码能力呀~
不过就算没什么算法,但也还是有解题思路的。因为这道题目输出的n行n列的矩阵,且数据元素是顺序的,所以这里我们采用的数据类型肯定是用二维数组更好操作。然后这个二维数组该如何填充成我们想要的样子呢。可以根据一个方向的变化来填充 ,首先方向是从左到右,元素加加,然后到达此方向的最后一个就换方向加加,最终生成一个n行n列的二维数组。我们可以让数组加加,然后定义一个step一一加加对应相应的数组位置。然后我们具体讲讲思路转换成代码的一个过程。首先二维数组我们可以用vector这一容器来定义实现,自己就是对这方面不太了解,导致该题产出较慢,待会在编程细节里在来详细解析。然后我们定义一下二维数组的x,y,x是行,y是列。然后step初始为1,将1赋给[0,0],所以就实现了二维数组的第一个元素为1,然后y加加,step加加。那我们如何判断该换方向加加呢,在从左到右第一行填充就应该是y<n即y等于3了,就不要往右加加了,超过边界了。这个时候要向下填充了,就是x加加,y不变,因为是在这一列,行元素有变化。然后x<n的时候就换方向。但在这之前应该注意给y减一和x加一,因为在上面的循环里面y超出了矩阵范围,x也要进入第二行,后面同理。所以我们可以得知通过x加加或者y加加,另一个不变来实现换方向的填充。所以一个代码的雏形就是while大循环,跳出的条件是step小于n²,然后嵌套while循环,判断y<n且数组为空然后加加遍历,到达了换方向的条件就跳出循环,然后相应的将x和y进行加或者减,然后进入另一个while循环,对另一个方向进行遍历加加,总共4个while先循环,最后return数组。
时空复杂度分析
暂时略!!!!!!!
具体代码如下所示:
/*
LeetCode59 螺旋矩阵
采用模拟解法解决数组问题
题目:
给你一个正整数n ,生成一个包含 1到n2的平方所有元素,且元素按顺时针顺序螺旋排列的
n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
首先这是一道模拟题,模拟题的意思就是本身不涉及算法,就是单纯根据题目描述模拟整个过程从而得到最后的结果
所以这道题就是考察代码能力和对编程语言的掌握能力
所以要多画画,不要空想
*/
#include<stdio.h>
#include<vector>
using namespace std;
int main(void)
{
return 0;
}
class Solution {
public:
vector< vector<int> > generateMatrix (int n) {
vector< vector<int> > ans;
ans = vector< vector<int> > (n, vector<int> (n));
int x = 0, y = 0;
int step = 1;
while(step <= n*n){
while(y < n && !ans[x][y])
ans[x][y++] = step++;
y-=1;
x+=1;
while(x < n && !ans[x][y])
ans[x++][y] = step++;
x-=1;
y-=1;
while(y >= 0 &&!ans[x][y])
ans[x][y--] = step++;
y += 1;
x-=1;
while(x >= 0 && !ans[x][y])
ans[x--][y] = step++;
x+=1;
y+=1;
}
return ans;
}
};
编程细节
这道题很大一部分是卡在了编程细节上面,对代码不是很熟悉,所以出了很多小问题!这里就来细讲一下。
容器vector
在 C++ 中,vector 是一个十分有用的容器。它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。在这道题中,我们需要一个二维数组来构建这个矩阵,所以就使用了vector容器,从而使二维数组更为方便的使用。
关于vector的使用,需要头文件和using
#include <vector>
using namespace std;
using namespace
实际上就是告诉编译器,你类型是什么,在哪能找到。
常用的是using namespace std,就是说用C++的标准名字空间。所谓namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
首先方法是
vector< vector<int> > generateMatrix (int n) {
}
vector< vector >是类型,代表一个二维数组的类型,注意要最外围的<>要有空格间隔,不然会报错,然后generateMatrix就是自己取的方法名字啦。(int n)就是传参的形参类型。
然后我们再具体来分析一下vector的一些使用
vector < vector<int> > ans;//声明一个叫ans的容器,它里面保存了二维数组类型,即ans里面的每个元素都是二维数组类型。
ans = vector < vector<int> > (n,vector<int>(n));//定义ans容器元素类型,初始化n个对象,每个对象都是vector < vector<int> >类型
//即每个对象都是二维数组,然后每个对象又包含n(后者n)个0,所以就实现了n²二维数组;
图中,我将外围容器table的初始化参数分成了两部分A、B。
A: table外围容器的大小
B: table外围容器的内容,即size1个vector型的元素。
B1:内部容器的大小
B2:内部容器的内容
观察规律,可以得出如下的初始化格式:
容器(大小,内容)。
所以大致vector就在这道题就是这么一个回事了,是不是有点弱智,下面让我们来看看更弱智的编程细节。
循环细节与前置后置加减
我们可能都会觉得循环很简单,不就是判断循环嘛,可是对于小白来说,就会有各种奇葩的问题出现。确实像教我们c语言老师说的那样,学编程一定不是看会的,是多敲,敲会的,很多东西看书看视频哎呀觉得好简单,可是上手就出现了各种问题,在我们逐步解决这些小问题,大问题的时候,我们的编程能力就会不断地提高。好了不扯了,让我们来看看我这个笨蛋又犯了什么错误。
while(step <= n*n){
while(y < n && !ans[x][y])
ans[x][y++] = step++;
y-=1;
x+=1;
while(x < n && !ans[x][y])
ans[x++][y] = step++;
x-=1;
y-=1;
...
}
首先我们看上面的3个while循环,他们的区别就是最上面的while循环是有花括号,而下面两个没有花括号,所以我们肯定知道下面是嵌套在其中的循环,然后当时做题的时候我是理所当然以为下面那个while循环是到另一个while循环前结束的,但实则不然,我们看书上的循环讲解,他们都是说循环到下一个分号结束,如果加花括号便是整个花括号内都是循环体。所以第二个循环体是ans[x][y++] = step++;,而不是包括下面的自变量增减。
然后还有一个就是前置加减和后置加减的区别。这个属于是忘记了知识点,emmm,也不知道怎么说自己好了,反正就是笨蛋!前置是先运算,再执行该条语句,后置是先执行该条语句,再进行运算。
总结
关于这道题确实很考验基本代码能力,自己作为一个小白代码能力当然很差,呜呜,但我会加油的!所以这道题做下来很曲折,所以以后要多思考多学习多总结。这道题里面有一个c++里面的vector容器,自己已经来了解了一些,以后看到不会发懵了!然后就是一些编程细节,自己也在慢慢思索,慢慢解决。最后就是还有一个时空复杂度不知道这道题该去如何分析,等我回学校亲自问大佬!我会把它写进疑问点汇总的,不会忘记的!我真是个笨蛋,for循环一个是n,嵌套一个是n²,可是while我就不知道了,难道是和for一样的?可就算是一样的,它嵌套了4个while循环哎,,,,,.
然后空间复杂度,我大概知道,但现在写出来也没办法,因为没有人可以给我判断正误,所以也只能以后和时间复杂度一起写咯!就这样,完结撒花~