【LeetCode周赛】2022上半年题目精选集——二分

news2024/9/23 13:20:42

文章目录

  • 2141. 同时运行 N 台电脑的最长时间
    • 解法1——二分答案
      • 补充:求一个int数组的和,但数组和会超int
    • 解法2——贪心解法
  • 2251. 花期内花的数目
    • 解法1——二分答案
      • 代码1——朴素二分写法
      • 代码2——精简二分⭐
    • 解法2——差分⭐⭐⭐
  • 2258. 逃离火灾
    • 解法1——两次bfs
    • 解法2——二分 + BFS

2141. 同时运行 N 台电脑的最长时间

2141. 同时运行 N 台电脑的最长时间
在这里插入图片描述

提示:
1 <= n <= batteries.length <= 10^5
1 <= batteries[i] <= 10^9

解法1——二分答案

二分答案。

解释见:【LeetCode周赛】2022上半年题目精选集——贪心

class Solution {
    public long maxRunTime(int n, int[] batteries) {
        // long sum = Arrays.stream(batteries).asLongStream().sum();
        long sum = Arrays.stream(batteries).mapToLong(Long::valueOf).sum();
        long l = 0, r = sum / n;
        while (l < r) {
            long mid = l + r + 1 >> 1;
            if (check(n, batteries, mid)) l = mid;
            else r = mid - 1;
        }
        return l;
    }

    public boolean check(int n, int[] batteries, long k) {
        long sum = 0;
        for (int battery: batteries) sum += Math.min(k, battery);
        return n <= sum / k;
    }
}

补充:求一个int数组的和,但数组和会超int

解法——将 int 转成 long

写法1:

long sum = Arrays.stream(batteries).asLongStream().sum();

写法2:

long sum = Arrays.stream(batteries).mapToLong(Long::valueOf).sum();

解法2——贪心解法

见:【LeetCode周赛】2022上半年题目精选集——贪心

2251. 花期内花的数目

2251. 花期内花的数目

在这里插入图片描述

解法1——二分答案

枚举每个人。

每个人看到花的数量,通过二分法得出,等于 start <= time 且 end >= time 的花的数量,可以通过 start <= time 减去 end < time 的数量得到每个人的答案。
(即从一个合理的范围内减去不合理的那部分)。

代码1——朴素二分写法

(其实就是笔者自己写的代码)

class Solution {
    public int[] fullBloomFlowers(int[][] flowers, int[] people) {
        int m = flowers.length, n = people.length;
        int[] ans = new int[n];
        int[] start = new int[m], end = new int[m];
        for (int i = 0; i < m; ++i) {
            start[i] = flowers[i][0];
            end[i] = flowers[i][1];
        }
        Arrays.sort(start);
        Arrays.sort(end);
        for (int i = 0; i < n; ++i) {
            ans[i] = op(start, end, people[i]);
        }
        return ans;
    }

    public int op(int[] start, int[] end, int time) {
        int n = start.length;
        if (start[0] > time || end[n - 1] < time) return 0;
        // 找到最后一个开花时间<=time的花
        int l = 0, r = n - 1; 
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (start[mid] > time) r = mid - 1;
            else l = mid;
        }
        int x = l;
        // 找到第一个结束时间>=time的花
        l = 0;
        r = n - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (end[mid] < time) l = mid + 1;
            else r = mid;
        }
        // 在开花时间<=time的花中减去结束时间<time的花就是答案
        return x - l + 1;
    }
}

代码2——精简二分⭐

计算 x = start 中 >= p + 1 的下标, y = end 中 >= p 的下标。
结果为 x - y。

class Solution {
    public int[] fullBloomFlowers(int[][] flowers, int[] persons) {
        int[] starts = Arrays.stream(flowers).mapToInt(f -> f[0]).sorted().toArray();
        int[] ends = Arrays.stream(flowers).mapToInt(f -> f[1]).sorted().toArray();
        return Arrays.stream(persons).map(p -> lowerBound(starts, p + 1) - lowerBound(ends, p)).toArray();
    }

    // 找到第一个>=x的值,即x的下界
    int lowerBound(int[] arr, int x) {
        int left = 0, right = arr.length;   // 注意r的初始值是n而不是n-1
        while (left < right) {
            int mid = (left + right) >>> 1;
            if (arr[mid] >= x) right = mid;
            else left = mid + 1;
        }
        return left;
    }
}

这种方法通过 lowerBound() 方法避免了写两次二分。
在这里插入图片描述

解法2——差分⭐⭐⭐

在这里插入图片描述
由于数据范围的原因,我们需要使用 map 而不是数组来存储 差分结果。

关于差分可见:【算法基础】1.5 前缀和与差分

