Leetcode 2132. 用邮票贴满网格图(Java + 两次一维前缀和 + 二维差分)

Leetcode 2132. 用邮票贴满网格图(Java + 两次一维前缀和 + 二维差分)

题目

  • 给你一个 m x n 的二进制矩阵 grid ,每个格子要么为 0 (空)要么为 1 (被占据)。
  • 给你邮票的尺寸为 stampHeight x stampWidth 。我们想将邮票贴进二进制矩阵中,且满足以下 限制 和 要求 :
    1. 覆盖所有 空 格子。
    2. 不覆盖任何 被占据 的格子。
    3. 我们可以放入任意数目的邮票。
    4. 邮票可以相互有 重叠 部分。
    5. 邮票不允许 旋转 。
    6. 邮票必须完全在矩阵 内 。
  • 如果在满足上述要求的前提下,可以放入邮票,请返回 true ,否则返回 false 。
  • m == grid.length
  • n == grid[r].length
  • 1 <= m, n <= 10 ^ 5
  • 1 <= m * n <= 2 * 10 ^ 5
  • grid[r][c] 要么是 0 ,要么是 1 。
  • 1 <= stampHeight, stampWidth <= 10 ^ 5

解法

  • 两次一维前缀和 + 二维差分:

第 1 步:

  • 先求出以每个点为左上角,是否可以贴邮票,
  • 接着使用二维差分,将每个可以贴邮票的点 +1,
  • 最后统一更新一遍,查询 贴邮票的点数 + 被占据的点数 是否等于总格子数

第 2 步:

  • 求出以每个点为左上角,是否可以贴邮票:
    • 先每行倒序、求出每个点往右最多多少空位 rowCount:空位 rowCount[i][j]=rowCount[i][j+1]+1,否则 rowCount[i][j]=0
    • 再每列倒序、求出每个点往下最多有多少个 rowCount >= stampWidth,设置为 rowColCount:大于等于 rowColCount[i][j]=rowColCount[i+1][j]+1,否则 rowColCount[i][j]=0
    • 最后求每个点的 rowColCount >= stampHeight,代表可以贴邮票 isStamp[i][j]=true

第 3 步:

  • 顺序遍历 isStamp,如果 true 则将当前点 stampCount[i][j]++、代表右下角均可以贴邮票,
  • 右边 stampCount[i][j+stampWidth]–、下边 stampCount[i+stampHeight][j]–、右下角 stampCount[i+stampHeight][j+stampWidth]++,
  • 以差分的形式处理结果,
    在这里插入图片描述

第 4 步:

  • 顺序遍历 stampCount,使用差分 DP 的思想,更新 stampCount:
  • stampCount[i][j] += stampCount[i-1][j]+stampCount[i][j-1]-stampCount[i-1][j-1]:代表上边区间 加 左边区间 减 重叠区间,
  • 如果 stampCount[i][j] > 0 代表此点被贴邮票
  • 时间复杂度:O(mn),空间复杂度:O(mn)

代码

