【问题标题】:Design a stack with operations on middle element设计一个对中间元素进行操作的堆栈
【发布时间】:2013-06-04 18:10:11
【问题描述】:

如何实现一个支持O(1)时间复杂度以下操作的栈?

  1. 将元素添加到堆栈顶部的推送。
  2. 从栈顶移除元素的 Pop。
  3. 查找将返回堆栈中间元素的中间元素。
  4. Delete Middle 将删除中间元素

【问题讨论】:

  • 带哨兵节点的循环双向链表,指向中间元素的指针,布尔值存储堆栈是否有偶数个元素。
  • 使所有删除的特殊情况消失。
  • 如果有2个元素,哪个是中间的?

标签: algorithm stack implementation


【解决方案1】:

这里是基于数组的实现

/**
 * Stack implementation with 
 * push // push the element at top of stack
 * pop // removes and returns the element from top of stack
 * findMiddle // returns the element from middle of stack
 * deleteMiddle // deletes the element from middle of stack
 * @author manjeet
 * @param <E>
 */

public class Stack<E> {
  private final int size;
  private int top;
  private E[] elements;

  /**
   * Constructor with default size
   */
  public Stack() {
    this(10);
  }

  public Stack(int s) {
    size = s > 0 ? s : 10;
    top = -1;
    elements = (E[]) new Object[size]; 
  }

  /**
   * Push element e to stack if it is not full
   * @param e
   */
  public void push(E e) {
    if (top == size - 1){
     // if stack is full
        System.out.println("Stack is full, cannot push element " +  e);
    }else{
        elements[++top] = e; // place e on Stack
    } 
  }

  /**
   * pop element from the top of the stack if it is not empty
   * @return top of the stack
   */
  public E pop() {
    E e = null;
    if (top == -1){
     // if stack is empty
        System.out.println("Stack is empty, cannot pop");
    }else{
        e = elements[top--]; // remove and return top element of Stack
    } 
    return e;
  }

  /**
   * Give middle element of the stack if it is not empty
   * @return middle element of the stack
   */
  E findMiddle() {
      if (top == -1){
          System.out.println("Stack is empty, cannot pop");
          return null;
      }
      return elements[top/2];
  }

  /**
   * Delete middle element of the stack if it is not empty
   * @return middle element of the stack
   */
  E deleteMiddle(){
      if (top == -1){
          System.out.println("Stack is empty, cannot pop");
          return null;
      }
      int index = (int)top/2;
      E middle = elements[index];
      System.arraycopy(elements, index+1 , elements, index, (top-index));
      top--;
      return middle;
  }

  public static void main(String args[]) {

      Stack<Integer> stack = new Stack<Integer>();
      stack.push(1);
      stack.push(2);
      stack.push(3);
      stack.push(4);
      stack.push(5);
      stack.push(6);
      stack.push(7);

      System.out.println("deleted=" + stack.deleteMiddle());
      System.out.println("middle=" + stack.findMiddle());
      System.out.println("popped=" + stack.pop());



    }
}

【讨论】:

    【解决方案2】:

    使用带有指向中间元素的额外指针的 LinkedList 数据结构。 此外,您还需要另一个变量 Var 来存储 LinkedList 是否包含偶数或奇数元素。

    • 将元素添加到堆栈顶部的推送。

    将元素添加到 LinkedList 的头部。根据Var更新指向中间元素的指针

    • 从栈顶移除元素的 Pop。

    移除 LinkedList 的头部。根据Var更新指向中间元素的指针

    • 查找将返回堆栈中间元素的中间元素。

    使用指向中间元素的指针

    • Delete Middle 将删除中间元素

    将下一个元素的值复制到中间,删除下一​​个元素。这里有更详细的描述:http://www.mytechinterviews.com/singly-linked-list-delete-node

    【讨论】:

    • 为什么不用数组或列表? Java 还使用内部数组作为堆栈的实现
    • 使用数组,我们将无法删除 O(1) 中的中间元素,因为它在中间,删除它需要将其余元素移动一个位置。
    • Stack => {top -> 1 -> 2 -> middle -> 3 -> 4 -> bottom} ,对于像这样的给定 Single LL,你将如何将中间指针移动到元素 2 时元素被推到顶部,但接下来的每个节点都指向下方。所以我相信这个问题可以使用DLL来解决,或者修改Single LL节点结构来处理这种情况。
    【解决方案3】:

    使用带有指向头、尾和中间元素的指针的 LinkedList 数据结构。

    这会给您推送、弹出和删除中间元素以及搜索的 O(1) 时间复杂度。

    唯一的技巧是在从这个数据结构中添加或减去元素时正确移动“中间”元素指针。

    【讨论】:

    • 为什么不用数组或列表? Java 还使用内部数组作为堆栈的实现
    猜你喜欢
    • 2011-06-17
    • 2019-10-14
    • 2013-05-03
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-14
    • 2011-01-23
    相关资源
    最近更新 更多