贪心题目:重构 2 行二进制矩阵

文章目录

题目

标题和出处

标题:重构 2 行二进制矩阵

出处:1253. 重构 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。

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

  1. 当 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,有最大的可能得到符合要求的矩阵。

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

相关推荐
伟大的车尔尼2 天前
贪心题目:吃苹果的最大数目
贪心
吞下星星的少年·-·11 天前
Div.2 CF 1130B题(构造,贪心)
算法·贪心·构造
伟大的车尔尼14 天前
贪心题目:加油站
贪心
伟大的车尔尼15 天前
贪心题目:给定行和列的和求可行矩阵
贪心
伟大的车尔尼16 天前
贪心题目:需要教语言的最少人数
贪心
lvwangshu17 天前
T3 涂鸦带师 题解
题解·贪心·倍增·技巧·思维好题·断环成链
吞下星星的少年·-·19 天前
牛客周赛 119B题(贪心)
算法·贪心
吞下星星的少年·-·20 天前
Div.2 CF edu195A题(数学,贪心)
数学·算法·贪心
伟大的车尔尼21 天前
贪心题目:交换一次的先前排列
贪心