class Solution {
    public int[] fullBloomFlowers(int[][] flowers, int[] people) {
        Map<Integer, Integer> diff = new HashMap();
        for (int[] flower: flowers) {
            diff.merge(flower[0], 1, Integer::sum);
            diff.merge(flower[1] + 1, -1, Integer::sum);
        }
        // 去除差分哈希表中的所有时间点
        int[] times = diff.keySet().stream().mapToInt(Integer::intValue).sorted().toArray();

        int n = people.length;
        Integer[] ids = IntStream.range(0, n).boxed().toArray(Integer[]::new);
        Arrays.sort(ids, (i, j) -> people[i] - people[j]);  // 按时间升序取出people数组下标

        int[] ans = new int[n];
        int i = 0, sum = 0;
        for (int id: ids) {
            while (i < times.length && times[i] <= people[id]) {
                sum += diff.get(times[i++]);
            }
            ans[id] = sum;
        }
        return ans;
    }
}

在这里插入图片描述

2258. 逃离火灾

2258. 逃离火灾

难度:2347
在这里插入图片描述

解法1——两次bfs

先对火焰进行多源 bfs ,计算出火焰达到每个位置的时间。

然后对人进行 bfs,记录每条路径上最多能等待多少时间,每条路径达到终点时更新答案。

class Solution {
    public int maximumMinutes(int[][] grid) {
        int[] dx = {-1, 0, 1, 0}, dy = {0, -1, 0, 1};

        // 先处理出火达到每个地方的时间,如果达到不了,设置成最大值
        int m = grid.length, n = grid[0].length;
        int[][] times = new int[m][n];
        Queue<int[]> q = new LinkedList();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] != 1) {
                    times[i][j] = Integer.MAX_VALUE;    // 表示火还没有到
                } else {
                    q.offer(new int[]{i, j});           // 加入当前有火的队列    
                    times[i][j] = 1;
                }
            }
        }

        // 计算火焰达到每个位置的时间
        int t = 2;
        while (!q.isEmpty()) {
            int sz = q.size();
            for (int i = 0; i < sz; ++i) {
                int[] cur = q.poll();
                int x = cur[0], y = cur[1];
                for (int k = 0; k < 4; ++k) {
                    int nx = x + dx[k], ny = y + dy[k];
                    if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == 0) {
                        grid[nx][ny] = 1;
                        times[nx][ny] = t;
                        q.offer(new int[]{nx, ny});
                    }
                }
            }
            t++;
        }

        // bfs 人
        int ans = -1;
        t = 2;
        grid[0][0] = 2;
        q.offer(new int[]{0, 0, times[0][0] - 1});  // 最后一个元素记录当前时间的冗余
        while (!q.isEmpty()) {
            int sz = q.size();
            for (int i = 0; i < sz; ++i) {
                int[] cur = q.poll();
                int x = cur[0], y = cur[1], curLeftTime = cur[2];
                for (int k = 0; k < 4; ++k) {
                    int nx = x + dx[k], ny = y + dy[k];
                    if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] != 2) {
                        // 把走过的地方标记成墙壁,但是终点可以以不同方式到达多次
                        if (nx != m - 1 || ny != n - 1) grid[nx][ny] = 2;               
                        int leftTime;
                        // 如果到了终点就不用考虑当前时刻被火追上
                        if (nx == m - 1 && ny == n - 1) leftTime = Math.min(curLeftTime, times[nx][ny] - t);
                        else leftTime = Math.min(curLeftTime, times[nx][ny] - t - 1);

                        if (leftTime < 0) continue;     // 时间不够这条路走不通
                        if (nx == m - 1 && ny == n - 1) ans = Math.max(ans, leftTime);
                        q.offer(new int[]{nx, ny, leftTime});
                    }
                }
            }
            t++;
        }
        return ans > m * n? (int)1e9: ans;
    }
}

在这里插入图片描述

解法2——二分 + BFS

https://leetcode.cn/problems/escape-the-spreading-fire/solution/er-fen-bfspythonjavacgo-by-endlesscheng-ypp1/

注意!:实际上笔者认为这道题目是不需要二分的,使用二分反倒时间复杂度上去了。

在这里插入图片描述

class Solution {
    static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public int maximumMinutes(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int left = -1, right = m * n;
        while (left < right) {
            var mid = (left + right + 1) / 2;
            if (check(grid, mid)) left = mid;
            else right = mid - 1;
        }
        return left < m * n ? left : (int) 1e9;
    }

