等和矩阵分割II
#3548 等和矩阵分割II
先考虑水平分割的情况:
- 计算矩阵所有元素的和total、矩阵每行的和row_sum[i]
- 遍历所有的行数,有三种情况:
- 找到一个前i行的和等于total/2的情况,则可以不需要删除元素,直接进行分割
- 发现前i行的和 < total/2, 则需要从[i+1, grid.size()]行中找到一个元素等于(total/2 - 前i行和),如果可以找到,则可以进行分割。否则i++;
- 发现前i行的和 > total/2, 则需要从[0, i]行中找到下一个元素等于(前i行和 - total/2), 如果可以找到,则进行分割。否则i++;
如上就是整体的逻辑,代码实现上需要注意,从子矩阵中找到一个元素可以使用map来加速。同时我们需要保证矩阵中剩余的数字是联通的,就又有以下三种情况:
- 子矩阵的大小 > 2*2, 可以去掉任何一个元素,剩下的都是联通的
- 只有单行,只能去除首位的元素,
- 只有单列,同样只能去除首位的元素
在考虑垂直分割的情况,实际上可以使用一个辅助矩阵,将入参转换一下,就可以直接进行计算。
需要注意到是求和或者map的get操作,可能会让int类型溢出,需要使用int64_t来存储。 WA了好几次。
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| 代码如下:
```c++ class Solution { public: bool canPartitionGrid(vector<vector<int>> &grid) { int m = grid.size(), n = grid[0].size(); vector<int64_t> row_sum(m), col_sum(n); int64_t total = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { total += grid[i][j]; row_sum[i] += grid[i][j]; col_sum[j] += grid[i][j]; } } if (scan(grid, row_sum, total)) { return true; }
vector<vector<int>> transposed_grid(n, vector<int>(m)); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { transposed_grid[j][i] = grid[i][j]; } } return scan(transposed_grid, col_sum, total); }
private: bool scan(const vector<vector<int>> &grid, const vector<int64_t> &line_sum, const int64_t total) { int m = grid.size(), n = grid[0].size(); unordered_map<int64_t, int64_t> up_map, down_map; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { down_map[grid[i][j]]++; } } int64_t up_sum = 0; for (int i = 0; i < m - 1; i++) { for (int j = 0; j < n; j++) { up_map[grid[i][j]]++; down_map[grid[i][j]]--; if (down_map[grid[i][j]] == 0) { down_map.erase(grid[i][j]); } up_sum += grid[i][j]; }
int64_t down_sum = total - up_sum; if (up_sum == down_sum) { return true; }
int64_t target = std::llabs(up_sum - down_sum); int h = (up_sum > down_sum ? i + 1 : m - i - 1); int w = n; unordered_map<int64_t, int64_t> &target_map = (up_sum > down_sum ? up_map : down_map);
if (!target_map.count(target)) { continue; }
if (h >= 2 && w >= 2) { return true; }
if (h == 1 && w >= 2) { int row = (up_sum > down_sum) ? i : m - 1; if (grid[row][0] == target || grid[row][n - 1] == target) { return true; } }
if (h >= 2 && w == 1) { int top = (up_sum > down_sum) ? 0 : i + 1; int bot = top + h - 1; if (grid[top][0] == target || grid[bot][0] == target) { return true; } } }
return false; } };
|