/**
     * 两次一维前缀和 + 二维差分:
     *
     * 第 1 步:
     * 先求出以每个点为左上角,是否可以贴邮票,
     * 接着使用二维差分,将每个可以贴邮票的点 +1,
     * 最后统一更新一遍,查询 贴邮票的点数 + 被占据的点数 是否等于总格子数
     *
     * 第 2 步:
     * 求出以每个点为左上角,是否可以贴邮票:
     *     * 先每行倒序、求出每个点往右最多多少空位 rowCount:空位 rowCount[i][j]=rowCount[i][j+1]+1,否则 rowCount[i][j]=0
     *     * 再每列倒序、求出每个点往下最多有多少个 rowCount >= stampWidth,设置为 rowColCount:大于等于 rowColCount[i][j]=rowColCount[i+1][j]+1,否则 rowColCount[i][j]=0
     *     * 最后求每个点的 rowColCount >= stampHeight,代表可以贴邮票 isStamp[i][j]=true
     *
     * 第 3 步:
     * 顺序遍历 isStamp,如果 true 则将当前点 stampCount[i][j]++、代表右下角均可以贴邮票,
     * 右边 stampCount[i][j+stampWidth]--、下边 stampCount[i+stampHeight][j]--、右下角 stampCount[i+stampHeight][j+stampWidth]++,
     * 以差分的形式处理结果,
     *
     * 第 4 步:
     * 顺序遍历 stampCount,使用差分 DP 的思想,更新 stampCount:
     * stampCount[i][j] += stampCount[i-1][j]+stampCount[i][j-1]-stampCount[i-1][j-1]:代表上边区间 加 左边区间 减 重叠区间,
     * 如果 stampCount[i][j] > 0 代表此点被贴邮票
     * 时间复杂度:O(m*n),空间复杂度:O(m*n)
     */
    public boolean possibleToStamp(int[][] grid, int stampHeight, int stampWidth) {
        int m = grid.length;
        int n = grid[0].length;

        // 列 +1 方便处理最右边的点
        int[][] rowCount = new int[m][n + 1];

        // 被占领的数量
        int fillCount = 0;

        // 先每行倒序、求出每个点往右最多多少空位 rowCount:空位 rowCount[i][j]=rowCount[i][j+1]+1,否则 rowCount[i][j]=0
        for (int i = 0; i < m; i++) {
            for (int j = n - 1; j >= 0; j--) {
                if (grid[i][j] == 0) {
                    rowCount[i][j] = rowCount[i][j + 1] + 1;


                } else {
                    rowCount[i][j] = 0;
                    fillCount++;
                }
            }
        }

        // 行 +1 方便处理最下边的点
        int[][] rowColCount = new int[m + 1][n];

        // 最后求每个点的 rowColCount >= stampHeight,代表可以贴邮票 isStamp[i][j]=true
        boolean[][] isStamp = new boolean[m][n];

        // 再每列倒序、求出每个点往下最多有多少个 rowCount >= stampWidth,设置为 rowColCount:大于等于 rowColCount[i][j]=rowColCount[i+1][j]+1,否则 rowColCount[i][j]=0
        for (int j = 0; j < n; j++) {
            for (int i = m - 1; i >= 0; i--) {
                if (rowCount[i][j] >= stampWidth) {
                    rowColCount[i][j] = rowColCount[i + 1][j] + 1;

                    if (rowColCount[i][j] >= stampHeight) {
                        isStamp[i][j] = true;
                    }

                } else {
                    rowColCount[i][j] = 0;
                }
            }
        }

        // 行列向右下移动一位,方便处理
        int[][] stampCount = new int[m + 1][n + 1];
        // 顺序遍历 isStamp,如果 true 则以二维差分方式处理
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (isStamp[i][j]) {
                    stampCount[i + 1][j + 1]++;

                    if (i + 1 + stampHeight <= m) {
                        stampCount[i + 1 + stampHeight][j + 1]--;
                    }

                    if (j + 1 + stampWidth <= n) {
                        stampCount[i + 1][j + 1 + stampWidth]--;
                    }

                    if (i + 1 + stampHeight <= m && j + 1 + stampWidth <= n) {
                        stampCount[i + 1 + stampHeight][j + 1 + stampWidth]++;
                    }
                }
            }
        }

        int stampCountRes = 0;
        // 顺序遍历 stampCount,使用差分 DP 的思想,更新 stampCount
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                stampCount[i][j] += stampCount[i][j - 1] + stampCount[i - 1][j] - stampCount[i - 1][j - 1];
                if (stampCount[i][j] > 0) {
                    stampCountRes++;
                }
            }
        }

        return fillCount + stampCountRes == m * n;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/254951.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于PaddleOCR搭建身份证识别web api接口

前言 通过 这篇文章【基于PaddleOCR的DBNet神经网络实现全网最快最准的身份证识别模型】开发的身份证识别模型&#xff0c;还无法进行部署应用&#xff0c;这篇文章就已经开发好的代码如何部署&#xff0c;并如何通过api的接口进行访问进行讲解。 项目部署 以windows系统为例…

想做新程序员?马上用 GPT-4 编程,一切我们都替你搞好了!

// 打不过就加入。与其担心被 GPT-4 取代&#xff0c;不如现在就学习驾驭它。 &#xff08;GPT-3.5 和其他模型都不用怕&#xff0c;它们都不行&#xff0c;谁用谁知道……除了 Claude 我们还在测试中&#xff09; 文末有一键加入方法&#xff0c;国内用户也能无障碍使用—…

提升 API 可靠性的五种方法

API 在我们的数字世界中发挥着关键的作用&#xff0c;使各种不同的应用能够相互通信。然而&#xff0c;这些 API 的可靠性是保证依赖它们的应用程序功能正常、性能稳定的关键因素。本文&#xff0c;我们将探讨提高 API 可靠性的五种主要策略。 1.全面测试 要确保 API 的可靠性…

自动化测试 (四) 读写64位操作系统的注册表

自动化测试经常需要修改注册表 很多系统的设置&#xff08;比如&#xff1a;IE的设置&#xff09;都是存在注册表中。 桌面应用程序的设置也是存在注册表中。 所以做自动化测试的时候&#xff0c;经常需要去修改注册表 Windows注册表简介 注册表编辑器在 C:\Windows\regedit…

hypervisor display显卡节点card0生成过程

ditsi 配置 lagvm/LINUX/android/vendor/qcom/proprietary/devicetree/qcom direwolf-g9ph.dts #include "direwolf-vm-la.dtsi" direwolf-vm-la.dtsi #include "display/quin-vm-display-la.dtsi" quin-vm-display-la.dtsi //对应/sys/class/drm/card…

微信小程序背景图片设置

问题 :微信小程序通过css:background-image引入背景图片失败 [渲染层网络层错误] pages/wode/wode.wxss 中的本地资源图片无法通过 WXSS 获取&#xff0c;可以使用网络图片&#xff0c;或者 base64&#xff0c;或者使用<image/>标签 解决方法微信小程序在使用backgroun…

C++指针

本文章对C指针的使用做一个全面的阐述与解释 1.1指针的定义使用 指针&#xff1a; 通过指针间接访问内存 指针就是地址 看下面代码&#xff1a; #include<iostream> using namespace std; int main(){//1、定义指针int * p;int a 10;//2、使用指针p &a;cout<…

