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. 操作 html 的时候是使用 dom 方法还是字符串拼接?

    比如一个列表里面有很多个 li,要给他们加上数据.但多少个 li 是不确定的,由后台数据确定.这时候,就要动态生成 html 内容了. 那么,这个过程, 是使用 += 方法把标签.数据进行一个个的字符 ...

  2. Vs Code搭建 TypeScript 开发环境

    一.npm install -g typescript 全局安装TypeScript   二.使用Vs Code打开已创建的文件夹,使用快捷键Ctrl+~启动终端输入命令 tsc --init 创建t ...

  3. JS实现ul,li排序效果

    <!DOCTYPE html> <html> <head> <title>js列表排序</title> <meta charset=& ...

  4. Data Structure 基本概念

    数据(data) 描述客观事物的数值 数据项(data item) 具有原子性,不可分割的最小单位 数据元素(data element)集合的个体,通常由很多数据组成 数据对象(data object ...

  5. 学习笔记7—python 列表,数组,矩阵两两转换tolist()

    from numpy import *   a1 =[[1,2,3],[4,5,6]] #列表 print('a1 :',a1) #('a1 :', [[1, 2, 3], [4, 5, 6]])   ...

  6. Codeforces 801C - Voltage Keepsake

    C. Voltage Keepsake 题目链接:http://codeforces.com/problemset/problem/801/C time limit per test 2 second ...

  7. What is a working set and how do I use it?

    //http://www.avajava.com/tutorials/lessons/what-is-a-working-set-and-how-do-i-use-it.html Working se ...

  8. SOCKET 接收图片

    using System;using System.Collections.Generic;using System.Text;using System.Net.Sockets;using Syste ...

  9. Python核心编程的四大神兽

    http://www.cnblogs.com/ssy3340/p/9747722.html

  10. BGP - 5,BGP属性

    metric,自己决定去哪个EBGP邻居 local-pre,影响AS内部IBGP邻居的路由决策 med,影响AS外部EBGP邻居的路由决策   1,BGP属性     公认传递(well-known ...