题目描述
思路解析动画文字版
记住这把尺子:同一条直线序列,用 n 算旧坐标、用 c 算新坐标。下面每一帧都在套它。
原矩阵 · 2×4 · 共 8 个元素:这是原矩阵,2 行 4 列,一共 8 个数。目标是把它们重新装成 4 行 2 列。
第一步 · 先对总数:动手前先算总数。原矩阵 2×4 是 8 个,目标 4×2 也是 8 个,正好装得下,可以重塑。要是总数对不上,后面会演,直接把原矩阵还回去。
展平第 0 个 · 读 (0,0):展平就是从左上角出发,一行读完再读下一行。先读 (0,0) 这一格,值是 1,把它放到序列第一位。
展平第 1 个 · 读 (0,1):继续沿着这一行往右走,读 (0,1) 的 2,接进序列,现在序列里有 2 个数了。
展平第 2 个 · 读 (0,2):继续沿着这一行往右走,读 (0,2) 的 3,接进序列,现在序列里有 3 个数了。
展平第 3 个 · 读 (0,3):继续沿着这一行往右走,读 (0,3) 的 4,接进序列,现在序列里有 4 个数了。
展平第 4 个 · 读 (1,0):这一行读完了,换到下一行的开头 (1,0),值 5 接到序列后面。注意是整行整行地往下走,顺序不能乱。
展平第 5 个 · 读 (1,1):继续沿着这一行往右走,读 (1,1) 的 6,接进序列,现在序列里有 6 个数了。
展平第 6 个 · 读 (1,2):继续沿着这一行往右走,读 (1,2) 的 7,接进序列,现在序列里有 7 个数了。
展平第 7 个 · 读 (1,3):继续沿着这一行往右走,读 (1,3) 的 8,接进序列,现在序列里有 8 个数了。
展平完成 · 8 个数排成一条线:整张矩阵读完了,8 个数按行序排成了一条直线。接下来把这条线按 4×2 的新形状重新装回去。
准备目标矩阵 · 4×2 空架子:搭一个 4 行 2 列的空架子,圆点表示还没填。等下把刚才那条序列,一个一个按行序填进来。
回填第 0 个 · 放进 (0,0):从序列头部拿出第一个数 1,按新宽度 c=2 算位置:0 整除 2 是第 0 行,0 取余 2 是第 0 列,填到 (0,0)。
回填第 1 个 · 放进 (0,1):接着填第 1 个数 2,落在 (0,1)。可以看到序列是怎么被切成一段段、铺进新形状的。
回填第 2 个 · 放进 (1,0):新矩阵这一行也填满了,换行。第 2 个数 3 落到 (1,0),正好是下一行的开头。
回填第 3 个 · 放进 (1,1):接着填第 3 个数 4,落在 (1,1)。可以看到序列是怎么被切成一段段、铺进新形状的。
回填第 4 个 · 放进 (2,0):新矩阵这一行也填满了,换行。第 4 个数 5 落到 (2,0),正好是下一行的开头。
回填第 5 个 · 放进 (2,1):接着填第 5 个数 6,落在 (2,1)。可以看到序列是怎么被切成一段段、铺进新形状的。
回填第 6 个 · 放进 (3,0):新矩阵这一行也填满了,换行。第 6 个数 7 落到 (3,0),正好是下一行的开头。
回填第 7 个 · 放进 (3,1):接着填第 7 个数 8,落在 (3,1)。可以看到序列是怎么被切成一段段、铺进新形状的。
重塑完成 · 4×2 新矩阵:8 个数全填完了。新矩阵每一行是 [1,2]、[3,4]、[5,6]、[7,8],数字顺序和原来一模一样,只是行列变了。这就是重塑的结果。
反例 · 想重塑成 3×3:再看一个塞不下的情况。还是这张 8 个数的矩阵,如果要重塑成 3×3,那是 9 个格子,数字不够填、总数对不上。
反例 · 直接原样返回:这种时候不强行重塑,按题目要求把原矩阵原封不动地还回去。所以总数校验一定要放在最前面。
边界先想清:能拉成一行、也能拉成一列,只要总数等;总数不等就原样还回。
两个高频追问:用编号直接转坐标可省掉中间数组;规整矩阵才能用整除取余定位。
参考代码
from __future__ import annotationsfrom typing import *from collections import *from functools import *from itertools import *from math import *from heapq import *from bisect import *class Solution: def matrixReshape(self, mat: List[List[int]], r: int, c: int) -> List[List[int]]: m, n = len(mat), len(mat[0]) if m * n != r * c: return mat ans = [[0] * c for _ in range(r)] for i in range(m * n): ans[i // c][i % c] = mat[i // n][i % n] return ans复杂度
- 时间:O(m·n),每个元素恰好搬一次,总共 m 乘 n 个,无重复无回头
- 空间:O(m·n),新矩阵要存下全部元素;不计返回结果本身则是 O(1) 额外变量
易错点
面试追问把动画讲成自己的话
追问不展平成一条线,能直接用两组行列坐标互相转换吗?
追问如果原矩阵每行长度不一定相等怎么办?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
图像渲染
LeetCode 733 · 简单 · 沿着 图论套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题