唐门绝技——暴雨梨花针思路及题解

254 阅读3分钟

原题地址:[唐门绝技:暴雨梨花针最少发射次数](唐门绝技:暴雨梨花针最少发射次数 - MarsCode)

问题描述

在唐门,外门弟子唐三发现了一种强大的暗器技巧,名为暴雨梨花针,它能在一条直线上摧毁所有目标。唐三在一本古籍中学习到了这门技巧,为了练习,他设置了若干个靶子在二维平面上。每个靶子是一条垂直于X轴的线段,由三个参数 x_{left}x_{right}y 描述,其中 y 是固定的高度,x_{left} 和 x_{right} 表示线段在X轴上的起止位置。

唐三的目标是使用尽可能少的暴雨梨花针来击中所有靶子。由于暴雨梨花针的珍贵,每次射击必须经济有效。每次射击暴雨梨花针都将从某个 x 值发射,能垂直上升到 y = 100

  • 请你帮助唐三计算最少需要多少次射击,才能保证击中所有靶子。结果需对给定的 P 取余。

思路解析

拿到这道题,我一开始的思路是找到能穿透木板最多的x轴坐标,然后再统计其他不能覆盖该坐标的木板的数量,最后都加起来就是答案,但代码写完才发现这种思路只能解决只有一组木板重叠的用例。苦思冥想后,我换了种思路那就是先将木板根据最右端也就是target[i][1],进行从小到大排序,再用一个变量从第一个木板的右端开始遍历,对于下一块木板,如果这块木板的左端小于前一个木板的右端,这块木板的右端大于前一块木板的右端,说明这两块木板可以被一根针打到,我们将这个用来记录x坐标的变量更新为这块木板的右端再去判断下一块木板,同理,当下一块木板不满足上述条件,说明我们需要另一根针来击碎它,针的数量加一,仍然将将这个用来记录x坐标的变量更新为这块木板的右端再去判断下一块木板,当这个变量等于最后一块木板的右端时,得出答案

测试用例:

样例1:

输入:k = 4, p = 100, target = [[10, 26, 3], [4, 8, 29], [1, 5, 8], [9, 9, 9]]
输出:3

样例2:

输入:k = 3, p = 100, target = [[10, 26, 3], [4, 8, 29], [1, 5, 8]]
输出:2

样例3:

输入:k = 5, p = 100, target = [[5, 15, 5], [1, 2, 3], [20, 25, 2], [6, 18, 2], [30, 40, 1]]
输出:4

样例4:

输入:k = 2, p = 100, target = [[0, 10, 5], [15, 20, 3]]
输出:2

样例5:

输入:k = 6, p = 100, target = [[3, 8, 10], [5, 10, 12], [1, 3, 14], [15, 18, 10], [20, 25, 10], [8, 12, 10]]
输出:4

话不多说直接上代码:

 public static int[][] sortTargets(int[][] target) {
        Arrays.sort(target, (a, b) -> a[1] - b[1]);
        return target;
    }//排序函数(根据右端排序)

    public static int solution(int k, int p, int[][] target) {
        target = sortTargets(target);//对原数组进行排序
        int sum = 0;//针的数量
        int i = 0;//数组索引
        while (i < k) {
            int right = target[i][1];
            int j = i + 1;//判断下一个木板
            while (j < k && target[j][0] <= right) {
                j++;//符合条件跳过
            }
            if(j < k){
                right = target[j][1];//更新指针
            }
            i = j;//更新索引
            sum++;//针数量加1
        }
        return sum % p;//对p取模返回
    }

通过截图:

Snipaste_2024-11-05_20-58-01.png