题目描述:
链接:https://www.nowcoder.com/questionTerminal/220361995bb64de08dc47c646ee111ab
来源:牛客网
一条直线上等距离放置了n台路由器。路由器自左向右从1到n编号。第i台路由器到第j台路由器的距离为| i-j |。 每台路由器都有自己的信号强度,第i台路由器的信号强度为ai。所有与第i台路由器距离不超过ai的路由器可以收到第i台路由器的信号(注意,每台路由器都能收到自己的信号)。问一共有多少台路由器可以收到至少k台不同路由器的信号。
输入描述:
输入第一行两个数n , k(1≤n , k≤10^5)
第二行n个数, a1 , a2 , a3……… , an(0≤ai≤10^9)
输出描述:
输出一个数,一共有多少台路由器可以收到至少k台不同路由器的信号。
示例1
输入
4 4
3 3 3 3
输出
4
解法:
import java.util.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String args[]) throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String line = bf.readLine();
String[] sp = line.split(" ");
int n = Integer.valueOf(sp[0]);
int k = Integer.valueOf(sp[1]);
int[][] scope = new int[n][2];
line = bf.readLine();
sp = line.split(" ");
for (int i = 0; i < n; i++) {
int cur = Integer.valueOf(sp[i]);
scope[i][0] = i- cur;//辐射区域左边界
scope[i][1] = i + cur;//辐射区域右边界
}
Arrays.sort(scope,(o1, o2) -> o1[0]-o2[0]);
PriorityQueue<Integer> heap = new PriorityQueue<>();//默认是小根堆
int count = 0;
int j = 0;
for (int i = 0; i < n; i++) {
while (j < n && scope[j][0] <= i){
heap.add(scope[j][1]);
j++;
}
while (!heap.isEmpty() && heap.peek() < i){
heap.poll();
}
if(heap.size() >= k){
count++;
}
}
bf.close();
System.out.println(count);
}
}
思路概述:
通过一个二维数组记录每一个坐标上的路由器的辐射区域的边界值。之后按照左边界排序。
一个位置如果要在一个区域里,则需要当前坐标大于等于左边界 并且 小于等于右边界。
所以遍历坐标值,如果区域左边界 小于等于 当前坐标,我们就让该区域的右边界进入小根堆(因为坐标是从小到大的,前置位的大于该区域左边界了,那后置位的一定也会大于。所以我们只需要进一次即可,把记录第几个范围区间的 j 定义在循环体外)。
然后不断判断堆顶(最小的右边界)是否小于当前坐标位置,如果小于,则出堆(同样的,一定也小于后置位)。
最后如果size符合条件,则count加一。