顺时针打印矩阵——状态机封装法

9 篇文章 0 订阅

最近面试字节跳动时,面试官给了这个题{ {1, 2, 3, 4},{5, 6 ,7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}, {17, 18, 19, 20} };虽然去年做过类似的题,但是需要申请一份空间用于记录矩阵是否被打印,这种思路被面试官直接否定,让我不许开辟空间。由于需要不断判断当前打印值的位置,逻辑上比较麻烦,但是没做出来。后来挂了,自己再考虑这个题时,觉得可以用状态机来解决这一类比较复杂的问题。结合状态机的封装,找到了一中空间复杂度为O(1)的做法,时间复杂度为矩阵的大小O(n*m)。这类逻辑判断的问题可以转化为状态机,把它分析成从一个状态到另一个状态的转换,逻辑将会变得非常清晰。同时,利用状态转换机还可以解决比较难想的动态规划问题。
在这里插入图片描述
具体的代码实现如下:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> clockPrint(vector<vector<int> > &mat) {
	vector<int> res;
	int xmin = 0, ymin = 0, xmax = mat.size()-1, ymax = mat[0].size() - 1;
	//总共需要循环的次数,也可以不加这个数,while(1)循环,满足条件直接break
	int total = xmax+1+(ymax+2) / 2;
	int curx = xmin, cury = ymin;
	while (total--) {
		//状态机的封装
		//退出条件
		if (xmin >= xmax) {
			for(cury = ymin; cury <= ymax; ++cury)
				res.push_back(mat[curx][cury]);
			break;
		}
		if (ymin >= ymax) {
			for (curx = xmin; curx <= xmax; ++curx) {
				res.push_back(mat[curx][cury]);
			}
			break;
		}
		//状态转换
		if (curx == xmin && cury == ymin) {
			for (cury = ymin; cury <= ymax; cury++) {
				res.push_back(mat[curx][cury]);
			}
			cury--;
			xmin++;
			curx++;
		}
		else if (curx == xmin && cury == ymax) {
			for (curx = xmin; curx <= xmax; ++curx) {
				res.push_back(mat[curx][cury]);
			}
			curx--;
			ymax--;
			cury--;
		}
		else if (curx == xmax && cury == ymax) {
			for (cury == ymax; cury >= ymin; cury--) {
				res.push_back(mat[curx][cury]);
			}
			cury++;
			xmax--;
			curx--;
		}
		else if (curx == xmax && cury == ymin) {
			for (curx = xmax; curx >= xmin; --curx) {
				res.push_back(mat[curx][cury]);
			}
			curx++;
			ymin++;
			cury++;
		}
	}
	return res;
}

int main()
{
	vector<vector<int> > matrix = { {1, 2, 3, 4},{5, 6 ,7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}, {17, 18, 19, 20} };
	vector<int> res = clockPrint(matrix);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值