    boolean check(int[][] grid, int t) {
        int m = grid.length, n = grid[0].length;
        var fire = new boolean[m][n];
        var f = new ArrayList<int[]>();
        for (var i = 0; i < m; i++)
            for (var j = 0; j < n; j++)
                if (grid[i][j] == 1) {
                    fire[i][j] = true;
                    f.add(new int[]{i, j});
                }
        while (t-- > 0 && f.size() > 0)
            f = spreadFire(grid, fire, f); // 蔓延至多 t 分钟的火势
        if (fire[0][0]) return false; // 起点着火,寄

        var vis = new boolean[m][n];
        vis[0][0] = true;
        var q = new ArrayList<int[]>();
        q.add(new int[]{0, 0});
        while (q.size() > 0) {
            var tmp = q;
            q = new ArrayList<>();
            for (var p : tmp)
                if (!fire[p[0]][p[1]])
                    for (var d : dirs) {
                        int x = p[0] + d[0], y = p[1] + d[1];
                        if (0 <= x && x < m && 0 <= y && y < n && !fire[x][y] && !vis[x][y] && grid[x][y] == 0) {
                            if (x == m - 1 && y == n - 1) return true; // 我们安全了…暂时。
                            vis[x][y] = true;
                            q.add(new int[]{x, y});
                        }
                    }
            f = spreadFire(grid, fire, f); // 蔓延 1 分钟的火势
        }
        return false; // 寄
    }

    ArrayList<int[]> spreadFire(int[][] grid, boolean[][] fire, ArrayList<int[]> f) {
        int m = grid.length, n = grid[0].length;
        var tmp = f;
        f = new ArrayList<>();
        for (var p : tmp)
            for (var d : dirs) {
                int x = p[0] + d[0], y = p[1] + d[1];
                if (0 <= x && x < m && 0 <= y && y < n && !fire[x][y] && grid[x][y] == 0) {
                    fire[x][y] = true;
                    f.add(new int[]{x, y});
                }
            }
        return f;
    }
}    

在这里插入图片描述
仅作了解即可。

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

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

相关文章

在VSCode中导出安装的所有插件并在其他计算机进行导入

插件导出&#xff1a; 1、切换要导出的文件路径 cd D:\桌面文件\DownLoads2、导出到extensions文本 code --list-extensions > extensions.txt如图所示&#xff1a; 插件导入&#xff1a; 当您在另一台计算机上导出了 Visual Studio Code 编辑器已安装的扩展程序列表…

MySQL为什么选择B+树创建索引

不同方式查找数据 1. 全表遍历2. 哈希结构2.1 使用哈希结构创建索引的缺点2.2 哈希索引的适用性 3. 二叉搜索树4. AVL树5. B树6. B树6.1 B 树和 B 树的差异6.2 采用B树创建索引的优势6.3 一些需要注意的问题 1. 全表遍历 将磁盘中存储的所有数据记录依次加载&#xff0c;与给定…

linux下的mosquitto服务安装及使用(避坑指南)

Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单&#xff0c;可以方便的来进行一些测试。 mosquitto介绍 Mosquitto的特点&#xff1a; 1. 轻量级&#xff1a;Mosquitto是一个轻量级的MQTT代理…

Git学习(mac)

Git基础 1.安装与配置 下载与安装&#xff1a;git官网 使用入口&#xff1a; win&#xff1a;右键菜单 git bash Mac: 终端 查看git版本&#xff1a; git --version使用Git工作之前&#xff0c;我们需要做个一次性的配置。方便后续Git能跟踪到谁做了修改&#xff0c;我们需…

第四章——复合类型

数组 数组&#xff08;array&#xff09;是一种数据格式&#xff0c;能够存储多个同类型的值。例如30个int类型的值&#xff0c;12个float类型的值。每个值都存储在一个独立的数组元素中&#xff0c;计算机在内存中依次存储数组的各个元素。 创建数组时应指出以下三点&#x…

10.1UEC++/UObject

1. 1.new出的对象&#xff0c;不用自己管理内存释放&#xff1b; 2.比如两个类对象指针a,b同时指向一个苹果&#xff0c;若苹果消亡&#xff0c;会将a,b同时指向空。 3.保存时&#xff0c;将工程中的actor&#xff0c;属性等能够保存在本地就是uob在发挥作用。 4.不管在ue&…

自然语言处理实战项目12-基于注意力机制的CNN-BiGRU模型的情感分析任务的实践

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理实战项目12-基于注意力机制的CNN-BiGRU模型的情感分析任务的实践&#xff0c;本文将介绍一种基于注意力机制的CNN-BiGRU模型&#xff0c;并将其应用于实际项目中。我们将使用多条CSV数据样例&#xff0…

虚拟机ubuntu系统IP地址变成127.0.0.1了

使用sudo dhclient -v指令动态获取IP地址 注意要把电脑网线拔掉&#xff0c;如果WIFI和有线同时连着设备就会出现如下情况 拔掉网线后正常

网络应用基础交换机(NETBASE第五课)

