我将在几周后进行期末考试,我们的一个练习题是:
给定N个整数的队列,找到队列中的最小值和 从队列中删除它。完成后,其余值必须 按原来的顺序。您只能使用队列操作,即 您无权访问阵列中的基础存储或链接 名单。描述实现此操作的最省时的方法 并以N为单位给出订单(Big O)。
我很遗憾我将如何解决这个问题。
编辑:队列操作是“Enqueue”,“Dequeue”,“isFull”,“isEmpty”,如果它是循环队列,则“前”和“后”。
答案 0 :(得分:3)
如果你有一个队列并且只允许对它进行入队和出列,那么在队列中找到任意值的唯一方法就是执行需要很多的队列才能找到该特定值。如果您不知道队列中该值的位置,那么在最坏的情况下,您可能必须检查队列中的所有n个元素,这需要Θ(n)时间。所以从这个意义上说,我们提出的任何解决方案都必须在最坏的情况下至少做Θ(n)工作。
你可以这样做的一种方法是想象将队列视为一个元素环,光标位于指示前方的某个位置。如果你将一个元素出列然后立即重新入队,那就好像你已经将光标顺时针移动了一个点(或者逆时针移动 - 毕竟这只是一个比喻)。因此,您可以考虑通过在队列中移动光标直到找到要删除的元素,然后将其出列而不重新排队,然后将光标移动到您开始的位置来解决此问题。这是一种方法:
/* 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);
}
}
这个算法总是做Θ(n)工作 - 循环完全访问每个元素一次,并且每个元素执行O(1)总工作 - 和O(1)总队列操作。
有趣的事实:这个队列的隐喻正是循环缓冲区背后的想法,循环缓冲区通常用于实现固定大小的队列。