【LeetCode】矩阵操作
1. 矩阵旋转
将 n × n 矩阵顺时针旋转 90°。
我的思路是 “ 从外到内一层一层旋转 ”。
一个 n × n 矩阵有 (n + 1) / 2 层,每层有 4 部分,将这 4 部分旋转。
顺时针旋转 90° 就是将 matrix[n - 1 - q][p] 赋值给 matrix[p][q] 即可。

C++代码:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int i = ; i < (n + ) / ; i++) {
for (int j = i; j < n - - i; j++) {
int p = i, q = j;
int temp = matrix[p][q];
for (int k = ; k < ; k++) {
matrix[p][q] = matrix[n - - q][p];
int tp = p;
p = n - - q;
q = tp;
}
matrix[p][q] = temp;
}
}
}
答案的方法非常直观易懂!学到了!
首先将矩阵从上到下逆置,然后按对角线对称交换元素。
1 2 3 7 8 9 7 4 1
4 5 6 => 4 5 6 => 8 5 2
7 8 9 1 2 3 9 6 3
void rotate(vector<vector<int> > &matrix) {
reverse(matrix.begin(), matrix.end());
for (int i = ; i < matrix.size(); ++i) {
for (int j = i + ; j < matrix[i].size(); ++j)
swap(matrix[i][j], matrix[j][i]);
}
}
逆时针旋转的原理类似。
首先将矩阵从左到右逆置,然后按对角线对称交换元素。注意从上到下和从左到右逆置矩阵的区别!
1 2 3 3 2 1 3 6 9
4 5 6 => 6 5 4 => 2 5 8
7 8 9 9 8 7 1 4 7
void anti_rotate(vector<vector<int> > &matrix) {
for (auto vi : matrix)
reverse(vi.begin(), vi.end());
for (int i = ; i < matrix.size(); ++i) {
for (int j = i + ; j < matrix[i].size(); ++j)
swap(matrix[i][j], matrix[j][i]);
}
}
2. 矩阵螺旋遍历
给定 m x n 矩阵,以螺旋顺序遍历矩阵所有元素。
e.g. 给出如下矩阵
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
返回 [1, 2, 3, 6, 9, 8, 7, 4, 5]。
我尝试定义行标记 i 和列标记 j,第一层是 (0, 0),第二层是 (1, 1),不断循环。每次循环内改变 i 和 j,实现螺旋遍历。但实现起来代码要写的非常冗长,比如最内层只有一行或只有一列时,就会出错。于是看了别人的解法,深受启发!
方法一:死办法
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.empty()) return {};
int m = matrix.size(), n = matrix[].size();
vector<int> result(m * n);
int u = , d = m - , l = , r = n - , k = ;
while () {
for (int j = l; j <= r; j++) result[k++] = matrix[u][j];
if (++u > d) break;
for (int i = u; i <= d; i++) result[k++] = matrix[i][r];
if (--r < l) break;
for (int j = r; j >= l; j--) result[k++] = matrix[d][j];
if (--d < u) break;
for (int i = d; i >= u; i--) result[k++] = matrix[i][l];
if (++l > r) break;
}
return result;
}
定义 u(上),d(下),l(左),r(右)表示各个方向的极限下标,转了一圈后,由于 ++u、--r、--d、++l ,进入里面一层继续螺旋遍历。
此外,由于知道结果数组大小(m x n),预先分配空间并直接赋值要比 push_back 效率高。
方法二:方向矩阵法
原理:
螺旋遍历就是不断地向 4 个方向(右、下、左、上)移动。假设要处理一个 5 x 3 的矩阵,初始标志位坐标设为 (0, -1),即 '0' 的位置。
0 [ 1 2 3 4 5]
[ 6 7 8 9 10]
[11 12 13 14 15]
接下来需要移动标志位:
- 向右移动 5 位
向下移动 2 位 - 向左移动 4 位
向上移动 1 位 - 向右移动 3 位
向下移动 0 位 --> 结束
注意到方向一直是 “ 右 → 下 → 左 →上 ”,水平移动的步数是 { 5,4,3 } (5 是矩阵的行数),竖直移动的步数是 { 2,1,0 } (2 是矩阵的列数减 1)。
因此,可以构造一个方向矩阵存储所有方向,以及一个含有两个元素的数组存储水平和竖直移动的步数。这样就用一次循环代替了四次循环。
而且这样做的一个好处是,如果我们要改变遍历的起点(如从右上角元素开始),或者改变螺旋的方向(如逆时针),只需要改变方向矩阵,循环主体不需要改变。虽然更为复杂,但增加了代码的可重用性!
C++实现:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.empty()) return {};
int m = matrix.size(), n = matrix[].size();
vector<int> result;
vector<vector<int>> dir = {{, }, {, }, {, -}, {-, }};
vector<int> step = {n, m - };
int i = , j = -, dirIndex = , stepIndex = ;
while (step[stepIndex]) {
for (int k = ; k < step[stepIndex]; k++) {
i += dir[dirIndex][];
j += dir[dirIndex][];
result.push_back(matrix[i][j]);
}
step[stepIndex]--;
stepIndex = (stepIndex + ) % ;
dirIndex = (dirIndex + ) % ;
}
return result;
}
可以发现 stepIndex 刚好等于 dirIndex % 2,可以进行替换,少定义一个变量,但也降低了可读性。
3. 螺旋矩阵
给定一个整数 n,产生一个方阵,该方阵由元素 1 到 n2 以螺旋顺序填充。
e.g. n = 3,返回矩阵
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
死办法,定义 u、d、l、r。
vector<vector<int>> generateMatrix(int n) {
/* 注意 vector<vector<int>> 的初始化方式 */
vector<vector<int>> result(n, vector<int>(n));
int u = , r = n - , d = n - , l = , k = ;
while() {
for (int j = l; j <= r; j++) result[u][j] = k++;
if (++u > d) break;
for (int i = u; i <= d; i++) result[i][r] = k++;
if (--r < l) break;
for (int j = r; j >= l; j--) result[d][j] = k++;
if (--d < u) break;
for (int i = d; i >= u; i--) result[i][l] = k++;
if (++l > r) break;
}
return result;
}
也可以使用定义方向矩阵的方法。
【LeetCode】矩阵操作的更多相关文章
- Leetcode 566. Reshape the Matrix 矩阵变形(数组,模拟,矩阵操作)
Leetcode 566. Reshape the Matrix 矩阵变形(数组,模拟,矩阵操作) 题目描述 在MATLAB中,reshape是一个非常有用的函数,它可以将矩阵变为另一种形状且保持数据 ...
- Linear regression with one variable算法实例讲解(绘制图像,cost_Function ,Gradient Desent, 拟合曲线, 轮廓图绘制)_矩阵操作
%测试数据 'ex1data1.txt', 第一列为 population of City in 10,000s, 第二列为 Profit in $10,000s 1 6.1101,17.592 5. ...
- iOS开发UI篇—Quartz2D使用(矩阵操作)
iOS开发UI篇—Quartz2D使用(矩阵操作) 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: - (void)drawRect:(CGRect)r ...
- 【iOS】Quartz2D矩阵操作
前面画基本图形时,画四边形是由几条直线拼接成的,现在有更简便的方法. 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: - (void)drawRect: ...
- MATLAB命令大全和矩阵操作大全
转载自: http://blog.csdn.net/dengjianqiang2011/article/details/8753807 MATLAB矩阵操作大全 一.矩阵的表示在MATLAB中创建矩阵 ...
- Matlab、R向量与矩阵操作 z
已有 1849 次阅读 2012-8-2 15:15 |系统分类:科研笔记|关键词:矩阵 480 window border center Matlab.R向量与矩阵操作 描 述 Matla ...
- Python中的矩阵操作
Numpy 通过观察Python的自有数据类型,我们可以发现Python原生并不提供多维数组的操作,那么为了处理矩阵,就需要使用第三方提供的相关的包. NumPy 是一个非常优秀的提供矩阵操作的包.N ...
- poj3735—Training little cats(特殊操作转化为矩阵操作)
题目链接:http://poj.org/problem?id=3735 题目意思: 调教猫咪:有n只饥渴的猫咪,现有一组羞耻连续操作,由k个操作组成,全部选自: 1. g i 给第i只猫咪一颗花生 2 ...
- Matlab、R向量与矩阵操作
Matlab.R向量与矩阵操作 描 述 Matlab R 1 建立行向量v=[1 2 3 4] v=[1 2 3 4] v<-c(1,2,3,4)或v<-scan(),然后输入 ...
- MATLAB矩阵操作大全
转载自:http://blog.csdn.net/dengjianqiang2011/article/details/8753807 MATLAB矩阵操作大全 一.矩阵的表示 在MATLAB中创建矩阵 ...
随机推荐
- VHDL 数字时钟设计
序言 这个是我在做FPGA界的HelloWorld--数字钟设计时随手写下的,再现了数字钟设计的过程 目标分析 时钟具有时分秒的显示,需6个数码管.为了减小功耗采用扫描法显示 按键设置时间,需要对按键 ...
- 【NOI 2009】诗人小G
Problem Description 小 \(G\) 是一个出色的诗人,经常作诗自娱自乐.但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用 ...
- FI 业务
f-02 post f-03 clear[account]-> f-04 post with clear fb70/f-22 f-32 clear[account]->f-28 post ...
- Linux命令之locate命令
1.locate locate 命令是文件搜索命令,它的搜索速度比 find 命令更快,原因在于它不搜索具体目录, 而是搜索一个数据库,这个数据库包含本地所有文件信息.Linux系统自动创建这个数据库 ...
- [转]Eclipse下开发Struts奇怪异常:org.apache.struts.taglib.bean.CookieTei
今天早上开始在Eclipse下学习struts,于是按照李兴华老师的<struts入门视频教程>一步一步地充满快乐的学习,等把登陆程序写完,打开浏览器准备运行的时候,奇怪的异常产生了,异常 ...
- 【Web Service】
Restful: (Representational State Transfer 表现层[指客户端]状态[指服务器端]转化) RPC: RPC 风格的开发关注于服务器/客户端之间的方法调用, 而并 ...
- 前端单页面富应用(SPA)的实现
一. 什么是单页面富应用? 单页面应用:Single Page Application 概念:Web应用即使不刷新也在不同的页面间切换,解决浏览器前进.后退等机制被破坏等问题.并且页面访问会被浏览器保 ...
- 【BZOJ】3214: [Zjoi2013]丽洁体
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3214 字符串长度最大不超过$5$直接$HASH$起来 首先在$T$中考虑找到最前的一个包含 ...
- Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland dfs
D. Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes i ...
- overload、override、overwrite的介绍
答:(1)overload(重载),即函数重载: ①在同一个类中: ②函数名字相同: ③函数参数不同(类型不同.数量不同,两者满足其一即可): ④不以返回值类型不同作为函数重载的条件. (2)over ...