计算几何-扫描线算法

news2025/3/14 20:46:20

1、定义 

计算几何中,扫描线算法(Sweep Line Algorithm)或平面扫描算法(Plane Sweep Algorithm)是一种算法模式,虚拟扫描线或扫描面来解决欧几里德空间中的各种问题,一般被用来解决图形面积,周长等问题,是计算几何中的关键技术之一。


这种算法背后的想法是想象一条线(通常是一条垂直线)在平面上扫过或移动,在某些点停止。几何操作仅限于几何对象,无论何时停止,它们都与扫描线相交或紧邻扫描线,并且一旦线穿过所有对象,就可以获得完整的解。

2、个人理解

其实说起来比较简单,就是用一条线(横着的或者竖着的)从上到下,或者从左到右,这么水平扫描过去,需要记录中间状态,扫描完就能够得到最终结果,扫描线可以实现降维操作,类似于三维变成二维。思想是这个思想。

解题套路:

  1. 数据排序
  2. 扫描排序后的数据,聚合有共性的数据
  3. 用一个新的数据结构存聚合后的结果

3、做几道题来沉淀下

1、天际线问题
/**
 * 天际线 @link https://leetcode.cn/problems/the-skyline-problem/
 */
public class TheSkylineProblem {

    public List<List<Integer>> getSkyline(int[][] buildings) {
        // 降维,
        List<int[]> buildingList = new ArrayList<>();
        for (int[] building : buildings) {
            int[] leftBuild = new int[2];
            leftBuild[0] = building[0];
            leftBuild[1] = -building[2];
            buildingList.add(leftBuild);
            int[] rightBuild = new int[2];
            rightBuild[0] = building[1];
            rightBuild[1] = building[2];
            buildingList.add(rightBuild);
        }
        // 排个序,按X从小到大排,如果X相同,则比较高度,也是从小到大
        buildingList.sort((o1, o2) -> {
            if (o1[0] - o2[0] == 0) {
                return o1[1] - o2[1];
            } else {
                return o1[0] - o2[0];
            }
        });

        List<List<Integer>> res = new ArrayList<>();
        // 最大堆,记录高度状态
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(Comparator.reverseOrder());
        int maxHeight = 0;
        // 结果必定是有个0值的
        priorityQueue.add(maxHeight);

        for (int[] build : buildingList) {
            // 左边界那么将这个高度入队,右边界删除即可
            if (build[1] < 0) {
                priorityQueue.add(-build[1]);
            } else {
                priorityQueue.remove(build[1]);
            }
            // 与当前最高度不同,则收集结果
            if (!priorityQueue.isEmpty() && maxHeight != priorityQueue.peek()) {
                maxHeight = priorityQueue.peek();
                List<Integer> tempList = new ArrayList<>();
                tempList.add(build[0]);
                tempList.add(maxHeight);
                res.add(tempList);
            }
        }
        return res;
    }
}

2、矩形面积 II

扫描线经典问题

package geometry.sweepline;

import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import java.util.*;

/**
 * 矩形面积2, https://leetcode.cn/problems/rectangle-area-ii/description/
 * 比较常见的利用扫描线来计算面积
 *
 * 竖着扫描,用区间Y的高度来作为扫描线,通过计算每个相邻的X差值*区间Y高度差,来收集面积结果
 * 中间状态就是:
 * 维护Y的区间高度,如果比上一个区间高就更新 Y的区间值
 * 同时也维护一个Y区间高度的差值
 * 
 * 需要注意精度值。。。 用 int 收集结果会超出
 */
public class RectangleAreaII {