网络应用基础交换机&#xff08;NETBASE第五课&#xff09; 交换机的定义 交换是按照通信两端传输信息的需要&#xff0c;用人工或设备自动完成的方法&#xff0c;把要传输的信息送到符合要求的相应路由上的技术的统称。交换机根据工作位置的不同&#xff0c;可以分为广域网交…

Tubi 时间序列 KPI 的异常值检测

欢迎来到 Tubi—— 在这里&#xff0c;广告型视频点播永不停歇&#xff01; 作为全球最大的流媒体服务之一&#xff0c;Tubi 保持稳定增长&#xff0c;并始终关注对业务发展至关重要的前沿趋势。基于此&#xff0c;Tubi 数据科学团队创建了一套全新警报系统&#xff0c;对 Key…

【Kubernetes运维篇】RBAC认证授权详解(一)

文章目录 一、RBAC授权认证理论知识1、什么是RBAC授权&#xff1f;2、认证基本流程3、K8S客户端访问apiserver的认证几方式1、第一种&#xff1a;客户端认证2、第二种&#xff1a;Bearertoken方式3、第三种&#xff1a;Serviceaccount方式 4、RBAC授权常见角色绑定方式1、第一种…

安装OSAR_Co_X

在找开源的QSAR平台 在WOS里用“open source”、“QSAR”、“platform”为关键字找到一个描述QSAR-Co-X的文献&#xff0c;这是一个基于python开发的QSAR平台&#xff08;额&#xff0c;&#xff0c;&#xff0c;目前还不是很清楚&#xff09;。 根据链接找到Github里代码的所…

讲故事vs讲知识,区别太大

讲故事vs讲知识&#xff0c;区别很大 以故事化的方式讲知识&#xff0c;一般受众爱听 讲故事&#xff0c;通常受众爱听 趣讲大白话&#xff1a;但不是所有的故事都爱听 【趣讲信息科技219期】 #非著名IT人安志强的趣味笔记# **************************** 有一小部分故事&#…

CTFshow-pwn入门-栈溢出pwn49(静态链接pwn-mprotect函数的应用)

pwn49 首先我们先将pwn文件下载下来&#xff0c;然后赋上可执行权限&#xff0c;再来查看pwn文件的保护信息。 chomd x pwn checksec pwn file pwn我们可以看到这是一个32位的pwn文件&#xff0c;并且保护信息开启了NX和canary&#xff0c;也就是堆栈不可执行且有canary。最最…

算数运算符

运算符介绍&#xff1a;运算符是一种特殊的符号&#xff0c;用以表示数据的运算、赋值和比较等。 算术运算符赋值运算符关系运算符逻辑运算符位运算符三元运算符 算术运算符 算术运算符是对数值类型的变量进行运算的。 % 取模&#xff0c;取余 在 % 的本质&#xff0c;a % b…

UE5.1.1 C++从0开始(17.GAS游戏能力系统)

教程的链接&#xff1a;https://www.bilibili.com/video/BV1nU4y1X7iQ 教程内的老师没用GAS的插件&#xff0c;而是自己写了一个。这一篇文章只是开头&#xff0c;还有很多的内容没有往里面写。 新增了一个object类&#xff0c;新增了一个使用这个类的组件。然后把这个组件用…

text-to-3d方面的论文列表分享

以下给出几篇我个人觉得比较有价值的text-to-3d的论文列表&#xff0c;论文的超链接会连接到arxiv上。 DreamfusionFantasia3DTangoLatent-NeRFMagic-3dClip-ForgeClip-MeshDreamfieldAvatarCLIPPoint-EShape-EText2Mesh

P3804 【模板】后缀自动机(SAM)

题目描述 给定一个只包含小写字母的字符串 S。 请你求出 S 的所有出现次数不为 11 的子串的出现次数乘上该子串长度的最大值。 输入格式 一行一个仅包含小写字母的字符串 S。 输出格式 一个整数&#xff0c;为所求答案。 题解&#xff1a;这里就不讲后缀自动机的模板相关…

zigbee学习之DHT11温湿度传感器+zigbee无线通信

开发环境&#xff1a;IAR烧录器串口调试助手CC2530DHT11 两个模块&#xff1a;一个作为协调器&#xff0c;负责接收数据&#xff0c;一个作为终端&#xff0c;负责发送数据 步骤&#xff1a; 1、SampleApp.c里配引脚P0_6(查看硬件上的标识) 2、DTH11.c里配引脚 3、修改PANID和信…

超纯水抛光混床树脂的选择及工艺流程

一、什么是超纯水&#xff1f; 既将水中的导电介质几乎完全去除&#xff0c;又将水中不离解的胶体物质、气体及有机物均去除至很低程度的水。电阻率大于18MΩ*cm&#xff0c;或接近18.3MΩ*cm极限值。 超纯水是科技界为了研制超纯材料&#xff08;半导体原件材料、纳米精细陶…