我正在做练习问题Practice IT Kth Smallest
这个问题基本上是你在PriorityQueue和某个k中传递的,你将返回该PriorityQueue中的第k个最小值。您还要将PriorityQueue恢复到其初始状态,并可以使用一个堆栈或队列作为辅助数据结构。
我的更高级别的伪思想是因为PriorityQueue已经从Java PriorityQueue充当了最小堆,我真正需要做的就是(我的算法):
从PriorityQueue
将第k个最小值存储为局部变量
将已移除的k个元素推送到堆栈(堆栈,以便我可以按相同的顺序添加元素)
弹出堆栈中的所有元素并将其重新添加回PriorityQueue
返回第k个最小值
以下是执行所有操作的代码:
public int kthSmallest(PriorityQueue<Integer> pQ, int k) {
if(k <= 0 || k > pQ.size()) {
throw new IllegalArgumentException();
} else {
Stack<Integer> aux = new Stack<Integer>();
int kThSmallest = -1;
for(int c=0;c<k;c++){
int element = pQ.remove();
if(c == k-1)
kThSmallest = element;
aux.push(element);
}
while(!aux.isEmpty())
pQ.add(aux.pop());
return kThSmallest;
}
}
当我运行程序时,我得到所有正确的输出,以kth最小,但我无法恢复我的PriorityQueue的状态。例如,传递PriorityQueue:
时[-3, 9, 17, 22, 42, 81] with a k of 3
...我的算法生成了正确的结果,17但是它将PriorityQueue的状态更改为[-3, 17, 9, 81, 22, 42]
,这是意料之外的。
我考虑制作PriorityQueue的副本,但违反了一个条件,&#34;您可以使用一个堆栈或队列作为辅助数据结构&#34;。
如何恢复PriorityQueue的状态?
答案 0 :(得分:2)
您的实施需要调整两件事。首先,您应该使用队列而不是堆栈作为辅助数据结构。将项目推入堆栈然后将其弹出将导致它们以相反的顺序添加回优先级队列。如果它们作为1, 2, 3
从优先级队列中退出,则它们将作为3, 2, 1
添加回优先级队列。这是因为堆栈是LIFO(后进先出)数据结构。您希望将队列用作辅助数据结构,因为它是FIFO(先进先出)数据结构,因此它将保留相同的顺序。
其次,您只将第一个k元素拉出priorty队列。我建议排空整个队列,以便按顺序将所有元素添加回队列,而不仅仅是一些。
换句话说,我会按如下方式调整你的程序:
public int kthSmallest(PriorityQueue<Integer> pQ, int k) {
if(k <= 0 || k > pQ.size()) {
throw new IllegalArgumentException();
} else {
Queue<Integer> aux = new ArrayDeque<Integer>();
int kThSmallest = -1;
for(int c=0;c<pQ.size();c++){
Integer element = pQ.remove();
if(c == k-1)
kThSmallest = element;
aux.add(element);
}
while(!aux.isEmpty())
pQ.add(aux.remove());
return kThSmallest;
}
}
注意:我将程序中的'element'变量从int
类型更改为Integer
。这与你的程序的正确性无关,但注意自动拳击是一个好习惯。通用类型(如集合)使用盒装整数。这是一个存储原始整数的对象。将盒装整数分配给int
类型的某些内容需要将其取消装箱,即转回int
原语。这不是什么大问题,除了你立即将这个值重新添加回集合中。由于您已将其拆箱为原始int
,因此需要将其重新装箱回Integer
,这需要系统创建一个对象来存储它。因为您所做的一切如果将值取出并将其放回集合中,最好在此处使用Integer
值,以避免取消装箱和装箱值,因为它不是真正需要的。