路灯照明问题(java)

路灯照明问题

难度:★★

区间合并,排序和扫描。

路灯照明问题

时间限制:1秒 | 内存限制:262144K | 语言限制:不限

题目描述:

在一条笔直的公路上安装了N个路灯,从位置0开始安装,路灯之间间距固定为100米。 每个路灯都有自己的照明半径,请计算第一个路灯和最后一个路灯之间,无法照明的区间的长度和。

输入描述:

第一行为一个数N,表示路灯个数,1<=N<=100000
第二行为N个空格分隔的数,表示路径的照明半径,1<=照明半径<=100000*100

输出描述:

第一个路灯和最后一个路灯之间,无法照明的区间的长度和

示例1

输入

2

50 50

输出

0

说明

路灯1覆盖0-50,路灯2覆盖50-100,路灯1和路灯2之间(0米-100米)无未覆盖的区间

示例2

输入

4

50 70 20 70

输出

20

说明

[170,180],[220,230],两个未覆盖的区间,总里程为20

解题思路:

  1. 首先,我们需要接收输入,根据输入创建一个列表,每个元素是一个包含左边界和右边界的数组,代表每个路灯的照射范围。
  2. 其次,我们对列表进行排序,根据每个数组的左边界值进行排序。
  3. 在排序后,我们需要判断是否存在一盏路灯的照射范围覆盖了全部区域。如果存在,那么未覆盖区域就为0,直接输出结果。
  4. 如果不存在这样的路灯,我们就开始遍历这个排序后的列表。在遍历过程中,我们比较当前路灯的左边界和前一个路灯的右边界,如果当前路灯的左边界大于前一个路灯的右边界,就说明存在未被覆盖的区间,把这个区间的长度加入到总的未覆盖长度中。
  5. 最后,我们还需要检查最后一个路灯的右边界是否小于整个区域的右边界,如果小于,就把这个未被覆盖的区间长度也加入到总的未覆盖长度中。

JAVA代码:

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt(); // 读取路灯的数量
        List<int[]> list = new ArrayList<>(); // 创建列表来保存每个路灯的照射范围
        for (int i = 0; i < n; i++) { // 对每个路灯进行处理
            int temp = scan.nextInt(); // 读取路灯的照射半径
            int k = i * 100; // 计算路灯的位置
            int left = k - temp; // 计算照射范围的左边界
            int right = k + temp; // 计算照射范围的右边界
            if (left < 0) {
                left = 0; // 确保左边界不小于0
            }
            if (right > 100 * (n - 1)) {
                right = 100 * (n - 1); // 确保右边界不大于整个区域的右边界
            }
            list.add(new int[]{left, right}); // 把这个照射范围添加到列表中
        }
        // 根据左边界对列表进行排序
        list.sort(Comparator.comparingInt(a -> a[0]));

        // 检查是否存在一盏路灯的照射范围覆盖了全部区域
        for (int[] interval : list) {
            if (interval[0] <= 0 && interval[1] >= 100 * (n - 1)) {
                System.out.println(0); // 如果存在这样的路灯,就输出0,并结束程序
                return;
            }
        }

        int total = 0; // 用来保存总的未覆盖长度
        int end = 0; // 保存当前的照射范围右边界

        // 遍历排序后的列表,寻找未覆盖的区间
        for (int[] interval : list) {
            if (interval[0] > end) { // 如果当前路灯的左边界大于前一个路灯的右边界,就找到了一个未覆盖的区间
                total += interval[0] - end; // 把这个区间的长度加入到总的未覆盖长度中
            }
            end = Math.max(end, interval[1]); // 更新当前的照射范围右边界
        }
        // 检查最后一个路灯的右边界是否小于整个区域的右边界
        if (end < 100 * (n - 1)) {
            total += 100 * (n - 1) - end; // 如果小于,就把这个未被覆盖的区间长度加入到总的未覆盖长度中
        }
        System.out.println(total); // 输出总的未覆盖长度
    }
}

代码说明:

  1. 首先,我们使用Scanner从输入中读取路灯的数量,然后创建一个数组来存储每个路灯的照射半径。
  2. 之后,我们对这个数组进行排序,以便于我们后续的操作。
  3. 创建一个变量end来保存当前的照射范围右边界,初始值为0。同时,创建一个变量total来保存总的未覆盖长度,初始值也为0。
  4. 开始遍历每个路灯,对于每个路灯,我们计算它的左边界(即i * 100 - lights[i]),然后与end比较。
    • 如果当前路灯的左边界大于end,那么在end和当前路灯的左边界之间就存在一个未被覆盖的区间,我们把这个区间的长度加到total上。
    • 如果当前路灯的左边界小于等于end,那么这个路灯的照射范围是被覆盖的,我们不需要对total进行操作。
  5. 在处理完当前路灯的左边界之后,我们需要更新endend应该是当前路灯的右边界(即i * 100 + lights[i])和当前end中的较大值。这样可以确保end总是最大的右边界,避免重复计算。
  6. 在处理完所有的路灯之后,我们还需要检查一下最后一个路灯的右边界是否小于整个区域的右边界(即100 * (n - 1))。如果小于,那么在这两个边界之间就存在一个未被覆盖的区间,我们把这个区间的长度加到total上。
  7. 最后,我们输出total,即总的未覆盖长度。

这个解决方案利用了排序和扫描的方法,将复杂度控制在了O(n log n),其中n是路灯的数量。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杜柠函

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值