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. JavaScript——执行环境、变量对象、作用域链

    前言 这几天在看<javascript高级程序设计>,看到执行环境和作用域链的时候,就有些模糊了.书中还是讲的不够具体.通过上网查资料,特来总结,以备回顾和修正. 目录: EC(执行环境或 ...

  2. PHP变量的值类型和引用类型

    PHP 变量在内存中保存的并不直接是值的内容而是值的地址.比如: $a = 1; 从表面上看起来似乎是 $a 直接存储了 1 这个值.但是实际情况是,PHP 解释器创建了变量 $a , 将值 1 存入 ...

  3. Dalvik VM 和JVM的比较

    避免出现版权问题android重写JVM 两者在编译后的文件格式区别: JVM: .java->.class->.jar DALVIK VM:.java->.class->.d ...

  4. 动态 hover 使用变相使用

    使用   onmouseover  和 onmouseout 代替 hover foreach (var menu in Model.OrderBy(x => x.Order).Where(x ...

  5. 性能跃升50%!解密自主研发的金融级分布式关系数据库OceanBase 2.0

    小蚂蚁说: 相信大家对蚂蚁金服自主研发的金融级分布式关系数据库OceanBase的故事不再陌生了.在刚刚过去的2018年天猫双11中,成交额2135亿再次创造了新纪录,而支撑今年双11的支付宝核心链路 ...

  6. Reference SoftReference WeakReference PhantomReference Cleaner 的研究与实践

    最近在看netty的时候看到直接内存的相关概念,为了更详细的了解一下具体原理,搜到了一篇不错的文章 http://lovestblog.cn/blog/2015/05/12/direct-buffer ...

  7. pl/sql编译存储过程卡住的解决方法

    oracle编译存过卡住处理: 问题描述: 在编译某个存过时,由于没提交或断网或者test没停止又重新编译,导致编译存过一直卡死 问题分析: 存过或某张表被锁 问题处理: 1.查看存过是否锁住,loc ...

  8. maven 引入外部jar包的几种方式

    方式1:dependency 本地jar包 <dependency> <groupId>com.hope.cloud</groupId> <!--自定义--& ...

  9. RNN生产唐诗

    1. 项目的RNN模型: 项目中的输入x是这样的:

  10. 在cmd中登录MySQL数据库

    mysql -uroot -p 输入密码,即可