以下为力扣官方题解
题目
在 M A T L A B MATLAB MATLAB 中,有一个非常有用的函数 r e s h a p e reshape reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
给出一个由二维数组表示的矩阵,以及两个正整数 r r r 和 c c c,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
如果具有给定参数的 r e s h a p e reshape reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。
示例1
输入: n u m s = [ [ 1 , 2 ] , [ 3 , 4 ] ] nums = [[1,2], [3,4]] nums=[[1,2],[3,4]] r = 1 , c = 4 r = 1, c = 4 r=1,c=4
输出: [ [ 1 , 2 , 3 , 4 ] ] [[1,2,3,4]] [[1,2,3,4]]
解释: 行遍历 n u m s nums nums 的结果是 [ 1 , 2 , 3 , 4 ] [1,2,3,4] [1,2,3,4]。新的矩阵是 1 ∗ 4 1 * 4 1∗4 矩阵, 用之前的元素值一行一行填充新矩阵。
示例2
输入: n u m s = [ [ 1 , 2 ] , [ 3 , 4 ] ] nums = [[1,2], [3,4]] nums=[[1,2],[3,4]] r = 2 , c = 4 r = 2, c = 4 r=2,c=4
输出: [ [ 1 , 2 ] , [ 3 , 4 ] ] [[1,2], [3,4]] [[1,2],[3,4]]
解释:没有办法将 2 ∗ 2 2 * 2 2∗2 矩阵转化为 2 ∗ 4 2 * 4 2∗4 矩阵。 所以输出原矩阵。
注意
- 给定矩阵的宽和高范围在 [ 1 , 100 ] [1, 100] [1,100]。
- 给定的 r r r 和 c c c 都是正数。
官方题解 二维数组的一唯表示
思路与算法
对于一个行数为 m m m,列数为 n n n,行列下标都从 0 0 0 开始编号的二维数组,我们可以通过下面的方式,将其中的每个元素 ( i , j ) (i, j) (i,j) 映射到整数域内,并且它们按照行优先的顺序一一对应着 [ 0 , m n ) [0, mn) [0,mn) 中的每一个整数。形象化地来说,我们把这个二维数组「排扁」成了一个一维数组。如果读者对机器学习有一定了解,可以知道这就是 f l a t t e n flatten flatten 操作。
这样的映射即为: ( i , j ) → i × n + j (i, j) \to i \times n+j (i,j)→i×n+j
同样地,我们可以将整数 x x x 映射回其在矩阵中的下标,即 { i = x / n j = x % n \begin{cases} i = x ~/~ n \\ j = x ~\%~ n \end{cases} {i=x / nj=x % n
其中 / / / 表示整数除法, % \% % 表示取模运算。
那么题目需要我们做的事情相当于:
- 将二维数组 n u m s nums nums 映射成一个一维数组;
- 将这个一维数组映射回 r r r 行 c c c 列的二维数组。
我们当然可以直接使用一个一维数组进行过渡,但我们也可以直接从二维数组 n u m s nums nums 得到 r r r 行 c c c 列的重塑矩阵:
- 设 n u m s nums nums 本身为 m m m 行 n n n 列,如果 m n ≠ r c mn \neq rc mn=rc,那么二者包含的元素个数不相同,因此无法进行重塑;
- 否则,对于 x ∈ [ 0 , m n ) x \in [0, mn) x∈[0,mn),第 x x x 个元素在 n u m s nums nums 中对应的下标为 ( x / n , x % n ) (x ~/~ n, x~\%~ n) (x / n,x % n),而在新的重塑矩阵中对应的下标为 ( x / c , x % c ) (x ~/~ c, x~\%~ c) (x / c,x % c),我们直接进行赋值即可。
代码
class Solution {
public int[][] matrixReshape(int[][] nums, int r, int c) {
int m = nums.length;
int n = nums[0].length;
if (m * n != r * c) {
return nums;
}
int[][] ans = new int[r][c];
for (int x = 0; x < m * n; ++x) {
ans[x / c][x % c] = nums[x / n][x % n];
}
return ans;
}
}
复杂度分析
- 时间复杂度: O ( r c ) O(rc) O(rc)。这里的时间复杂度是在重塑矩阵成功的前提下的时间复杂度,否则当 m n ≠ r c mn \neq rc mn=rc 时,直接返回原数组的对象,需要的时间复杂度仅为 O ( 1 ) O(1) O(1)。
- 空间复杂度: O ( 1 ) O(1) O(1)。这里的空间复杂度不包含返回的重塑矩阵需要的空间。