1605. 给定行和列的和求可行矩阵
题目描述
给你两个非负整数数组 rowSum 和 colSum ,其中 rowSum[i] 是二维矩阵中第 i 行元素的和, colSum[j] 是第 j 列元素的和。换言之你不知道矩阵里的每个元素,但是你知道每一行和每一列的和。
请找到大小为 rowSum.length x colSum.length 的任意 非负整数 矩阵,且该矩阵满足 rowSum 和 colSum 的要求。
请你返回任意一个满足题目要求的二维矩阵,题目保证存在 至少一个 可行矩阵。
示例 1:
输入:rowSum = [3,8], colSum = [4,7]
输出:[[3,0],
[1,7]]
解释:
第 0 行:3 + 0 = 3 == rowSum[0]
第 1 行:1 + 7 = 8 == rowSum[1]
第 0 列:3 + 1 = 4 == colSum[0]
第 1 列:0 + 7 = 7 == colSum[1]
行和列的和都满足题目要求,且所有矩阵元素都是非负的。
另一个可行的矩阵为:[[1,2],
[3,5]]
示例 2:
输入:rowSum = [5,7,10], colSum = [8,6,8]
输出:[[0,5,0],
[6,1,0],
[2,0,8]]
示例 3:
输入:rowSum = [14,9], colSum = [6,9,8]
输出:[[0,9,5],
[6,0,3]]
示例 4:
输入:rowSum = [1,0], colSum = [1]
输出:[[1],
[0]]
示例 5:
输入:rowSum = [0], colSum = [0] 输出:[[0]]
提示:
1 <= rowSum.length, colSum.length <= 5000 <= rowSum[i], colSum[i] <= 108sum(rowSum) == sum(colSum)
解法
方法一:贪心 + 构造
思考
需要构造非负矩阵使各行之和、各列之和分别等于给定数组,且 \(\sum \textit{rowSum} = \sum \textit{colSum}\)。逐格搜索填数在 \(m,n \le 500\) 下不可行。
对位置 \((i,j)\) 放入 \(x=\min(\textit{rowSum}[i],\textit{colSum}[j])\) 并同时扣减对应行、列剩余,剩余问题仍满足行和与列和相等,因而可以继续贪心。
按行优先扫描整张表即可得到一组可行解,不必回溯。
我们可以先初始化一个 \(m\) 行 \(n\) 列的答案矩阵 \(ans\)。
接下来,遍历矩阵的每一个位置 \((i, j)\),将该位置的元素设为 \(x = min(rowSum[i], colSum[j])\),并将 \(rowSum[i]\) 和 \(colSum[j]\) 分别减去 \(x\)。遍历完所有的位置后,我们就可以得到一个满足题目要求的矩阵 \(ans\)。
以上策略的正确性说明如下:
根据题目的要求,我们知道 \(rowSum\) 和 \(colSum\) 的和是相等的,那么 \(rowSum[0]\) 一定小于等于 \(\sum_{j = 0}^{n - 1} colSum[j]\)。所以,在经过 \(n\) 次操作后,一定能够使得 \(rowSum[0]\) 为 \(0\),并且保证对任意 \(j \in [0, n - 1]\),都有 \(colSum[j] \geq 0\)。
因此,我们把原问题缩小为一个 \(m-1\) 行和 \(n\) 列的子问题,继续进行上述的操作,直到 \(rowSum\) 和 \(colSum\) 中的所有元素都为 \(0\),就可以得到一个满足题目要求的矩阵 \(ans\)。
时间复杂度 \(O(m \times n)\),空间复杂度 \(O(m \times n)\)。其中 \(m\) 和 \(n\) 分别为 \(rowSum\) 和 \(colSum\) 的长度。
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |