LeetCode 3070.元素和小于等于 k 的子矩阵的数目:原地修改(前缀和思想)

【LetMeFly】3070.元素和小于等于 k 的子矩阵的数目:原地修改(前缀和思想)

力扣题目链接:https://leetcode.cn/problems/count-submatrices-with-top-left-element-and-sum-less-than-k/

给你一个下标从 0 开始的整数矩阵 grid 和一个整数 k

返回包含 grid 左上角元素、元素和小于或等于 k子矩阵的数目。

示例 1:

复制代码
输入:grid = [[7,6,3],[6,6,1]], k = 18
输出:4
解释:如上图所示,只有 4 个子矩阵满足:包含 grid 的左上角元素,并且元素和小于或等于 18 。

示例 2:

复制代码
输入:grid = [[7,2,9],[1,5,0],[2,6,6]], k = 20
输出:6
解释:如上图所示,只有 6 个子矩阵满足:包含 grid 的左上角元素,并且元素和小于或等于 20 。

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= n, m <= 1000
  • 0 <= grid[i][j] <= 1000
  • 1 <= k <= 109

解题方法:前缀和原地修改

第一层循环从上到下第二层循环从左到右遍历一遍 g r i d grid grid数组,在遍历过程中把 g r i d [ i ] [ j ] grid[i][j] grid[i][j]的值修改为从左上角到这个元素的子矩阵元素之和。

怎么 O ( 1 ) O(1) O(1)时间得到右下角为 ( i , j ) (i,j) (i,j)的子矩阵之和?借助前面的遍历结果即可:

  • 如果 i i i和 j j j都大于 0 0 0,则 g r i d [ i ] [ j ] + = g r i d [ i − 1 ] [ j ] + g r i d [ i ] [ j − 1 ] − g r i d [ i − 1 ] [ j − 1 ] grid[i][j] += grid[i - 1][j] + grid[i][j - 1] - grid[i - 1][j - 1] grid[i][j]+=grid[i−1][j]+grid[i][j−1]−grid[i−1][j−1]:

    复制代码
    1 2
    3 4

    如图矩阵在计算左上角到右下角的 4 4 4的时候,可以借助左上角到 4 4 4上面 2 2 2的元素和 + 左上角到 4 4 4左边 3 3 3的元素和 - 计算重复的左上角到 4 4 4左上角 1 1 1的元素和。

  • 如果 i i i大于 0 0 0而 j j j等于 0 0 0,则直接加上这个元素上一行的结果即可;

  • 如果 j j j大于 0 0 0而 i i i等于 0 0 0同理。

优化:如果到 g r i d [ i ] [ j ] grid[i][j] grid[i][j]的子矩阵元素和已经大于 k k k,那么再往右和往下的更大子矩阵的和一定更大,可跳过。

  • 时间复杂度 O ( m n ) O(mn) O(mn)
  • 空间复杂度 O ( 1 ) O(1) O(1)

AC代码

C++
cpp 复制代码
/*
 * @LastEditTime: 2026-03-18 22:19:52
 */
class Solution {
public:
    int countSubmatrices(vector<vector<int>>& grid, int k) {
        int ans = 0;
        int n = grid.size(), m = grid[0].size();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (i && j) {
                    grid[i][j] += grid[i - 1][j] + grid[i][j - 1] - grid[i - 1][j - 1];
                } else if (i) {
                    grid[i][j] += grid[i - 1][j];
                } else if (j) {
                    grid[i][j] += grid[i][j - 1];
                }
                ans += grid[i][j] <= k;
            }
        }
        return ans;
    }
};

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
玛卡巴卡ldf12 小时前
【LeetCode 手撕算法】(多维动态规划)不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离
java·数据结构·算法·leetcode·动态规划·力扣
被AI抢饭碗的人12 小时前
算法:数据结构
数据结构·算法
运筹vivo@12 小时前
leetcode每日一题: 跳跃游戏 IV
leetcode·游戏·宽度优先
_深海凉_12 小时前
LeetCode热题100-验证二叉搜索树
算法·leetcode·职场和发展
shehuiyuelaiyuehao12 小时前
算法27,二维前缀和
开发语言·python·算法
蒟蒻的贤12 小时前
编译原理里的冲突到底是什么?
考研·算法
_深海凉_13 小时前
LeetCode热题100-二叉树的右视图
算法·leetcode·职场和发展
圣保罗的大教堂13 小时前
leetcode 1391. 检查网格中是否存在有效路径 中等
leetcode
计算机安禾13 小时前
【c++面向对象编程】第29篇:定位new(placement new):在指定内存上构造对象
开发语言·c++·算法
淞綰13 小时前
c语言的练习-字符串的练习-寻找最长连续字符以及出现次数
c语言·数据结构·学习·算法·c语言的练习