queue.poll():
-
poll()是PriorityQueue类的方法,用于从队列中取出并移除 优先级最高的元素。由于这里的队列是根据自定义的比较器进行排序的,因此poll()会返回队列中优先级最高的元素。- 如果队列不为空,
poll()会返回并移除队列中的第一个元素。如果队列为空,则返回null排序发生的时机:
- 当你向队列中添加元素时,
PriorityQueue会根据比较器自动排序,即插入时就进行排序。 - 但是,优先队列本身并不会在插入每个元素时进行排序,而是保持一个堆结构,确保每次
poll()操作(即移除队头元素)时,队头元素是排序后的最小值。 - 所以在你执行
queue.add(new long[]{arr[i], i});时,队列的元素会被按这个规则“排好”。 - 当你调用
queue.poll()时,队头元素是最小的,这个操作会自动从队列中移除最小的元素,同时保持队列的排序结构。为什么这么做?
防止重复操作和保证正确性:
- 在你当前的程序中,元素的值可能会被修改(比如加到邻居元素上),如果没有这段代码,队列中的元素可能会包含已经被修改过的值。比如,如果
arr[index]被更新成了-1,但由于队列是基于堆结构的,它仍然存在于队列中,并且被错误地作为最小元素取出进行下一轮的处理。为了避免这种情况,就需要检查队列中的元素是否是最新的值。 - 如果某个元素的值已经被修改(例如变为
-1),它就不再是原来的有效值,因此不能再被继续处理。通过将其重新加入队列,确保队列中存的是未被更新过的有效数据,并且通过continue跳过已更新的元素,从而保证每次操作的正确性。
结论
这段代码的目的是确保队列中的元素总是保持最新状态,并且如果某个元素已经被更新过,它不会重复参与计算。通过这种方式,程序能够正确地执行每一轮的操作,避免了可能因为处理过期数据而导致的错误。
- 在你当前的程序中,元素的值可能会被修改(比如加到邻居元素上),如果没有这段代码,队列中的元素可能会包含已经被修改过的值。比如,如果
- 当你向队列中添加元素时,
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt() , k = sc.nextInt();
long[] arr = new long[n];
//queue存的是数组,在后面将值赋给cur时,cur[0]是值cur[1]是序号
PriorityQueue<long[]> queue = new PriorityQueue<>(((o1, o2) -> {
if (o1[0] == o2[0]) return Long.compare(o1[1],o2[1]);
else return Long.compare(o1[0],o2[0]);
}));
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
queue.add(new long[]{arr[i],i});
}
//关于优先队列的排序的时机:当向队列中添加元素时,优先队列会根据比较器自动排序,即插入时就进行排序
//但是优先队列本身并不会在插入每个元素时进行排序,它会保持一个堆结构,但是每次poll时,按排序规则移除
//比如在本题中是移除最小的
// for(long[] v:queue){
// System.out.print(Arrays.toString(v)+" ");
// }System.out.println();
while (k > 0) {
//一开始就进行赋值,并弹出队首元素
long[] cur = queue.poll();
long value = cur[0];
int index = (int) cur[1];
// for(long[] v:queue){
// System.out.print(Arrays.toString(v)+" ");
// }System.out.println();
//因为index和value在原始的数组中是一一对应的,如果不相等,说明发生了修改
//(说明这个元素的值已经被修改过了,可能已经参与了前面的加法操作(并且被标记为 -1))
//就将其重新加回队列
//保证如果队列中出现了已经更新过的元素,它不会继续参与本轮操作,而是等待下一轮被处理。
if (value != arr[index]) {
// System.out.printf("符合value != arr[%d]",index);
// System.out.println();
queue.add(new long[]{arr[index],index});
// for(long[] v:queue){
// System.out.print(Arrays.toString(v)+" ");
// }System.out.println();
continue;
}
// System.out.printf("%d arr前:",k);
// for(int i=0;i<arr.length;i++){
// System.out.print(arr[i]+" ");
// }System.out.println();
//因为是会影响左右两边,所以要向右和向左找
// 如果要是不符合数组的范围,就相当于出界了,就不找了
// 向左找
for (int i = index-1; i >= 0; i--) {
// System.out.printf("index=%d",i);
// System.out.println();
if (arr[i] != -1) {
arr[i] += value;
break;
}
}
// System.out.printf("%d arr中:",k);
// for(int i=0;i<arr.length;i++){
// System.out.print(arr[i]+" ");
// }System.out.println();
// 向右找
for (int i = index+1; i < n; i++) {
if (arr[i] != -1) {
arr[i] += value;
break;
}
}
// System.out.printf("%d arr后:",k);
// for(int i=0;i<arr.length;i++){
// System.out.print(arr[i]+" ");
// }System.out.println();
arr[index] = -1;
k--;
}
for (long x : arr) {
if (x > -1) System.out.print(x + " ");
}
}
}
浙公网安备 33010602011771号