简体   繁体   English

在队列中查找最小值,并将其从队列中删除

[英]Finding the minimum value in a queue, and deleting it from the queue

I have a final exam coming up in a few weeks, and one of our practice questions is this: 我将在几周内完成期末考试,我们的实践问题之一是:

Given a queue of N integers, find the minimum value in the queue and delete it from the queue. 给定一个由N个整数组成的队列,请在队列中找到最小值并将其从队列中删除。 When you finish, the rest of the values must be in their original order. 完成后,其余值必须保持其原始顺序。 You can only use queue operations, ie, you do not have access to the underlying storage in an array or linked list. 您只能使用队列操作,即您无权访问数组或链表中的基础存储。 Describe the most time-efficient way to implement this operation and give the order (Big O) in terms of N. 描述实现此操作的最省时方法,并以N表示顺序(大O)。

I'm pretty lost as to how I'm going to go about this. 我对如何解决这个问题感到迷茫。

EDIT: Queue operations are "Enqueue", "Dequeue", "isFull", "isEmpty", and if it's a circular queue, "front" and "back". 编辑:队列操作为“入队”,“出队”,“ isFull”,“ isEmpty”,如果是循环队列,则为“前”和“后”。

If you have a queue and are only permitted to do enqueues and dequeues on it, then the only way you can find an arbitrary value in the queue is to perform as many dequeues are necessary to find that particular value. 如果您有一个队列,并且只允许在其上进行入队和出队,那么您可以在队列中找到任意值的唯一方法是执行尽可能多的出队以查找该特定值。 If you don't know where in the queue that value is, then in the worst case you might have to inspect all n elements of the queue, which takes Θ(n) time. 如果您不知道该值在队列中的什么位置,那么在最坏的情况下,您可能必须检查队列中的所有n个元素,这需要Θ(n)的时间。 So in that sense, any solution we come up with has to always do at least Θ(n) work in the worst case. 因此,从这个意义上讲,在最坏的情况下,我们想出的任何解决方案都必须至少做Θ(n)工作。

One way that you can go about doing this is to imagine treating the queue as if it's a ring of elements with a cursor in some position indicating the front. 您可以执行此操作的一种方法是,想象将队列视为元素环,并将光标放在指示前部的某个位置上。 If you dequeue an element and then immediately re-enqueue it, it's as if you've moved the cursor one spot clockwise (or counterclockwise - this is just a metaphor, after all). 如果您将元素出队,然后立即将其重新入队,就好像您已将光标顺时针(或逆时针)移动了一个点(毕竟,这只是一个隐喻)。 So you could consider solving this problem by moving the cursor around the queue until you find the element to delete, then dequeue it without re-enqueuing it, then moving the cursor around to back where you started. 因此,您可以考虑通过以下方式解决此问题:将光标移到队列中,直到找到要删除的元素,然后不重新排队就将其出队,然后再将光标移回开始的位置。 Here's one way to do this: 这是执行此操作的一种方法:

/* Store the number of elements in the queue, since it will change as
 * the loop runs. We want to visit each element exactly once.
 */
int numElems = queue.size();
for (int i = 0; i < numElems; i++) {
    ValueType elem = queue.dequeueMin();

    /* Remove the element if it matches the thing to get rid of, or,
     * equivalently, preserve the element if it isn't.
     */
    if (elem != theThingToRemove) {
        queue.enqueue(elem);
    }
}

This algorithm always does Θ(n) work - the loop visits each element exactly once and does O(1) total work - and O(1) total queue operations - per element. 该算法始终执行Θ(n)的工作-循环仅对每个元素进行一次访问,并且对每个元素执行O(1)的总工作-和O(1)的总队列操作。

Fun fact: this metaphor for a queue is exactly the idea behind a circular buffer, which is often used to implement fixed-sized queues. 有趣的事实:对队列的这种隐喻恰好是循环缓冲区背后的想法,通常用于实现固定大小的队列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM