当前位置: 首页 > article >正文

力扣(leetcode)每日一题 699 掉落的方块 | 线段树|经典

699. 掉落的方块

题干

在二维平面上的 x 轴上,放置着一些方块。
给你一个二维整数数组 positions ,其中 positions[i] = [lefti, sideLengthi] 表示:第 i 个方块边长为 sideLengthi ,其左侧边与 x 轴上坐标点 lefti 对齐。
每个方块都从一个比目前所有的落地方块更高的高度掉落而下。方块沿 y 轴负方向下落,直到着陆到 另一个正方形的顶边 或者是 x 轴上 。一个方块仅仅是擦过另一个方块的左侧边或右侧边不算着陆。一旦着陆,它就会固定在原地,无法移动。
在每个方块掉落后,你必须记录目前所有已经落稳的 方块堆叠的最高高度 。
返回一个整数数组 ans ,其中 ans[i] 表示在第 i 块方块掉落后堆叠的最高高度。

题解

这个题目不仅需要用线段树,在进行线段树初始化的时候还有一个非常重要的技巧

class Solution {

    public static List<Integer> fallingSquares(int[][] positions) {
        TreeSet<Integer> treeSet = new TreeSet<>();
        for (int[] position : positions) {
            treeSet.add(position[0]);
            treeSet.add(position[0] + position[1] - 1);
        }
        HashMap<Integer, Integer> map = new HashMap<>();
        int count = 1;
        for (Integer i : treeSet) {
            map.put(i, count);
            count++;
        }
        SegmentTree segmentTree = new SegmentTree(map.size());
        segmentTree.build(positions, map);
        return segmentTree.getResult();

    }

    // 位置1 位置2   遍历位置  数量累加?

    public static class SegmentTree {
        int root = 1;
        int left = 1;
        int right;
        int[] maxArr;
        int[] updateArr; // 反正不会更新为0
        List<Integer> collect = new ArrayList<>();

        public SegmentTree(int n) {
            int length = n + 1;
            right = n;
            maxArr = new int[length * 4];
            updateArr = new int[length * 4];
        }

        public void update(int start, int end, int value) {
            update(start, end, value, left, right, root);
        }

        public void update(int start, int end, int value, int left, int right, int node) {
            if (start <= left && right <= end) {
                updateArr[node] = value;
                maxArr[node] = value;
                return;
            }
            int mid = (left + right) / 2;
            if (start <= mid) {
                update(start, end, value, left, mid, node * 2);
            }
            if (mid < end) {
                update(start, end, value, mid + 1, right, node * 2 + 1);
            }
            maxArr[node] = Math.max(maxArr[node * 2], maxArr[node * 2 + 1]);
        }

        public int getMax(int start, int end) {
            return getMax(start, end, left, right, root);
        }

        public int getMax(int start, int end, int left, int right, int node) {
            if (start <= left && right <= end) {
                return maxArr[node];
            }
            int mid = (left + right) / 2;
            int max = 0;
            int max2 = 0;
            // 刷新
            if (updateArr[node] != 0) {// 下发任务
                updateArr[node * 2] = updateArr[node];
                updateArr[node * 2 + 1] = updateArr[node];
                maxArr[node * 2] = updateArr[node];
                maxArr[node * 2 + 1] = updateArr[node];
                updateArr[node] = 0;
            }
            if (start <= mid) {
                max = getMax(start, end, left, mid, node * 2);
            }
            if (mid < end) {
                max2 = getMax(start, end, mid + 1, right, node * 2 + 1);
            }
            return Math.max(max, max2);
        }

        int curMax = 0;

        public void build(int[][] positions, HashMap<Integer, Integer> map) {
            for (int[] position : positions) {
                int i1 = position[0]; // 2,2      2,3 算头不算尾
                int i2 = position[1];
                Integer index1 = map.get(i1);
                Integer index2 = map.get(i1 + i2 - 1);
                // 获取范围上的最大值
                int max = getMax(index1, index2); // 范围 i1, i1 + i2
                update(index1, index2, max + i2);
                curMax = Math.max(curMax, max + i2);
                collect.add(curMax);
            }
        }

        public List<Integer> getResult() {
            return collect;
        }
    }

}
总结

还是去网上找视频看把,这个真不好解释

首先正放心 4,6 会落在4,6和10,6的位置,但是10,6的位置是没有支点的,也就是用不了的。因为这时候10位置来了方块,是无法累加上去的
然后这里不能记录4,6 5,6 6,6 7,6 8,6 9,6 这里需要对点进行map的压缩。
这样只要头尾的点就可以了。
也就是你会有很多点 数值很大 100,10000,555555,666666,666669
但是会通过hash映射到 1,2,3,4,5上。非常的紧凑


http://www.kler.cn/news/331689.html

相关文章:

  • MFC工控项目实例二十一型号选择界面删除参数按钮禁用切换
  • Python知识点:如何使用TensorFlow Lite与Python进行边缘AI计算
  • 【网络】网络安全概述
  • 探索未来:mosquitto-python,AI领域的新宠
  • ARM Process state -- SPSR
  • 滚雪球学MySQL[5.3讲]:数据库隔离级别与一致性详解:从幻读到MVCC
  • 数据结构(二叉树)
  • 基于SpringBoot+Vue的汽车保险理赔系统
  • WDG看门狗在stm32中的应用
  • 在 VSCode IDE 中,使用 ESP32-S3 的 USB 接口进行调试
  • ElasticSearch备考 -- 异步检索
  • Node.js env 环境变量多种配置方式
  • 软件测试学习笔记丨Pytest 学习指南
  • unity 默认渲染管线材质球的材质通道,材质球的材质通道
  • 学习docker第二弹------基本命令[帮助启动类命令、镜像命令、容器命令]
  • [深度学习][python]yolov11+deepsort+pyqt5实现目标追踪
  • 28 Vue3之搭建公司级项目规范
  • Nginx编译所需基本库pcre、zlib、openssl
  • [uni-app]小兔鲜-06地址+sku+购物车
  • Ruby 数组(Array)