【1253. 重构 2 行二进制矩阵】

文章描述了一道LeetCode上的编程问题,要求根据给定的上行和、下行和以及每列的和重构一个2行的二进制矩阵。通过贪心算法,当条件满足时可以构建出符合要求的矩阵,否则返回空数组。解决方案包括检查条件、初始化矩阵和遍历列进行填充。
摘要由CSDN通过智能技术生成

来源:力扣(LeetCode)

描述:

给你一个 2n 列的二进制数组:

  • 矩阵是一个二进制矩阵,这意味着矩阵中的每个元素不是 0 就是 1
  • 0 行的元素之和为 upper
  • 1 行的元素之和为 lower
  • i 列(从 0 开始编号)的元素之和为 colsum[i]colsum 是一个长度为 n 的整数数组。

你需要利用 upperlowercolsum 来重构这个矩阵,并以二维整数数组的形式返回它。

如果有多个不同的答案,那么任意一个都可以通过本题。

如果不存在符合要求的答案,就请返回一个空的二维数组。

示例 1:

输入:upper = 2, lower = 1, colsum = [1,1,1]
输出:[[1,1,0],[0,0,1]]
解释:[[1,0,1],[0,1,0]][[0,1,1],[1,0,0]] 也是正确答案。

示例 2:

输入:upper = 2, lower = 3, colsum = [2,2,1,1]
输出:[]

示例 3:

输入: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]]

提示:

  • 1 <= colsum.length <= 105
  • 0 <= upper, lower <= colsum.length
  • 0 <= colsum[i] <= 2

方法:贪心

思路与算法

我们需要求得任意一个 2 行 n 列的二进制数组(其中行和列的序号从 0 开始),满足数组中的每一个元素不是 0 就是 1,并且第 0 行的元素和为 upper,第 1 行的元素和为 lower,第 i 列的元素之和为 colsum[i],若不存在直接返回一个空的二维数组即可。

记 sum 为数组 colsum 的元素和,two 为数组 colsum 中 2 的个数。明显当 sum ≠ upper + lower 时,一定不存在满足题意的矩阵。然后当第 i 列 colsum[i] = 2 时,第 i 列的两个元素只能都为 1。那么如果 two > min{upper, lower} 时,此时同样不存在满足题意的矩阵。

否则我们一定可以通过下述的方案来构造一个符合题目要求的矩阵。设结果矩阵为 res[2][n]。当第 i 列 colsum[i] 等于 0 或者 2 时只有一种情况:

  • colsum[i] = 0 时:res[0][i] = res[1][i] = 0。
  • colsum[i] = 2 时:res[0][i] = res[1][i] = 1。

所以现在我们只关注 colsum[i] = 1 的情况。首先我们将初始的 upper 和 lower 减去数组 colsum 中 2 的个数 two,那么现在 upper + lower 为数组 colsum 中 1 的个数。那么我们将从左到右遍历 colsum 中的每一列,若第 i 列 colsum[i] 等于 1:

  • 若 upper > 0,则我们在该列的第一行放置 1,第二行放置 0:res[0][i] = 1,res[1][i] = 0,并且 upper 减一。
  • 否则我们在该列的第一行放置 0,第二行放置 1:res[0][i] = 0,res[1][i] = 1。

当遍历完成后就得到了符合题目要求的矩阵 res[2][n]。现在给出该方案的正确性证明:从上述的构造过程可以得到,整个数组中除了 1 就 0,每一列中 1 的个数完全符合数组 colsum 描述,且在第一行中我们共放置了 upper 个 1,第二行共放置了 lower 个 1。因此这样构造的矩阵 res[2][n] 为满足题意的二进制矩阵,正确性得证。

代码:

class Solution {
public:
    vector<vector<int>> reconstructMatrix(int upper, int lower, vector<int>& colsum) {
        int n = colsum.size();
        int sum = 0, two = 0;
        for (int i = 0; i < n; ++i) {
            if (colsum[i] == 2) {
                ++two;
            }
            sum += colsum[i];
        }
        if (sum != upper + lower || min(upper, lower) < two) {
            return {};
        }
        upper -= two;
        lower -= two;
        vector<vector<int>> res(2, vector<int>(n, 0));
        for (int i = 0; i < n; ++i) {
            if (colsum[i] == 2) {
                res[0][i] = res[1][i] = 1;
            } else if (colsum[i] == 1) {
                if (upper > 0) {
                    res[0][i] = 1;
                    --upper;
                } else {
                    res[1][i] = 1;
                }
            }
        }
        return res;
    }
};

执行用时:60 ms, 在所有 C++ 提交中击败了65.12%的用户
内存消耗:56.1 MB, 在所有 C++ 提交中击败了96.12%的用户
复杂度分析
时间复杂度:O(n),其中 n 为数组 colsum 的长度。
空间复杂度:O(1),仅使用常量空间。注意返回的结果数组不计入空间开销。
author:LeetCode-Solution

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千北@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值