贪心题目:给定行和列的和求可行矩阵

文章目录

题目

标题和出处

标题:给定行和列的和求可行矩阵

出处:1605. 给定行和列的和求可行矩阵

难度

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 即为符合要求的矩阵。

上述做法使用贪心策略,贪心策略的正确性说明如下。

  1. 由于计算矩阵 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 的元素之和相等。

  2. 将 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 行的所有元素之和是负数,不符合题目的前提。

  3. 将 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)。注意返回值不计入空间复杂度。

相关推荐
伟大的车尔尼1 天前
贪心题目:需要教语言的最少人数
贪心
lvwangshu2 天前
T3 涂鸦带师 题解
题解·贪心·倍增·技巧·思维好题·断环成链
吞下星星的少年·-·4 天前
牛客周赛 119B题(贪心)
算法·贪心
吞下星星的少年·-·5 天前
Div.2 CF edu195A题(数学,贪心)
数学·算法·贪心
伟大的车尔尼6 天前
贪心题目:交换一次的先前排列
贪心
lvwangshu7 天前
CF1882D Tree XOR 题解
动态规划·题解·贪心·dp·树形dp·换根dp·性质题·思维好题·推导题
伟大的车尔尼8 天前
贪心题目:救生艇
贪心
Jasmine_llq8 天前
《P8816 [CSP-J 2022] 上升点列》
数据结构·算法·贪心·排序·二维动态规划 dp·类背包状态转移
lvwangshu9 天前
字符串 题解
字符串·trie·题解·贪心·技巧·性质题·思维好题