    public int rectangleArea(int[][] rectangles) {
        // 降维,收集X坐标,并根据从小到大排序
        List<Integer> xList = new ArrayList<>();
        for (int[] rectangle : rectangles) {
            xList.add(rectangle[0]);
            xList.add(rectangle[2]);
        }

        Collections.sort(xList);
        int MOD = (int) (1.0E9 + 7);

        int res = 0;
        for (int i = 1; i < xList.size(); i++) {
            int xLeft = xList.get(i - 1);
            int xRight = xList.get(i);
            int interval = xRight - xLeft;
            if (interval == 0) {
                continue;
            }
            List<int[]> yList = new ArrayList<>();
            for (int[] rectangle : rectangles) {
                // 搞错了,这rectangle[2] 要大于 XRight 才记录,表示当前矩形区域覆盖 【xLeft,xRight】 这区域,最差也要是当前区域覆盖自己,所以有个=
                if (rectangle[0] <= xLeft && rectangle[2] >= xRight) {
                    yList.add(new int[]{rectangle[1], rectangle[3]});
                }
            }
            yList.sort((o1, o2) -> o1 != o2 ? o1[0] - o2[0] : o1[1] - o2[1]);
            long yTotal = 0;
            int lastDownY = -1;
            int lastUpY = -1;
            for (int[] ys : yList) {
                // 如果当前最低的高度都高于上次最高高度,那么更新全部信息
                if (ys[0] > lastUpY) {
                    // 先计算高度差值再赋值
                    yTotal += lastUpY - lastDownY;
                    lastDownY = ys[0];
                    lastUpY = ys[1];
                } else if (ys[1] > lastUpY){
                    // 只是当前最高高于上次最高
                    lastUpY = ys[1];
                }
            }
            yTotal += lastUpY - lastDownY;
            long value = yTotal * interval;
            res += value;
            res = res % MOD;
        }
        return res;
    }

