LeetCode刷题day21

算法打卡第二十一天,今天你刷题了吗
😄😄😄😄😄😄😄😄😄😄
😃😃😃😃😃😃😃😃😃😃
💓💓💓大家一起来刷题!💓💓💓
😍😍😍😍😍😍😍😍😍😍
😘😘😘😘😘😘😘😘😘😘
请添加图片描述

今日刷题重点----螺旋矩阵

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例 1:

在这里插入图片描述

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

根据卡尔大佬的说法,求解本题依然是要坚持循环不变量原则。

模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。

可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人

这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开又闭的原则,这样这一圈才能按照统一的规则画下来。

那么我按照左闭右开的原则,来画一圈,大家看一下:
在这里插入图片描述

这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画

这也是坚持了每条边左闭右开的原则。

一些同学做这道题目之所以一直写不好,代码越写越乱。

就是因为在画每一条边的时候,一会左开又闭,一会左闭右闭,一会又来左闭右开,岂能不乱。

参考代码1
//1.一圈一圈的进行填数.圈数=n/2,如果n为奇数,则中间的那个数单独处理.
//2.每次圈的边长相比上一次总是少二 ,以n=6为例:6 4 2  所以可以使用一个变量每次循环之后加2
//3.在进行循环时,要按照一定的规则,既要让所有的点都被遍历到也尽量不要多次进行遍历. 我们采用左闭右开的规则
vector<vector<int>> generateMatrix(int n) {
	vector<vector<int>> res(n,vector<int>(n,0));//定义一个二维数组
	int loop = n / 2;
	int cnt = 1;//填充变量
	int offset = 1;
	int startX = 0,startY = 0;//定义每圈的起始坐标
	while(loop--) {
		int i = startX;
		int j = startY;
		//从左到右
		for(; j< startY+n-offset; j++) {
			res[i][j] = cnt++;
		}
		//从上到下
		for(; i<startX+n-offset; i++) {
			res[i][j]=cnt++;
		}
		//从右向左
		for(; j>startY; j--) {
			res[i][j] = cnt++;
		}
		//从下到上
		for(; i>startX; i--) {
			res[i][j] = cnt++;
		}
		//offset变量加2
		offset+=2;
		//startX,startY进行更新
		startX++;
		startY++;

	}
	if(n%2) { //如果n是奇数.
		res[n/2][n/2] = cnt;
	}
	return res;

}
思路2

生成一个 n×n 空矩阵 res,随后模拟整个向内环绕的填入过程:

  • 定义当前左右上下边界 l,r,u,d,初始值 num = 1,迭代终止值 sum= n * n;

  • 当 num <= sum 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后:num++,得到下一个需要填入的数字;

  • 更新边界:例如从左到右填完后,上边界 u++,相当于上边界向内缩 1。

使用num <= sum而不是l < r || u < d作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。

最终返回 res即可

参考代码2
vector<vector<int>> generateMatrix(int n) {
	vector<vector<int>> res(n,vector<int>(n,0));
	int l = 0,r =n-1,u = 0,d = n-1;
	int sum = n*n,num=1;
	//cout<<"123"<<endl;
	while(num<=sum) {
		//从左到右
		for(int i = l; i<=r; i++) {
			res[u][i]=num++;
		}
		u++;
		//从上到下
		for(int i = u; i<=d; i++) {
			res[i][r] = num++;
		}
		r--;
		//从右向左
		for(int i = r; i>=l; i--) {
			res[d][i]=num++;
		}
		d--;
		//从下到上
		for(int i = d; i>=u; i--) {
			res[i][l] = num++;
		}
		l++;
		cout<<num<<endl;

	}
	return res;
}

请添加图片描述

54. 螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

在这里插入图片描述

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

在这里插入图片描述

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
思路分析

和上面的题思路二很相似,但本题不同的是会出现矩形;,所以中间的for循环也要对sum进行限制,防止减成0后,后面的for还执行.

参考代码
//思路:参考螺旋矩阵二  注意每层for循环中间的sum条件也要限制. 具体原因可以举个例子比如说只有一行的话,
//从左到右循环完毕按说已经结束了,但是 从右向左的for依旧会被执行.. 
vector<int> spiralOrder(vector<vector<int>>& matrix) {
	vector<int> res;
	if(matrix.size()==0){
		return res;
	}
	int n = matrix.size();
	int m = matrix[0].size(); 
	int l = 0,r = m-1,u = 0,d = n-1;
	int sum = n*m;
	while(sum){
		//从左到右
		for(int i=l;i<=r&&sum;i++){
			res.push_back(matrix[u][i]);
			sum--;
		} 
		u++;//上边界++ 
		//从上到下 
		for(int i = u;i<=d&&sum;i++){
			res.push_back(matrix[i][r]);
			sum--;
		}
		r--;//右边界
		//从右 向左
		for(int i = r;i>=l&&sum;i--){
			res.push_back(matrix[d][i]);
			sum--;
		} 
		d--;
		//从下到上
		for(int i = d;i>=u&&sum;i--){
			res.push_back(matrix[i][l]);
			sum--;
		} 
		l++;//左边界. 
	}
	return res;
}

请添加图片描述

剑指 Offer 29. 顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
思路分析:

和上面的题类似

参考代码
vector<int> spiralOrder(vector<vector<int>>& matrix) {
	if(matrix.size()==0){
		return {};
	}
	int n = matrix.size();
	int m = matrix[0].size();
	int l = 0,r = m-1,u = 0,d = n-1;
	int sum = n*m,num=1;
	vector<int> ans;
	while(num<=sum){
		//从左到右
		for(int i =l;i<=r;i++){
			V.push_back(matrix[u][i]);
			num++;
		} 
		u++;
		
		//从上到下
		for(int i = u;i<=d;i++){
			V.push_back(matrix[i][r]);
			num++; 
		}
		r--;
		
		//从右到左
		for(int i=r;i>=l;i--){
			V.push_back(matrix[d][i]);
			num++;
		}
		d--;
		
		//从下到上 
		for(int i = d;i>=u;i--){
			V.push_back(matrix[i][l]);
			num++;
		}
		l++;
		
	} 
	return V;
}

😜😜😜😜😜 大家卷起来啊,加油!!!冲他妈的! 😜😜😜😜😜
请添加图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱编程的大李子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值