原题地址:[唐门绝技:暴雨梨花针最少发射次数](唐门绝技:暴雨梨花针最少发射次数 - 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取模返回
}