LeetCode:最小棧(c#)

一、題目內容


設計一個支持 push,pop,top 操作,並能在常數時間內檢索到最小元素的棧。

  • push(x) – 將元素 x 推入棧中。
  • pop() – 刪除棧頂的元素。
  • top() – 獲取棧頂元素。
  • getMin() – 檢索棧中的最小元素。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

二、解題思路

解題思路一(維護一個有序的鏈表)


  • 1.實現棧效果可以使用Stack類型來完成
  • 2.實現“在常數時間內檢索到最小元素的棧”可以維護一個[有序雙向鏈表(升序)]
  • a.棧中Push新元素就插入到[有序雙向鏈表(升序)]中【時間複雜度O(n)】
    b.查詢最小元素就直接把[有序雙向鏈表(升序)]第一個元素返回【時間複雜度O(1)】
    c.刪除棧頂元素就把刪除的那個元素,在[有序雙向鏈表(升序)]中刪除【時間複雜度O(1)】
    

代碼實現

public class MinStack
{
    /*
     *  1.實現棧效果可以使用Stack<T>類型來完成
     *  2.實現“在常數時間內檢索到最小元素的棧”可以維護一個[有序雙向鏈表(升序)],
     *      a.棧中Push新元素就插入到[有序雙向鏈表(升序)]中【時間複雜度O(n)】
     *      b.查詢最小元素就直接把[有序雙向鏈表(升序)]第一個元素返回【時間複雜度O(1)】
     *      c.刪除棧頂元素就把刪除的那個元素,在[有序雙向鏈表(升序)]中刪除【時間複雜度O(1)】
     */
    public MinStack()
    {
        _stack = new Stack<LinkedListNode>();
    }

    /// <summary>
    /// 棧
    /// </summary>
    private readonly Stack<LinkedListNode> _stack;

    /// <summary>
    /// 第一個元素【最小元素】
    /// </summary>
    private LinkedListNode _top;

    /// <summary>
    /// 向雙向鏈表插入一個元素
    /// </summary>
    /// <param name="node">插入的節點【一定是乾淨的節點 Left = null && Right = null】</param>
    private void AddLinkedListNode(LinkedListNode node)
    {
        //判斷_top 是否爲null
        if (_top == null)
        {
            //如果爲null就賦值當前節點爲top【結束】
            _top = node;
            return;
        }

        //判斷_top節點是否大於當前節點
        if (_top.Value > node.Value)
        {
            //如果大於,將當前節點和_top節點互換位置,並關聯【結束】
            node.Right = _top;
            _top.Left = node;
            _top = node;
            return;
        }

        //循環查詢從_top節點開始查詢,下個節點是否爲null或者大於等於當前節點
        var upNode = _top;
        while (upNode.Right != null && upNode.Right.Value < node.Value)
        {
            upNode = upNode.Right;
        }

        //如果爲null就將上一個節點下和當前節點關聯
        if (upNode.Right == null)
        {
            upNode.Right = node;
            node.Left = upNode;
        }
        //如果大於就將上一個節點和下一個節點中插入當前節點【結束】
        else
        {
            node.Left = upNode;
            node.Right = upNode.Right;

            upNode.Right.Left = node;

            upNode.Right = node;
        }
    }

    /// <summary>
    /// 雙向鏈表移除一個元素
    /// </summary>
    /// <param name="node">移除的節點</param>
    private void RemoveLinkedListNode(LinkedListNode node)
    {
        //當前節點是否有left
        if (node.Left == null)
        {
            //沒有就將當前節點的子節點賦值爲_top,並將當前節點和右節點斷開連接【返回】
            //判斷右節點是否爲null,如果爲null就不需要斷開連接
            _top = node.Right;
            if (node.Right != null)
                node.Right.Left = null;
        }
        else
        {
            //讓左邊節點和右邊節點連接
            node.Left.Right = node.Right;
            if (node.Right != null)
                node.Right.Left = node.Left;
        }
    }

    /// <summary>
    /// 將元素 x 推入棧中。
    /// </summary>
    public void Push(int x)
    {
        var node = new LinkedListNode(x);
        //棧中Push新元素就插入到[有序雙向鏈表(升序)]中【時間複雜度O(n)】
        AddLinkedListNode(node);
        //將元素加入棧
        _stack.Push(node);
    }

    /// <summary>
    /// 刪除棧頂的元素。
    /// </summary>
    public void Pop()
    {
        //取出並移除棧頂元素
        var node = _stack.Pop();
        //刪除棧頂元素就把刪除的那個元素,在[有序雙向鏈表(升序)]中刪除【時間複雜度O(1)】
        RemoveLinkedListNode(node);
    }

    /// <summary>
    /// 獲取棧頂元素。
    /// </summary>
    public int Top()
    {
        //取出棧頂元素,並返回其值
        return _stack.Peek().Value;
    }

    /// <summary>
    /// 檢索棧中的最小元素。
    /// </summary>
    public int GetMin()
    {
        if (_top == null) return 0;
        //查詢最小元素就直接把[有序雙向鏈表(升序)]第一個元素返回【時間複雜度O(1)】
        return _top.Value;
    }

    /// <summary>
    /// 雙向鏈表節點
    /// </summary>
    public class LinkedListNode
    {
        public LinkedListNode(int value)
        {
            Value = value;
        }

        /// <summary>
        /// 左節點
        /// </summary>
        public LinkedListNode Left { get; set; }

        /// <summary>
        /// 右節點
        /// </summary>
        public LinkedListNode Right { get; set; }

        /// <summary>
        /// 值
        /// </summary>
        public int Value { get; set; }

        public override string ToString()
        {
            return Value.ToString();
        }
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.Push(x);
 * obj.Pop();
 * int param_3 = obj.Top();
 * int param_4 = obj.GetMin();
 */

解題思路二(維護一個最小值)


  • 1.實現棧效果可以使用Stack類型來完成
  • 2.實現“在常數時間內檢索到最小元素的棧”直接維護一個[最小值變量]
  • a.Push新值時更新下最小值【時間複雜度O(1)】
    b.Pop刪除棧頂的元素時,更新最小值【時間複雜度O(n)】
    c.GetMin 檢索棧中的最小元素,就返回[最小值變量]【時間複雜度O(1)】
    

代碼實現

public class MinStack
{
    /*
     *  1.實現棧效果可以使用Stack<T>類型來完成
     *  2.實現“在常數時間內檢索到最小元素的棧”直接維護一個[最小值變量]
     *      a.Push新值時更新下最小值【時間複雜度O(1)】
     *      b.Pop刪除棧頂的元素時,更新最小值【時間複雜度O(n)】
     *      c.GetMin 檢索棧中的最小元素,就返回[最小值變量]【時間複雜度O(1)】
     */
    public MinStack()
    {
        _stack = new Stack<int>();
    }

    /// <summary>
    /// 棧
    /// </summary>
    private readonly Stack<int> _stack;

    /// <summary>
    /// 存儲最小值
    /// </summary>
    private int _min = int.MaxValue;

    /// <summary>
    /// 將元素 x 推入棧中。
    /// </summary>
    public void Push(int x)
    {
        //將元素加入棧
        _stack.Push(x);
        _min = Math.Min(_min, x);
    }

    /// <summary>
    /// 刪除棧頂的元素。
    /// </summary>
    public void Pop()
    {
        //取出並移除棧頂元素
        var x = _stack.Pop();
        //判斷移除的值是否爲最小值,如果不是就不需要更新最小值
        if (x == _min)
        {
            //更新最小值
            _min = _stack.Any() ? _stack.Min() : int.MaxValue;
        }
    }

    /// <summary>
    /// 獲取棧頂元素。
    /// </summary>
    public int Top()
    {
        //取出棧頂元素
        return _stack.Peek();
    }

    /// <summary>
    /// 檢索棧中的最小元素。
    /// </summary>
    public int GetMin()
    {
        return _min;
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.Push(x);
 * obj.Pop();
 * int param_3 = obj.Top();
 * int param_4 = obj.GetMin();
 */
發佈了53 篇原創文章 · 獲贊 56 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章