C语言—每日选择题—Day53

指针相关博客 打响指针的第一枪&#xff1a;指针家族-CSDN博客 深入理解&#xff1a;指针变量的解引用 与 加法运算-CSDN博客 第一题 1. 有以下程序&#xff0c;输出的结果为&#xff08;&#xff09; #include <stdio.h> int main() {char a H;a (a > A &&…

PyTorch机器学习与深度学习

近年来&#xff0c;随着AlphaGo、无人驾驶汽车、医学影像智慧辅助诊疗、ImageNet竞赛等热点事件的发生&#xff0c;人工智能迎来了新一轮的发展浪潮。尤其是深度学习技术&#xff0c;在许多行业都取得了颠覆性的成果。另外&#xff0c;近年来&#xff0c;Pytorch深度学习框架受…

电机(按工作电源分类)介绍

文章目录 一、什么是电机&#xff1f;二、按工作电源分类直流电机1.直流有刷电机结构工作原理&#xff1a;直流减速电机 2.直流无刷电机结构工作原理&#xff1a; 3.总结结构和工作原理&#xff1a;效率和功率损耗&#xff1a;调速性能&#xff1a;寿命和可靠性&#xff1a;应用…

梯形加减速点动功能块(SMART PLC梯形图)

博途PLC的梯形加减速点动功能块算法和源代码介绍请查看下面文章链接: https://rxxw-control.blog.csdn.net/article/details/133185836https://rxxw-control.blog.csdn.net/article/details/133185836 1、梯形加减速速度曲线 2、梯形加减速点动功能块 3、接口定义

mmpose 使用笔记

目录 自己整理的可以跑通的代码&#xff1a; 图片demo&#xff1a; 检测加关键点 自己整理的可以跑通的代码&#xff1a; 最强姿态模型 mmpose 使用实例-CSDN博客 图片demo&#xff1a; python demo/image_demo.py \tests/data/coco/000000000785.jpg \configs/body_2d_k…

在 linux上运行 Scratch,找到了更github 的项目地址,而且找到了scratch的官方项目。

1&#xff0c;关于Scratch Scratch 是麻省理工学院的“终身幼儿园团队”发布的一种图形化编程工具&#xff0c; 主要面对全球青少年开放&#xff0c;所有人都可以在软件中创作自己的程序。 2&#xff0c;在linux 上面还真有个默认的 scratch 版本 但是太老旧了。 于是找了下…

孩子还是有一颗网安梦——Bandit通关教程:Level 15 → Level 16

&#x1f575;️‍♂️ 专栏《解密游戏-Bandit》 &#x1f310; 游戏官网&#xff1a; Bandit游戏 &#x1f3ae; 游戏简介&#xff1a; Bandit游戏专为网络安全初学者设计&#xff0c;通过一系列级别挑战玩家&#xff0c;从Level0开始&#xff0c;逐步学习基础命令行和安全概念…

Linux IO调度器介绍

Linux系统提供了多种IO调度器&#xff08;I/O Scheduler&#xff09;&#xff0c;每种调度器都有其独特的设计原理和优化目标。以下是一些常见的Linux IO调度器&#xff1a; Noop调度器&#xff1a;Noop&#xff08;No Operation&#xff09;调度器是最简单的IO调度器&#xff…

TaxtArea中内嵌一张放松图片,该图片实现属性悬浮放大功能

TaxtArea中内嵌一张发送图片&#xff0c;该图片实现属性悬浮放大功能&#xff0c;离开还原效果&#xff0c;点击发送按钮后&#xff0c;发送图片变为loading&#xff0c; <div class"textarea-wrapper" ><a-textarearef"textArea"v-model.trim&q…

每天五分钟计算机视觉:谷歌的Inception模块的计算成本的问题

计算成本 Inception 层还有一个问题,就是计算成本的问题,我们来看一下55 过滤器在该模块中的计算成本。 原始图片为28*28*192经过32个5*5的过滤操作,它的计算成本为: 我们输出28*28*32个数字,对于输出的每个数字来说,你都需要执行 55192 (5*5为卷积核的大小,192为通道…

【Java 并发】三大特性

在 Java 的高并发中&#xff0c;对于线程并发问题的分析通常可以通过 2 个主核心进行分析 JMM 抽象内存模型和 Happens-Before 规则三大特性: 原子性, 有序性和可见性 JMM 抽象内存模型和 Happens-Before 规则, 前面我们讨论过了。这里讨论一下三大特性。 1 原子性 定义: 一个…

Docker部署MinIO对象存储服务器结合内网穿透实现远程访问

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…

飞天使-jumpserver-docker跳板机安装

文章目录 jumpserverdocker 更新到最新下载安装包mysql启动mysql 命令 验证字符集,创建数据库使用jumpserver 进行连接测试 redis部署jumpserver 写入变量建jumpserver 容器正确输出登录验证 jumpserver 基础要求 硬件配置: 2 个 CPU 核心, 4G 内存, 50G 硬盘&#xff08;最低…