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】矩阵操作的更多相关文章

  1. Leetcode 566. Reshape the Matrix 矩阵变形(数组,模拟,矩阵操作)

    Leetcode 566. Reshape the Matrix 矩阵变形(数组,模拟,矩阵操作) 题目描述 在MATLAB中,reshape是一个非常有用的函数,它可以将矩阵变为另一种形状且保持数据 ...

  2. 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. ...

  3. iOS开发UI篇—Quartz2D使用(矩阵操作)

    iOS开发UI篇—Quartz2D使用(矩阵操作) 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: - (void)drawRect:(CGRect)r ...

  4. 【iOS】Quartz2D矩阵操作

    前面画基本图形时,画四边形是由几条直线拼接成的,现在有更简便的方法. 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: - (void)drawRect: ...

  5. MATLAB命令大全和矩阵操作大全

    转载自: http://blog.csdn.net/dengjianqiang2011/article/details/8753807 MATLAB矩阵操作大全 一.矩阵的表示在MATLAB中创建矩阵 ...

  6. Matlab、R向量与矩阵操作 z

    已有 1849 次阅读 2012-8-2 15:15 |系统分类:科研笔记|关键词:矩阵 480 window border center Matlab.R向量与矩阵操作   描    述 Matla ...

  7. Python中的矩阵操作

    Numpy 通过观察Python的自有数据类型,我们可以发现Python原生并不提供多维数组的操作,那么为了处理矩阵,就需要使用第三方提供的相关的包. NumPy 是一个非常优秀的提供矩阵操作的包.N ...

  8. poj3735—Training little cats(特殊操作转化为矩阵操作)

    题目链接:http://poj.org/problem?id=3735 题目意思: 调教猫咪:有n只饥渴的猫咪,现有一组羞耻连续操作,由k个操作组成,全部选自: 1. g i 给第i只猫咪一颗花生 2 ...

  9. 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(),然后输入 ...

  10. MATLAB矩阵操作大全

    转载自:http://blog.csdn.net/dengjianqiang2011/article/details/8753807 MATLAB矩阵操作大全 一.矩阵的表示 在MATLAB中创建矩阵 ...

随机推荐

  1. VHDL 数字时钟设计

    序言 这个是我在做FPGA界的HelloWorld--数字钟设计时随手写下的,再现了数字钟设计的过程 目标分析 时钟具有时分秒的显示,需6个数码管.为了减小功耗采用扫描法显示 按键设置时间,需要对按键 ...

  2. 【NOI 2009】诗人小G

    Problem Description 小 \(G\) 是一个出色的诗人,经常作诗自娱自乐.但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用 ...

  3. FI 业务

    f-02 post f-03 clear[account]-> f-04 post with clear fb70/f-22 f-32 clear[account]->f-28 post ...

  4. Linux命令之locate命令

    1.locate locate 命令是文件搜索命令,它的搜索速度比 find 命令更快,原因在于它不搜索具体目录, 而是搜索一个数据库,这个数据库包含本地所有文件信息.Linux系统自动创建这个数据库 ...

  5. [转]Eclipse下开发Struts奇怪异常:org.apache.struts.taglib.bean.CookieTei

    今天早上开始在Eclipse下学习struts,于是按照李兴华老师的<struts入门视频教程>一步一步地充满快乐的学习,等把登陆程序写完,打开浏览器准备运行的时候,奇怪的异常产生了,异常 ...

  6. 【Web Service】

    Restful: (Representational State Transfer  表现层[指客户端]状态[指服务器端]转化) RPC: RPC 风格的开发关注于服务器/客户端之间的方法调用, 而并 ...

  7. 前端单页面富应用(SPA)的实现

    一. 什么是单页面富应用? 单页面应用:Single Page Application 概念:Web应用即使不刷新也在不同的页面间切换,解决浏览器前进.后退等机制被破坏等问题.并且页面访问会被浏览器保 ...

  8. 【BZOJ】3214: [Zjoi2013]丽洁体

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3214 字符串长度最大不超过$5$直接$HASH$起来 首先在$T$中考虑找到最前的一个包含 ...

  9. 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 ...

  10. overload、override、overwrite的介绍

    答:(1)overload(重载),即函数重载: ①在同一个类中: ②函数名字相同: ③函数参数不同(类型不同.数量不同,两者满足其一即可): ④不以返回值类型不同作为函数重载的条件. (2)over ...