转置矩阵 图解题解
这道题到底在问什么
- 输入
- matrix=[[1,2,3],[4,5,6],[7,8,9]]
- 输出
- [[1,4,7],[2,5,8],[3,6,9]] 方阵沿对角线翻折
- 输入
- matrix=[[1,2,3],[4,5,6]]
- 输出
- [[1,4],[2,5],[3,6]] 2 行 3 列变成 3 行 2 列
先想最直接的笨办法
搭一个 4 行 2 列的空架子,圆点表示还没填。注意它的形状,行数等于原来的列数,列数等于原来的行数,正好掉了个个儿。接下来一个一个把数搬进来。(动画第 6 步)
最优解:一步一步想明白
- 3记牢这把尺子:新坐标 (i,j) 去原矩阵的 (j,i) 取数。后面每一帧都在套它。
- 4m=2 行,n=4 列,转置后会变成 4 行 2 列这是原矩阵,2 行 4 列,一共 8 个数。目标是把它翻成 4 行 2 列。先记住它现在的样子,等会儿对比着看。
- 5对角线上的 (0,0)、(1,1) 不动,其余元素以这条线为镜子对调转置的几何直觉:沿着左上到右下这条主对角线翻折。对角线上的数原地不动,其它数像照镜子一样,行列坐标对调位置。
- 6行列互换:原来 2×4,新矩阵就是 4×2,先开一个空的搭一个 4 行 2 列的空架子,圆点表示还没填。注意它的形状,行数等于原来的列数,列数等于原来的行数,正好掉了个个儿。接下来一个一个把数搬进来。
- 7第 0 个 · 原坐标 (0,0) → 新坐标 (0,0),行列互换从原矩阵 第 0 行第 0 列 起步,读到的值是 1。它要搬去新矩阵 第 0 行第 0 列,注意两个坐标对调了。
- 8ans[0][0] = matrix[0][0] = 1把 1 写进新矩阵 第 0 行第 0 列。看坐标:原来是 (0,0),现在是 (0,0),两个下标对调,这就是转置。
- 9第 1 个 · 原坐标 (1,0) → 新坐标 (0,1),行列互换接着读原矩阵 第 1 行第 0 列 的 5,准备搬到新矩阵 第 0 行第 1 列。
- 10ans[0][1] = matrix[1][0] = 5把 5 落到新矩阵 第 0 行第 1 列,第 0 行凑齐了。这一行 1、5,正好是原矩阵第 0 列那一竖排。
- 11第 2 个 · 原坐标 (0,1) → 新坐标 (1,0),行列互换新矩阵这一行填满了,换行。回原矩阵读 第 0 行第 1 列 的 2,它会落到新矩阵 第 1 行第 0 列,开启新一行。
- 12ans[1][0] = matrix[0][1] = 2把 2 写进新矩阵 第 1 行第 0 列。看坐标:原来是 (0,1),现在是 (1,0),两个下标对调,这就是转置。
- 13第 3 个 · 原坐标 (1,1) → 新坐标 (1,1),行列互换接着读原矩阵 第 1 行第 1 列 的 6,准备搬到新矩阵 第 1 行第 1 列。
- 14ans[1][1] = matrix[1][1] = 6把 6 落到新矩阵 第 1 行第 1 列,第 1 行凑齐了。这一行 2、6,正好是原矩阵第 1 列那一竖排。
- 15第 4 个 · 原坐标 (0,2) → 新坐标 (2,0),行列互换新矩阵这一行填满了,换行。回原矩阵读 第 0 行第 2 列 的 3,它会落到新矩阵 第 2 行第 0 列,开启新一行。
- 16ans[2][0] = matrix[0][2] = 3把 3 写进新矩阵 第 2 行第 0 列。看坐标:原来是 (0,2),现在是 (2,0),两个下标对调,这就是转置。
- 17第 5 个 · 原坐标 (1,2) → 新坐标 (2,1),行列互换接着读原矩阵 第 1 行第 2 列 的 7,准备搬到新矩阵 第 2 行第 1 列。
- 18ans[2][1] = matrix[1][2] = 7把 7 落到新矩阵 第 2 行第 1 列,第 2 行凑齐了。这一行 3、7,正好是原矩阵第 2 列那一竖排。
- 19第 6 个 · 原坐标 (0,3) → 新坐标 (3,0),行列互换新矩阵这一行填满了,换行。回原矩阵读 第 0 行第 3 列 的 4,它会落到新矩阵 第 3 行第 0 列,开启新一行。
- 20ans[3][0] = matrix[0][3] = 4把 4 写进新矩阵 第 3 行第 0 列。看坐标:原来是 (0,3),现在是 (3,0),两个下标对调,这就是转置。
- 21第 7 个 · 原坐标 (1,3) → 新坐标 (3,1),行列互换接着读原矩阵 第 1 行第 3 列 的 8,准备搬到新矩阵 第 3 行第 1 列。
- 22ans[3][1] = matrix[1][3] = 8把 8 落到新矩阵 第 3 行第 1 列,第 3 行凑齐了。这一行 4、8,正好是原矩阵第 3 列那一竖排。
- 238 个数全部就位,返回这个新矩阵8 个数全搬完了。新矩阵是 [1,5]、[2,6]、[3,7]、[4,8],4 行 2 列。和原来的 2 行 4 列一对比,长宽互换了,数字一个没少。
- 24新矩阵第 0 列 1、2、3、4 = 原矩阵第 0 行再回看一眼最直观的对应:新矩阵竖着的第 0 列是 1、2、3、4,正好是原矩阵横着的第 0 行。行变列、列变行,这就是转置的全貌。
⚠️ 容易写错的地方
✗ 错:想原地转置,直接在原矩阵上交换
✓ 对:非方阵必须开一个新矩阵
2×4 转置成 4×2,形状都变了,原地换不了;方阵才能原地对称交换
✗ 错:新矩阵开成 m 行 n 列
✓ 对:新矩阵是 n 行 m 列,行列数互换
转置后行数等于原来的列数,开错形状会越界或留空
✗ 错:搬运写成 ans[i][j]=matrix[i][j]
✓ 对:两个下标要对调,ans[i][j]=matrix[j][i]
下标不调等于原样复制,根本没转置
完整代码(Python / C++ / Java)
Python
from __future__ import annotations
from typing import *
from collections import *
from functools import *
from itertools import *
from math import *
from heapq import *
from bisect import *
class Solution:
def transpose(self, matrix: List[List[int]]) -> List[List[int]]:
return list(zip(*matrix))C++
#include <algorithm>
#include <array>
#include <cctype>
#include <climits>
#include <cmath>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
class Solution {
public:
vector<vector<int>> transpose(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size();
vector<vector<int>> ans(n, vector<int>(m));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
ans[i][j] = matrix[j][i];
}
}
return ans;
}
};Java
import java.util.*;
class Solution {
public int[][] transpose(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] ans = new int[n][m];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
ans[i][j] = matrix[j][i];
}
}
return ans;
}
}复杂度
时间
O(m·n)
每个元素恰好搬一次,总共 m 乘 n 个,无重复无回头
空间
O(m·n)
新矩阵要存下全部元素;不计返回结果本身,额外只用了循环变量,是 O(1)
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 转置矩阵 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
能不能原地转置,不开新矩阵?+
只有方阵能原地转置。当行数等于列数时,沿主对角线把 (i,j) 和 (j,i) 两两交换就行,注意 j 只从 i 加 1 开始,免得换两次又换回去。可本题不保证是方阵,2×4 转成 4×2 形状都变了,原地根本放不下,所以老老实实开一个 n 行 m 列的新矩阵最稳妥。
Python 那个 zip 写法是什么原理?+
zip 会把多个序列里同一位置的元素打包到一起。把原矩阵的每一行当作一个序列丢给 zip,它就把所有行的第 0 个凑成一组、第 1 个凑成一组,这每一组其实就是原矩阵的一列。原矩阵的列变成结果的行,这正好就是转置。所以一行 zip 等价于那两层循环,只是更简洁。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄声线把 转置矩阵 一步步讲透(全站 0 节语音精讲,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。