文章目录
题目
标题和出处
标题:重构 2 行二进制矩阵
难度
6 级
题目描述
要求
给定一个 2 \texttt{2} 2 行 n \texttt{n} n 列的矩阵的以下信息:
- 矩阵是一个二进制矩阵,这意味着矩阵中的每个元素都是 0 \texttt{0} 0 或 1 \texttt{1} 1。
- 第 0 \texttt{0} 0 行的元素之和为 upper \texttt{upper} upper。
- 第 1 \texttt{1} 1 行的元素之和为 lower \texttt{lower} lower。
- 第 i \texttt{i} i 列(下标从 0 \texttt{0} 0 开始)的元素之和为 colsumi \texttt{colsumi} colsumi,其中 colsum \texttt{colsum} colsum 是一个长度为 n \texttt{n} n 的整数数组。
要求利用 upper \texttt{upper} upper、 lower \texttt{lower} lower 和 colsum \texttt{colsum} colsum 重构这个矩阵。
以二维整数数组的形式返回。
如果有多个不同的答案,则返回任意一个。
如果不存在符合要求的答案,则返回一个空的二维数组。
示例
示例 1:
输入: upper = 2, lower = 1, colsum = 1,1,1 \texttt{upper = 2, lower = 1, colsum = 1,1,1} upper = 2, lower = 1, colsum = 1,1,1
输出: \[1,1,0,0,0,1] \texttt{\[1,1,0,0,0,1]} \[1,1,0,0,0,1]
解释: \[1,0,1,0,1,0] \texttt{\[1,0,1,0,1,0]} \[1,0,1,0,1,0] 和 \[0,1,1,1,0,0] \texttt{\[0,1,1,1,0,0]} \[0,1,1,1,0,0] 也是正确答案。
示例 2:
输入: upper = 2, lower = 3, colsum = 2,2,1,1 \texttt{upper = 2, lower = 3, colsum = 2,2,1,1} upper = 2, lower = 3, colsum = 2,2,1,1
输出: \[\] \texttt{\[\]} \[\]
示例 3:
输入: upper = 5, lower = 5, colsum = 2,1,2,0,1,0,1,2,0,1 \texttt{upper = 5, lower = 5, colsum = 2,1,2,0,1,0,1,2,0,1} upper = 5, lower = 5, colsum = 2,1,2,0,1,0,1,2,0,1
输出: \[1,1,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1,1,0,1] \texttt{\[1,1,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1,1,0,1]} \[1,1,1,0,1,0,0,1,0,0,1,0,1,0,0,0,1,1,0,1]
数据范围
- 1 ≤ colsum.length ≤ 10 5 \texttt{1} \le \texttt{colsum.length} \le \texttt{10}^\texttt{5} 1≤colsum.length≤105
- 0 ≤ upper, lower ≤ colsum.length \texttt{0} \le \texttt{upper, lower} \le \texttt{colsum.length} 0≤upper, lower≤colsum.length
- 0 ≤ colsumi ≤ 2 \texttt{0} \le \texttt{colsumi} \le \texttt{2} 0≤colsumi≤2
解法
思路和算法
如果存在符合要求的矩阵,则 upper + lower \textit{upper} + \textit{lower} upper+lower 必须等于数组 colsum \textit{colsum} colsum 的元素之和。如果 upper + lower \textit{upper} + \textit{lower} upper+lower 不等于 colsum \textit{colsum} colsum 的元素之和,则一定不存在符合要求的矩阵,返回空二维数组。
当 upper + lower \textit{upper} + \textit{lower} upper+lower 等于 colsum \textit{colsum} colsum 的元素之和时,根据给定的 upper \textit{upper} upper、 lower \textit{lower} lower 和 colsum \textit{colsum} colsum 构造矩阵,构造的过程中判断是否存在符合要求的矩阵。
用 matrix \textit{matrix} matrix 表示构造的矩阵。对于 0 ≤ i < n 0 \le i < n 0≤i<n,存在如下结论。
-
当 colsum i = 0 \textit{colsum}i = 0 colsumi=0 时,一定有 matrix 0 i = matrix 1 i = 0 \textit{matrix}0i = \textit{matrix}1i = 0 matrix0i=matrix1i=0。
-
当 colsum i = 2 \textit{colsum}i = 2 colsumi=2 时,一定有 matrix 0 i = matrix 1 i = 1 \textit{matrix}0i = \textit{matrix}1i = 1 matrix0i=matrix1i=1。
-
当 colsum i = 1 \textit{colsum}i = 1 colsumi=1 时, matrix 0 i \textit{matrix}0i matrix0i 和 matrix 1 i \textit{matrix}1i matrix1i 中存在一个 0 0 0 和一个 1 1 1。
由于当 colsum i = 0 \textit{colsum}i = 0 colsumi=0 或 colsum i = 2 \textit{colsum}i = 2 colsumi=2 时的构造矩阵方案唯一,当 colsum i = 1 \textit{colsum}i = 1 colsumi=1 时的构造矩阵方案不唯一,因此需要考虑 colsum i = 1 \textit{colsum}i = 1 colsumi=1 的构造矩阵方案。
对于 colsum \textit{colsum} colsum 中的等于 0 0 0 或 2 2 2 的值,其所在列对应的矩阵中的两行的值相同,只有 colsum \textit{colsum} colsum 中的等于 1 1 1 的值所在列对应的矩阵中的两行的值不同。记 diff = upper − lower \textit{diff} = \textit{upper} - \textit{lower} diff=upper−lower,则矩阵第 0 0 0 行的 1 1 1 的个数与矩阵第 1 1 1 行的 1 1 1 的个数之差为 diff \textit{diff} diff,假设有 x x x 个下标 i i i 满足 matrix i 0 = 1 \textit{matrix}i0 = 1 matrixi0=1 且 matrix i 1 = 0 \textit{matrix}i1 = 0 matrixi1=0,有 y y y 个下标 i i i 满足 matrix i 0 = 0 \textit{matrix}i0 = 0 matrixi0=0 且 matrix i 1 = 1 \textit{matrix}i1 = 1 matrixi1=1,则 x − y = diff x - y = \textit{diff} x−y=diff, x + y x + y x+y 等于 colsum \textit{colsum} colsum 中的 1 1 1 的个数。
由于 upper \textit{upper} upper 与 lower \textit{lower} lower 之差的产生原因是矩阵同一列的两行的值不同,即 colsum \textit{colsum} colsum 中的元素 1 1 1 所在列对应的矩阵中的两行的值不同,遍历 colsum \textit{colsum} colsum 的过程中每次遇到一个 1 1 1 之后剩余的 1 1 1 的个数更少,因此应在遍历过程中减少 upper \textit{upper} upper 与 lower \textit{lower} lower 之差的绝对值。
构造矩阵的具体做法是,对于每个 0 ≤ i < n 0 \le i < n 0≤i<n,根据 colsum i \textit{colsum}i colsumi 的值,执行如下操作。
-
如果 colsum i = 0 \textit{colsum}i = 0 colsumi=0,则将 matrix 0 i \textit{matrix}0i matrix0i 和 matrix 1 i \textit{matrix}1i matrix1i 的值都设为 0 0 0。
-
如果 colsum i = 2 \textit{colsum}i = 2 colsumi=2,则将 matrix 0 i \textit{matrix}0i matrix0i 和 matrix 1 i \textit{matrix}1i matrix1i 的值都设为 1 1 1,并将 upper \textit{upper} upper 和 lower \textit{lower} lower 的值都减 1 1 1。
-
如果 colsum i = 1 \textit{colsum}i = 1 colsumi=1,则比较 upper \textit{upper} upper 和 lower \textit{lower} lower,执行如下操作。
-
如果 upper > lower \textit{upper} > \textit{lower} upper>lower,则将 matrix 0 i \textit{matrix}0i matrix0i 的值设为 1 1 1,将 matrix 1 i \textit{matrix}1i matrix1i 的值设为 0 0 0,并将 upper \textit{upper} upper 的值减 1 1 1。
-
如果 upper < lower \textit{upper} < \textit{lower} upper<lower,则将 matrix 0 i \textit{matrix}0i matrix0i 的值设为 0 0 0,将 matrix 1 i \textit{matrix}1i matrix1i 的值设为 1 1 1,并将 lower \textit{lower} lower 的值减 1 1 1。
-
如果 upper = lower \textit{upper} = \textit{lower} upper=lower,则可以将 matrix \textit{matrix} matrix 的第 i i i 列中的任意一个值设为 1 1 1。此处将 upper = lower \textit{upper} = \textit{lower} upper=lower 与 upper > lower \textit{upper} > \textit{lower} upper>lower 归入同一种情况。
-
如果遍历过程中出现 upper < 0 \textit{upper} < 0 upper<0 或 lower < 0 \textit{lower} < 0 lower<0,则一定不存在符合要求的矩阵,返回空二维数组。如果遍历结束之后没有出现矛盾之处,则返回矩阵 matrix \textit{matrix} matrix。
上述做法使用贪心策略,贪心策略的正确性说明如下。
-
当 colsum i = 1 \textit{colsum}i = 1 colsumi=1 且 upper ≠ lower \textit{upper} \ne \textit{lower} upper=lower 时,考虑 upper > lower \textit{upper} > \textit{lower} upper>lower 的情况,可以使用同样的方法证明 upper < lower \textit{upper} < \textit{lower} upper<lower 的情况。当 upper > lower \textit{upper} > \textit{lower} upper>lower 时,如果将第 i i i 列的值设为 matrix 0 i = 0 \textit{matrix}0i = 0 matrix0i=0 且 matrix 1 i = 1 \textit{matrix}1i = 1 matrix1i=1,则当仍存在符合要求的矩阵时,一定存在大于 i i i 的列下标 j j j 满足 colsum j = 1 \textit{colsum}j = 1 colsumj=1,第 j j j 列的值设为 matrix 0 j = 1 \textit{matrix}0j = 1 matrix0j=1 且 matrix 1 j = 0 \textit{matrix}1j = 0 matrix1j=0,将 matrix \textit{matrix} matrix 的第 i i i 列和第 j j j 列交换之后仍符合要求。因此当 upper > lower \textit{upper} > \textit{lower} upper>lower 时,将第 i i i 列的值设为 matrix 0 i = 1 \textit{matrix}0i = 1 matrix0i=1 且 matrix 1 i = 0 \textit{matrix}1i = 0 matrix1i=0,有最大的可能得到符合要求的矩阵。
-
由于当 colsum i = 1 \textit{colsum}i = 1 colsumi=1 时总是将矩阵的元素和较大行的当前元素设为 1 1 1,将 upper \textit{upper} upper 和 lower \textit{lower} lower 中的较大值减 1 1 1,因此如果遍历过程中出现 upper < 0 \textit{upper} < 0 upper<0 或 lower < 0 \textit{lower} < 0 lower<0,则一定是因为 colsum \textit{colsum} colsum 中有过多的 2 2 2,导致在遍历结束之前就出现 upper = 0 \textit{upper} = 0 upper=0 和 lower = 0 \textit{lower} = 0 lower=0 的情况,此时对于元素和为 1 1 1 的列无论如何调整都不可能得到符合要求的矩阵。
代码
java
class Solution {
static final List<List<Integer>> EMPTY = new ArrayList<List<Integer>>();
public List<List<Integer>> reconstructMatrix(int upper, int lower, int[] colsum) {
int sum = 0;
for (int num : colsum) {
sum += num;
}
if (sum != upper + lower) {
return EMPTY;
}
List<Integer> row0 = new ArrayList<Integer>();
List<Integer> row1 = new ArrayList<Integer>();
int n = colsum.length;
for (int i = 0; i < n; i++) {
if (colsum[i] == 2) {
row0.add(1);
row1.add(1);
upper--;
lower--;
} else if (colsum[i] == 0) {
row0.add(0);
row1.add(0);
} else {
if (upper >= lower) {
row0.add(1);
row1.add(0);
upper--;
} else {
row0.add(0);
row1.add(1);
lower--;
}
}
if (upper < 0 || lower < 0) {
return EMPTY;
}
}
List<List<Integer>> matrix = new ArrayList<List<Integer>>();
matrix.add(row0);
matrix.add(row1);
return matrix;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 colsum \textit{colsum} colsum 的长度。需要构造 2 × n 2 \times n 2×n 的矩阵,填入每个元素的时间是 O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( 1 ) O(1) O(1)。注意返回值不计入空间复杂度。