文章目录
题目
标题和出处
标题:给定行和列的和求可行矩阵
难度
5 级
题目描述
要求
给定两个非负整数数组 rowSum \texttt{rowSum} rowSum 和 colSum \texttt{colSum} colSum,其中 rowSumi \texttt{rowSumi} rowSumi 是矩阵第 i \texttt{i} i 行元素的和, colSumj \texttt{colSumj} colSumj 是矩阵第 j \texttt{j} j 列元素的和。换言之,不知道矩阵里的每个元素,但是知道每一行与每一列的和。
请找到大小为 rowSum.length × colSum.length \texttt{rowSum.length} \times \texttt{colSum.length} rowSum.length×colSum.length 的任意非负整数 矩阵,且该矩阵满足 rowSum \texttt{rowSum} rowSum 和 colSum \texttt{colSum} colSum 的要求。
返回一个二维数组表示任意一个满足题目要求的矩阵。题目保证存在至少一个满足要求的矩阵。
示例
示例 1:
输入: rowSum = 3,8, colSum = 4,7 \texttt{rowSum = 3,8, colSum = 4,7} rowSum = 3,8, colSum = 4,7
输出: \[3,0,1,7] \texttt{\[3,0,1,7]} \[3,0,1,7]
解释:
第 0 \texttt{0} 0 行: 3 + 0 = 3 = rowSum0 \texttt{3} + \texttt{0} = \texttt{3} = \texttt{rowSum0} 3+0=3=rowSum0
第 1 \texttt{1} 1 行: 1 + 7 = 8 = rowSum1 \texttt{1} + \texttt{7} = \texttt{8} = \texttt{rowSum1} 1+7=8=rowSum1
第 0 \texttt{0} 0 列: 3 + 1 = 4 = colSum0 \texttt{3} + \texttt{1} = \texttt{4} = \texttt{colSum0} 3+1=4=colSum0
第 1 \texttt{1} 1 列: 0 + 7 = 7 = colSum1 \texttt{0} + \texttt{7} = \texttt{7} = \texttt{colSum1} 0+7=7=colSum1
行和列的和都满足题目要求,且所有矩阵元素都是非负的。
另一个可行的矩阵为: \[1,2,3,5] \texttt{\[1,2,3,5]} \[1,2,3,5]。
示例 2:
输入: rowSum = 5,7,10, colSum = 8,6,8 \texttt{rowSum = 5,7,10, colSum = 8,6,8} rowSum = 5,7,10, colSum = 8,6,8
输出: \[0,5,0,6,1,0,2,0,8] \texttt{\[0,5,0,6,1,0,2,0,8]} \[0,5,0,6,1,0,2,0,8]
数据范围
- 1 ≤ rowSum.length, colSum.length ≤ 500 \texttt{1} \le \texttt{rowSum.length, colSum.length} \le \texttt{500} 1≤rowSum.length, colSum.length≤500
- 0 ≤ rowSumi, colSumi ≤ 10 8 \texttt{0} \le \texttt{rowSumi, colSumi} \le \texttt{10}^\texttt{8} 0≤rowSumi, colSumi≤108
- sum(rowSum) = sum(colSum) \texttt{sum(rowSum)} = \texttt{sum(colSum)} sum(rowSum)=sum(colSum)
解法
思路和算法
用 m m m 和 n n n 分别表示数组 rowSum \textit{rowSum} rowSum 和数组 colSum \textit{colSum} colSum 的长度,则需要构造一个 m × n m \times n m×n 的矩阵 matrix \textit{matrix} matrix,该矩阵的元素都是非负整数且满足每一行与每一列的和的要求。
对于 0 ≤ i < m 0 \le i < m 0≤i<m 和 0 ≤ j < n 0 \le j < n 0≤j<n,应满足 matrix i j ≤ rowSum i \textit{matrix}ij \le \textit{rowSum}i matrixij≤rowSumi 且 matrix i j ≤ colSum j \textit{matrix}ij \le \textit{colSum}j matrixij≤colSumj,否则矩阵的第 i i i 行或第 j j j 列的剩余元素之和将是负数,矩阵中将存在负数,不符合要求。
如果 matrix i j \textit{matrix}ij matrixij 的值过小,则矩阵的第 i i i 行或第 j j j 列的剩余元素之和将过大,导致其他行和列出现负数。为了确保得到符合要求的矩阵,可以将矩阵的每个元素取不超过上界的最大值。
依次遍历矩阵 matrix \textit{matrix} matrix 的每一个位置,对于 0 ≤ i < m 0 \le i < m 0≤i<m 和 0 ≤ j < n 0 \le j < n 0≤j<n,将 matrix i j \textit{matrix}ij matrixij 的值设为 min ( rowSum i , colSum j ) \min(\textit{rowSum}i, \textit{colSum}j) min(rowSumi,colSumj),然后将 rowSum i \textit{rowSum}i rowSumi 和 colSum j \textit{colSum}j colSumj 都减去 matrix i j \textit{matrix}ij matrixij。遍历结束之后, matrix \textit{matrix} matrix 即为符合要求的矩阵。
上述做法使用贪心策略,贪心策略的正确性说明如下。
-
由于计算矩阵 matrix \textit{matrix} matrix 中的每个元素时都将 matrix i j \textit{matrix}ij matrixij 的值设为 min ( rowSum i , colSum j ) \min(\textit{rowSum}i, \textit{colSum}j) min(rowSumi,colSumj),然后将 rowSum i \textit{rowSum}i rowSumi 和 colSum j \textit{colSum}j colSumj 都减去 matrix i j \textit{matrix}ij matrixij,因此在计算 matrix i j \textit{matrix}ij matrixij 并更新 rowSum i \textit{rowSum}i rowSumi 和 colSum j \textit{colSum}j colSumj 之后, matrix i j \textit{matrix}ij matrixij、 rowSum i \textit{rowSum}i rowSumi、 colSum j \textit{colSum}j colSumj 都一定非负,且 rowSum \textit{rowSum} rowSum 的元素之和一定与 colSum \textit{colSum} colSum 的元素之和相等。
-
将 matrix \textit{matrix} matrix 的第 0 0 0 行的所有元素都赋值之后,必有 rowSum 0 = 0 \textit{rowSum}0 = 0 rowSum0=0。理由如下:假设此时 rowSum 0 > 0 \textit{rowSum}0 > 0 rowSum0>0,则数组 colSum \textit{colSum} colSum 的所有元素都变成 0 0 0,因此初始时数组 colSum \textit{colSum} colSum 的所有元素之和小于 rowSum 0 \textit{rowSum}0 rowSum0,即待构造的矩阵的所有元素之和小于 rowSum 0 \textit{rowSum}0 rowSum0,则待构造的矩阵从第 1 1 1 行到第 m − 1 m - 1 m−1 行的所有元素之和是负数,不符合题目的前提。
-
将 matrix \textit{matrix} matrix 的第 0 0 0 行的所有元素都赋值之后,矩阵剩余的部分为 m − 1 m - 1 m−1 行和 n n n 列,此时 rowSum 0 = 0 \textit{rowSum}0 = 0 rowSum0=0, colSum \textit{colSum} colSum 的每个元素分别为矩阵的剩余 m − 1 m - 1 m−1 行元素中每一列的元素之和,可以使用相同的方法依次构造矩阵的每一行。
实现方面有一处可以优化。由于需要确保矩阵 matrix \textit{matrix} matrix 的每个元素都是非负整数,因此每个元素的最小值为 0 0 0,遍历过程中,对于当前行和列,如果对应的 rowSum \textit{rowSum} rowSum 或 colSum \textit{colSum} colSum 的元素值为 0 0 0,则可以跳过当前行或列。
代码
java
class Solution {
public int[][] restoreMatrix(int[] rowSum, int[] colSum) {
int m = rowSum.length, n = colSum.length;
int[][] matrix = new int[m][n];
int row = 0, col = 0;
while (row < m && col < n) {
int num = Math.min(rowSum[row], colSum[col]);
matrix[row][col] = num;
rowSum[row] -= num;
colSum[col] -= num;
if (rowSum[row] == 0) {
row++;
}
if (colSum[col] == 0) {
col++;
}
}
return matrix;
}
}
复杂度分析
-
时间复杂度: O ( m × n ) O(m \times n) O(m×n),其中 m m m 和 n n n 分别是数组 rowSum \textit{rowSum} rowSum 和数组 colSum \textit{colSum} colSum 的长度。需要构造 O ( m × n ) O(m \times n) O(m×n) 的矩阵,计算矩阵的每一个元素的时间都是 O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( 1 ) O(1) O(1)。注意返回值不计入空间复杂度。