1253-重构 2 行二进制矩阵

Raphael Liu Lv10

给你一个 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 <= 10^5
  • 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} \neq \textit{upper} + \textit{lower 时,一定不存在满足题意的矩阵。然后当第 i 列 colsum}[i] = 2 时,第 i 列的两个元素只能都为 1。那么如果 two} > \min{\textit{upper}, \textit{lower}\ 时,此时同样不存在满足题意的矩阵。

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

  • colsum}[i] = 0 时:res}[0][i] = \textit{res}[1][i] = 0。
  • colsum}[i] = 2 时:res}[0][i] = \textit{res}[1][i] = 1。

所以现在我们只关注 colsum}[i] = 1 的情况。首先我们将初始的 upper 和 lower 减去数组 colsum 中 2 的个数 two,那么现在 upper} + \textit{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] 为满足题意的二进制矩阵,正确性得证。

代码

[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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;
}
};
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
public List<List<Integer>> reconstructMatrix(int upper, int lower, int[] colsum) {
int n = colsum.length;
int sum = 0, two = 0;
for (int i = 0; i < n; ++i) {
if (colsum[i] == 2) {
++two;
}
sum += colsum[i];
}
if (sum != upper + lower || Math.min(upper, lower) < two) {
return new ArrayList<List<Integer>>();
}
upper -= two;
lower -= two;
List<List<Integer>> res = new ArrayList<List<Integer>>();
for (int i = 0; i < 2; ++i) {
res.add(new ArrayList<Integer>());
}
for (int i = 0; i < n; ++i) {
if (colsum[i] == 2) {
res.get(0).add(1);
res.get(1).add(1);
} else if (colsum[i] == 1) {
if (upper > 0) {
res.get(0).add(1);
res.get(1).add(0);
--upper;
} else {
res.get(0).add(0);
res.get(1).add(1);
}
} else {
res.get(0).add(0);
res.get(1).add(0);
}
}
return res;
}
}
[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution:
def reconstructMatrix(self, upper: int, lower: int, colsum: List[int]) -> List[List[int]]:
n = len(colsum)
sum_val = 0
two_num = 0
for i in range(n):
if colsum[i] == 2:
two_num += 1
sum_val += colsum[i]
if sum_val != upper + lower or min(upper, lower) < two_num:
return []
upper -= two_num
lower -= two_num
res = [[0] * n for _ in range(2)]
for i in range(n):
if colsum[i] == 2:
res[0][i] = res[1][i] = 1
elif colsum[i] == 1:
if upper > 0:
res[0][i] = 1
upper -= 1
else:
res[1][i] = 1
return res
[sol1-Go]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
func reconstructMatrix(upper int, lower int, colsum []int) [][]int {
n := len(colsum)
sumVal := 0
twoNum := 0
for i := 0; i < n; i++ {
if colsum[i] == 2 {
twoNum++
}
sumVal += colsum[i]
}
if sumVal != upper + lower || math.Min(float64(upper), float64(lower)) < float64(twoNum) {
return [][]int{}
}
upper -= twoNum
lower -= twoNum
res := make([][]int, 2)
for i := 0; i < 2; i++ {
res[i] = make([]int, n)
}
for i := 0; i < n; i++ {
if colsum[i] == 2 {
res[0][i], res[1][i] = 1, 1
} else if colsum[i] == 1 {
if upper > 0 {
res[0][i] = 1
upper--
} else {
res[1][i] = 1
}
}
}
return res
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var reconstructMatrix = function(upper, lower, colsum) {
let n = colsum.length;
let sumVal = 0;
let twoNum = 0;
for (let i = 0; i < n; i++) {
if (colsum[i] == 2) {
twoNum++;
}
sumVal += colsum[i];
}
if (sumVal != upper + lower || Math.min(upper, lower) < twoNum) {
return [];
}
upper -= twoNum;
lower -= twoNum;
let res = Array.from({ length: 2 }, () => new Array(n).fill(0));
for (let 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;
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Solution {
public IList<IList<int>> ReconstructMatrix(int upper, int lower, int[] colsum) {
int n = colsum.Length;
int sum = 0, two = 0;
for (int i = 0; i < n; ++i) {
if (colsum[i] == 2) {
++two;
}
sum += colsum[i];
}
if (sum != upper + lower || Math.Min(upper, lower) < two) {
return new List<IList<int>>();
}
upper -= two;
lower -= two;
IList<IList<int>> res = new List<IList<int>>();
for (int i = 0; i < 2; ++i) {
res.Add(new List<int>());
}
for (int i = 0; i < n; ++i) {
if (colsum[i] == 2) {
res[0].Add(1);
res[1].Add(1);
} else if (colsum[i] == 1) {
if (upper > 0) {
res[0].Add(1);
res[1].Add(0);
--upper;
} else {
res[0].Add(0);
res[1].Add(1);
}
} else {
res[0].Add(0);
res[1].Add(0);
}
}
return res;
}
}
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#define MIN(a, b) ((a) < (b) ? (a) : (b))

int** reconstructMatrix(int upper, int lower, int* colsum, int colsumSize, int* returnSize, int** returnColumnSizes) {
int n = colsumSize;
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) {
*returnSize = 0;
return NULL;
}
upper -= two;
lower -= two;
int **res = (int **)malloc(sizeof(int *) * 2);
*returnColumnSizes = (int *)malloc(sizeof(int) * 2);
for (int i = 0; i < 2; i++) {
res[i] = (int *)calloc(n, sizeof(int));
(*returnColumnSizes)[i] = n;
}
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;
}
}
}
*returnSize = 2;
return res;
}

复杂度分析

  • 时间复杂度:O(n),其中 n 为数组 colsum 的长度。
  • 空间复杂度:O(1),仅使用常量空间。注意返回的结果数组不计入空间开销。
 Comments
On this page
1253-重构 2 行二进制矩阵