【问题标题】:Remove the last element in a queue移除队列中的最后一个元素
【发布时间】:2011-01-26 18:36:10
【问题描述】:

我需要删除队列的最后一个元素。 我可以使用的唯一操作是

  • Peek() - 获取第一个元素而不删除它
  • Enqueue(element) - 在队列后面插入一个元素
  • Dequeue() - 删除第一个元素
  • IsEmpty() - true 或 false 队列是否为空。

而且我不能使用数组或队列,元素个数不可用。

我想了一些解决办法,但每次都卡住了,因为我不知道如何判断当前元素是否是最后一个元素。

【问题讨论】:

  • 听起来像是功课。您可能想发帖到StackOverflow,但请务必将其标记为“家庭作业”,并包含有关您尝试的更多详细信息以及您已经完成的一些工作示例。
  • item = q.Dequeue() 直到 q.IsEmpty() ?
  • 这绝对是一个 Stack Overflow 问题,但 Bre 最好列出一些已经尝试过的东西。
  • @Martin,这将使队列为空。我们的想法是留下除了最后一个元素之外的所有内容。
  • 这种愚蠢的问题只能是家庭作业。如果你真的要问,你需要立即重新考虑你在做什么。

标签: algorithm queue


【解决方案1】:

Justin Beal's solution 更直接。但我认为它可以就地完成,而无需创建另一个队列。

object RemoveLast(Queue q) {
    object first = q.Peek();
    object current = null;
    while (true) {
        current = q.Dequeue();
        if (q.Peek() == first) {
            break;
        }
        q.Enqueue(current);
    }
    return current;
}

【讨论】:

  • 当 q 只有 1 个元素时,卡在循环中
  • @gli00001 它实际上会抛出 Peek() 因为队列是空的。所以中断条件应该类似于(q.Count == 0 || q.Peek() == first)
  • 在 java 中,它不会抛出,无论 peek() 的语言特定实现如何,如何:int size = q.size(); while (size-->0) { int current = q.poll();如果(大小==0){休息; } q.offer(当前); }
  • @gli00001 这是为 C# 设计的删除并重新添加除最后一项之外的所有项目。
【解决方案2】:

每次我都卡住了,因为我不知道如何判断当前元素是否是最后一个元素。

很好。由于您不知道“当前”元素是最后一个,因此您确实知道“上一个”元素是最后一个。

因此,通过保存前一个元素,您应该能够处理这个问题。

【讨论】:

    【解决方案3】:

    这样的事情会起作用:

    public Queue removeLast(Queue queue1){
    
      Queue queue2 = new Queue();
        
      while(!queue1.isEmpty()){
        Object o = queue1.dequeue();
        if(!queue1.isEmpty()){
          queue2.enqueue(o);
        }
      }
      return queue2;
    }
    

    【讨论】:

    • OP 必须到位。 “我无法使用任何数组或队列来帮助我”
    【解决方案4】:

    我有同样的要求,所以创建了一个扩展方法,如果他们的谷歌到达这里,其他人可以使用。

    using System.Collections.Generic;
    using System.Linq;
    
    /// <summary>
    /// Extensions for <see cref="System.Collections.Generic.Queue{T}"/>.
    /// </summary>
    public static class QueueExtensionsStatic
    {
        /// <summary>
        /// Removes the last item from the <see cref="System.Collections.Generic.Queue{T}"/>.
        /// </summary>
        /// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
        /// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
        /// <returns>Item removed from the <see cref="System.Collections.Generic.Queue{T}"/>.</returns>
        public static T Pop<T>(this Queue<T> q)
        {
            for (var i = 1; i < q.Count; i++)
                q.Enqueue(q.Dequeue());
    
            return q.Dequeue();
        }
    
        /// <summary>
        /// Removes the last <see cref="quantity"/> item(s) from the <see cref="System.Collections.Generic.Queue{T}"/>.
        /// </summary>
        /// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
        /// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
        /// <param name="quantity">Number of items to pop off the end of the <see cref="System.Collections.Generic.Queue{T}"/>.</param>
        /// <returns>Item removed from the <see cref="System.Collections.Generic.Queue{T}"/>.</returns>
        public static IEnumerable<T> Pop<T>(this Queue<T> q, int quantity)
        {
            for (var i = quantity; i < q.Count; i++)
                q.Enqueue(q.Dequeue());
    
            var poppedItems = new List<T>(quantity);
            for (int i = 0; i < quantity; i++)
                poppedItems.Add(q.Dequeue());
    
            return poppedItems;
        }
    
        /// <summary>
        /// Adds an item(<see cref="T"/>) to the start of the <see cref="System.Collections.Generic.Queue{T}"/>.
        /// </summary>
        /// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
        /// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
        public static void Push<T>(this Queue<T> q, T item)
        {
            q.Enqueue(item);
            for (var i = 1; i < q.Count; i++)
                q.Enqueue(q.Dequeue());
        }
    
        /// <summary>
        /// Adds items(<see cref="T"/>) to the start of the <see cref="System.Collections.Generic.Queue{T}"/>.
        /// </summary>
        /// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
        /// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
        /// <param name="items">List of items(<see cref="T"/>) to add to the <see cref="System.Collections.Generic.Queue{T}"/>.</param>
        public static void Push<T>(this Queue<T> q, IEnumerable<T> items)
        {
            if (items == null || !items.Any()) return;
    
            foreach (var item in items)
                q.Enqueue(item);
    
            for (var i = items.Count(); i < q.Count; i++)
                q.Enqueue(q.Dequeue());
        }
    }
    

    【讨论】:

      【解决方案5】:

      几天前,我在为我的作业实施类似要求时遇到了同样的问题。我认为解决这个问题的最简单方法是遍历队列并将“前”元素推到队列的后面并“弹出”它,但是当您到达队列中的最后一个元素时,只需“弹出”它并且不要“不要“推”它。

      【讨论】:

        【解决方案6】:

        我浏览了特立尼达提供的解决方案,这是迄今为止投票最多的答案。我猜这个解决方案只有在队列中的第一个元素/对象是唯一的时候才能完美运行。如果遇到第一个元素/对象的任何重复项,则无法将正确的元素作为最后一个元素。

        【讨论】:

        • 当队列有超过 1 个元素时,Trinidad 解决方案可以正常工作,
        • int size = q.size(); while (size-->0) { int current = q.poll();如果(大小==0){休息; } q.offer(当前); }
        猜你喜欢
        • 2022-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-10
        • 1970-01-01
        • 1970-01-01
        • 2011-06-27
        相关资源
        最近更新 更多