【计数】1252. 奇数值单元格的数目

题目描述

(简单)给你一个 m x n 的矩阵,最开始的时候,每个单元格中的值都是 0

另有一个二维索引数组 indicesindices[i] = [ri, ci] 指向矩阵中的某个位置,其中 rici 分别表示指定的行和列(从 0 开始编号)。

indices[i] 所指向的每个位置,应同时执行下述增量操作:

  1. ri 行上的所有单元格,加 1
  2. ci 列上的所有单元格,加 1

给你 mnindices 。请你在执行完所有 indices 指定的增量操作后,返回矩阵中奇数值单元格的数目。

示例:
在这里插入图片描述

输入: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 个奇数。

解题思路

之所以是简单题,是因为暴力模拟不会超时。。。但模拟的时间、空间复杂度实在是太高了,故考虑其他算法优化一下。

本体有如下特点:

  • 每次修改是以行、列为单位;
  • 单考虑行,每次修改答案增加列数个;
  • 单考虑列,每次修改答案增加行数个;
  • 无论是整行、整列或者单个矩阵元素,偶数次修改等价于无改动;

因此,首先考虑的就是将耦合在 indices[] 的操作解耦。分别记录各行各列的修改次数,奇数次维护答案,偶数次跳过。

需要考虑的一点是,若先考虑行,当再考虑列时,列的修改是不再是单纯增加行数。将行、列解耦的好处是,行操作完后矩阵关于列是统一的。因此,后续进行列操作时,每列的改动值时固定的。

  1. 假设列操作前,每列奇数单元有 c 个;
  2. 考虑操作性质后,改动后的技术单元个数为 m - c;
  3. 因此,每次列操作后,奇数单元增量为 m - 2c;

代码实现

class Solution {
    
    
public:
    int oddCells(int m, int n, vector<vector<int>>& indices) {
    
    
        //维护各行访问次数
        vector<int> row(m);
        //维护各列访问次数
        vector<int> col(n);
        for(auto& vec : indices){
    
    
            row[vec[0]]++;
            col[vec[1]]++;
        }
        int res = 0;
        //奇数的行数
        int cnt = 0;
        //每一奇数行增加n个
        for(int& i :row){
    
    
            if(i & 1){
    
    
                cnt++;
                res += n;
            }
        }

        for(int& i :col){
    
    
            if(i & 1){
    
    
                //每访问一列增加量 m - 2 * cnt
                res += (m - 2 * cnt);
            }
        }

        return res;
    }
};

运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/LogosTR_/article/details/125756290