    public static void main(String[] args) {
        List<int[]> rectangles = new ArrayList<>();
        rectangles.add(new int[]{0,0,2,2});
        rectangles.add(new int[]{1,0,2,3});
        rectangles.add(new int[]{1,0,3,1});
        RectangleAreaII rectangleAreaII = new RectangleAreaII();
        System.out.println("res:" + rectangleAreaII.rectangleArea(rectangles.toArray(new int[][]{})));
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试八股之Synchronized和ReentrantLock的区别

Synchronized和ReentrantLock的区别 实现级别&#xff1a; synchronized是Java的一个关键字&#xff0c;属于JVM层面的原生支持&#xff0c;它通过监视器锁&#xff08;Monitor&#xff09;来实现同步控制&#xff0c;无需手动获取和释放锁。 ReentrantLock是java.util.conc…

免费插件集-illustrator插件-Ai插件-文本对象和文本段落互转

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;进行文本对象和文本段落互转。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/878…

【408真题】2009-16

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…

计算机毕业设计Hadoop+Hive地震预测系统 地震数据分析可视化 地震爬虫 大数据毕业设计 Spark 机器学习 深度学习 Flink 大数据

2024 届本科毕业论文&#xff08;设计&#xff09; 基于Hadoop的地震预测的 分析与可视化研究 姓 名&#xff1a;____田伟情_________ 系 别&#xff1a;____信息技术学院___ 专 业&#xff1a;数据科学与大数据技术 学 号&#xff1a;__2011103094________ 指导…

Sam Altman微软Build 2024最新演讲:AI可能是下一个移动互联网

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

vue+echart :点击趋势图中的某一点或是柱状图,出现弹窗,并传输数据

样式 在趋势图中点击某一个柱状图&#xff0c;出现下面的弹窗 代码实现 主要是在趋势图页面代码中&#xff0c;在初始化趋势图的设置中&#xff0c;添加对趋势图监听的点击方法 drawChart() {const chartData this.chartData;let option {};if (!chartData.xData?.len…

【LVGL_Linux安装NXP的Gui-Guider】

GUI Guider是恩智浦为LVGL开发了一个上位机GUI设计工具&#xff0c;可以通过拖放控件的方式设计LVGL GUI页面&#xff0c;加速GUI的设计。 虽然他只支持自家芯片&#xff0c;但是应用层我们可以直接拿来用作其他MCU上。 GUI-Guider 下载 NXP官网下载&#xff1a;链接&#xff1…

SpringBoot 集成 ChatGPT(附实战源码)

建项目 项目结构 application.properties openai.chatgtp.modelgpt-3.5-turbo openai.chatgtp.api.keyREPLACE_WITH_YOUR_API_KEY openai.chatgtp.api.urlhttps://api.openai.com/v1/chat/completionsopenai.chatgtp.max-completions1 openai.chatgtp.temperature0 openai.cha…

超值分享50个DFM模型格式的素人直播资源,适用于DeepFaceLive的DFM合集

50直播模型&#xff1a;点击下载 作为直播达人&#xff0c;我在网上购买了大量直播用的模型资源&#xff0c;包含男模女模、明星脸、大众脸、网红脸及各种稀缺的路人素人模型。现在&#xff0c;我将这些宝贵的资源整理成合集分享给大家&#xff0c;需要的朋友们可以直接点击下…

前端中 dayjs 时间的插件使用(在vue 项目中)

Day.js中文网 这是dayjs的中文文档 里面包括了使用方法 下面我来详细介绍一下这个插件的使用 Day.js 可以运行在浏览器和 Node.js 中。 一般咱直接是 npm 安装 npm install dayjs 目前应该使用的是Es6 的语法 import dayjs from dayjs 当前时间 直接调用 dayjs() 将返回…

中小企业纵横数智之海,华为云“航母级”平台护航

自古以来&#xff0c;中国人对探索未知世界的想象&#xff0c;便是“纵横四海”。 《尚书》最早记载了中国人的海洋观念&#xff0c;所谓“文命&#xff0c;敷于四海”。屈原在《九歌 云中君》中感叹,“览冀州兮有余&#xff0c;横四海兮焉穷”&#xff0c;希望云神带着他找寻海…

SRE视角下的DevOps:构建稳定高效的软件交付流程

SRE 和 DevOps 有什么区别和联系&#xff1f;本文对此进行了解读&#xff0c;并着重从 SRE 实践出发阐述了 DevOps 的建设思路。 SRE 就是在用软件工程的思维和方法论完成以前由系统管理员团队手动完成的工作。SRE 的职责是运维一个服务&#xff0c;该服务由一些相关的系统组件…

【MyBatis】MyBatis解析全局配置文件源码详解

目录 一、前言 思维导图概括 二、配置文件解析过程分析 2.1 配置文件解析入口 2.2 初始化XMLConfigBuilder 2.3 XMLConfigBuilder#parse()方法&#xff1a;解析全局配置文件 2.3.1 解析properties配置 2.3.2 解析settings配置 2.3.2.1 元信息对象&#xff08;MetaClas…

Unity 自定义Web GL 发布模板

前言 使用讯飞语音识别时&#xff0c;发布Web GL 平台后需要在index.html 中添加相应的script 标签&#xff0c;但每次发布完添加比较麻烦&#xff0c;添加一个发布模板就可以不必每次发布完再手动添加修改。 实现 在Assets 文件夹下新建一个文件夹&#xff0c;重命名为WebG…

pygame raycasting纹理

插值原理 原理 color&#xff08;x&#xff09;(x-x1)/(x2-x1)(color2-color1)color1 x1<x<x2 假如说x伪3 那么color&#xff08;3-x1&#xff09;/(x2-x1)(color2-color1)color 可是图片纹理 这里不需要两种颜色&#xff0c;只需要获得碰撞点坐标后&#xff0c;如果…

腾讯面试:如何提升Kafka吞吐量?

面试题大全&#xff1a;www.javacn.site Kafka 是一个分布式流处理平台和消息系统&#xff0c;用于构建实时数据管道和流应用。它最初由 LinkedIn 开发&#xff0c;后来成为 Apache 软件基金会的顶级项目。 Kafka 特点是高吞吐量、分布式架构、支持持久化、集群水平扩展和消费组…

uniapp 对接 微信App/支付宝App 支付

相关文档&#xff1a;uni.requestPayment(OBJECT) | uni-app官网 示例代码&#xff1a; import qs from qsasync aliPay(){const { provider } await uni.getProvider({ service:payment })if(provider.includes(alipay)){uni.request({url:后端接口地址,data:{ //传参 },suc…

Linux服务升级:Twemproxy 升级 Redis代理

目录 一、实验 1.环境 2.多实例Redis部署 3.Twemproxy 升级Redis代理 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本软件IP备注CentOS7.9Twemproxy192.168.204.200 Redis代理 Redis127.0.0.1:6379第一个Redis实例 Redis127.0.0.1:6380第二个…

ssm141餐厅点菜管理系统+vue

餐厅点菜管理系统的设计与实现 摘 要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0c;所以对于信息的宣传和管…

2024年山东省安全员C证证考试题库及山东省安全员C证试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年山东省安全员C证证考试题库及山东省安全员C证试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大…