另有一个二维索引数组 indices,indices[i] = [ri, ci] 指向矩阵中的某个位置,其中 ri 和 ci 分别表示指定的行和列( 从0 开始编号)。
对 indices[i] 所指向的每个位置,应同时执行下述增量操作:
ri 行上的所有单元格,加 1 。
ci 列上的所有单元格,加 1 。
给你 m、n 和 indices 。请你在执行完所有 indices 指定的增量操作后,返回矩阵中 奇数值单元格 的数目。
示例 1:
**输入:** m = 2, n = 3, indices = [[0,1],[1,1]]
**输出:** 6
**解释:** 最开始的矩阵是 [[0,0,0],[0,0,0]]。
第一次增量操作后得到 [[1,2,1],[0,1,0]]。
最后的矩阵是 [[1,3,1],[1,3,1]],里面有 6 个奇数。
示例 2:
**输入:** m = 2, n = 2, indices = [[1,1],[0,0]]
**输出:** 0
**解释:** 最后的矩阵是 [[2,2],[2,2]],里面没有奇数。
提示:
1 <= m, n <= 50
1 <= indices.length <= 100
0 <= ri < m
0 <= ci < n
进阶: 你可以设计一个时间复杂度为 O(n + m + indices.length) 且仅用 O(n + m) 额外空间的算法来解决此问题吗?
方法一:直接模拟
直接使用使用一个 n \times m 的矩阵来存放操作的结果,对于 indices 中的每一对 [r_i, c_i],将矩阵第 r_i 行的所有数增加 1,第 c_i 列的所有数增加 1。在所有操作模拟完毕后,我们遍历矩阵,得到奇数的数目。
[sol1-Python3]
1 2 3 4 5 6 7 8 9
classSolution: defoddCells(self, m: int, n: int, indices: List[List[int]]) -> int: matrix = [[0] * n for _ inrange(m)] for x, y in indices: for j inrange(n): matrix[x][j] += 1 for row in matrix: row[y] += 1 returnsum(x % 2for row in matrix for x in row)
classSolution { public: intoddCells(int m, int n, vector<vector<int>>& indices){ int res = 0; vector<vector<int>> matrix(m, vector<int>(n)); for (auto &index : indices) { for (int i = 0; i < n; i++) { matrix[index[0]][i]++; } for (int i = 0; i < m; i++) { matrix[i][index[1]]++; } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] & 1) { res++; } } } return res; } };
classSolution { publicintoddCells(int m, int n, int[][] indices) { intres=0; int[][] matrix = newint[m][n]; for (int[] index : indices) { for (inti=0; i < n; i++) { matrix[index[0]][i]++; } for (inti=0; i < m; i++) { matrix[i][index[1]]++; } } for (inti=0; i < m; i++) { for (intj=0; j < n; j++) { if ((matrix[i][j] & 1) != 0) { res++; } } } return res; } }
publicclassSolution { publicintOddCells(int m, int n, int[][] indices) { int res = 0; int[,] matrix = newint[m, n]; foreach (int[] index in indices) { for (int i = 0; i < n; i++) { matrix[index[0], i]++; } for (int i = 0; i < m; i++) { matrix[i, index[1]]++; } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if ((matrix[i, j] & 1) != 0) { res++; } } } return res; } }
intoddCells(int m, int n, int** indices, int indicesSize, int* indicesColSize) { int res = 0; int **matrix = (int **)malloc(sizeof(int *) * m); for (int i = 0; i < m; i++) { matrix[i] = (int *)malloc(sizeof(int) * n); memset(matrix[i], 0, sizeof(int) * n); } for (int i = 0; i < indicesSize; i++) { for (int j = 0; j < n; j++) { matrix[indices[i][0]][j]++; } for (int j = 0; j < m; j++) { matrix[j][indices[i][1]]++; } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] & 1) { res++; } } free(matrix[i]); } free(matrix); return res; }
var oddCells = function(m, n, indices) { let res = 0; const matrix = newArray(m).fill(0).map(() =>newArray(n).fill(0)); for (const index of indices) { for (let i = 0; i < n; i++) { matrix[index[0]][i]++; } for (let i = 0; i < m; i++) { matrix[i][index[1]]++; } } for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if ((matrix[i][j] & 1) !== 0) { res++; } } } return res; };
funcoddCells(m, n int, indices [][]int) (ans int) { matrix := make([][]int, m) for i := range matrix { matrix[i] = make([]int, n) } for _, p := range indices { for j := range matrix[p[0]] { matrix[p[0]][j]++ } for _, row := range matrix { row[p[1]]++ } } for _, row := range matrix { for _, v := range row { ans += v % 2 } } return }
复杂度分析
时间复杂度:O(q \times (m + n) + m \times n), 其中 q 表示数组 indices 的长度,m, n 为矩阵的行数与列数。遍历数组时,每次都需要更新矩阵中一行加一列,需要的时间为 O(q \times (m + n)),最后还需要遍历矩阵,需要的时间为 O(m \times n),总的时间复杂度为 O(q \times (m + n) + m \times n)。
空间复杂度:O(m \times n),其中 m, n 为矩阵的行数与列数。需要存储矩阵的所有元素。
classSolution: defoddCells(self, m: int, n: int, indices: List[List[int]]) -> int: rows = [0] * m cols = [0] * n for x, y in indices: rows[x] += 1 cols[y] += 1 returnsum((row + col) % 2for row in rows for col in cols)
[sol2-C++]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: intoddCells(int m, int n, vector<vector<int>>& indices){ vector<int> rows(m), cols(n); for (auto & index : indices) { rows[index[0]]++; cols[index[1]]++; } int res = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if ((rows[i] + cols[j]) & 1) { res++; } } } return res; } };
[sol2-Java]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { publicintoddCells(int m, int n, int[][] indices) { int[] rows = newint[m]; int[] cols = newint[n]; for (int[] index : indices) { rows[index[0]]++; cols[index[1]]++; } intres=0; for (inti=0; i < m; i++) { for (intj=0; j < n; j++) { if (((rows[i] + cols[j]) & 1) != 0) { res++; } } } return res; } }
[sol2-C#]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
publicclassSolution { publicintOddCells(int m, int n, int[][] indices) { int[] rows = newint[m]; int[] cols = newint[n]; foreach (int[] index in indices) { rows[index[0]]++; cols[index[1]]++; } int res = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (((rows[i] + cols[j]) & 1) != 0) { res++; } } } return res; } }
intoddCells(int m, int n, int** indices, int indicesSize, int* indicesColSize) { int res = 0; int *rows = (int *)malloc(sizeof(int) * m); int *cols = (int *)malloc(sizeof(int) * n); memset(rows, 0, sizeof(int) * m); memset(cols, 0, sizeof(int) * n); for (int i = 0; i < indicesSize; i++) { rows[indices[i][0]]++; cols[indices[i][1]]++; } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if ((rows[i] + cols[j]) & 1) { res++; } } } free(rows); free(cols); return res; }
[sol2-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
var oddCells = function(m, n, indices) { const rows = newArray(m).fill(0); const cols = newArray(n).fill(0); for (const index of indices) { rows[index[0]]++; cols[index[1]]++; } let res = 0; for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (((rows[i] + cols[j]) & 1) !== 0) { res++; } } } return res; };
[sol2-Golang]
1 2 3 4 5 6 7 8 9 10 11 12 13 14
funcoddCells(m, n int, indices [][]int) (ans int) { rows := make([]int, m) cols := make([]int, n) for _, p := range indices { rows[p[0]]++ cols[p[1]]++ } for _, row := range rows { for _, col := range cols { ans += (row + col) % 2 } } return }
复杂度分析
时间复杂度:O(q + m \times n), 其中 q 表示数组 indices 的长度,m, n 为矩阵的行数与列数。遍历数组时需要的时间为 O(q),最后还需要遍历矩阵,需要的时间为 O(m \times n),因此总的时间复杂度为 O(q + m \times n)。
空间复杂度:O(m + n),其中 m, n 为矩阵的行数与列数。需要存储矩阵的行数统计与列数统计。
var oddCells = function(m, n, indices) { const rows = newArray(m).fill(0); const cols = newArray(n).fill(0); for (const index of indices) { rows[index[0]]++; cols[index[1]]++; } let oddx = 0, oddy = 0; for (let i = 0; i < m; i++) { if ((rows[i] & 1) !== 0) { oddx++; } } for (let i = 0; i < n; i++) { if ((cols[i] & 1) !== 0) { oddy++; } } return oddx * (n - oddy) + (m - oddx) * oddy; };
[sol3-Golang]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
funcoddCells(m, n int, indices [][]int)int { rows := make([]int, m) cols := make([]int, n) for _, p := range indices { rows[p[0]]++ cols[p[1]]++ } oddx := 0 for _, row := range rows { oddx += row % 2 } oddy := 0 for _, col := range cols { oddy += col % 2 } return oddx*(n-oddy) + (m-oddx)*oddy }
复杂度分析
时间复杂度:O(q + m + n), 其中 q 表示数组 indices 的长度,m, n 为矩阵的行数与列数。
空间复杂度:O(m + n),其中 m, n 为矩阵的行数与列数。需要存储矩阵的行数统计与列数统计。