算法 1.3.1 最小棧 【leetcode 155】

題目描述

最小棧
設(shè)計一個支持 push 灵巧,pop 搀矫,top 操作,并能在常數(shù)時間內(nèi)檢索到最小元素的棧刻肄。

push(x) —— 將元素 x 推入棧中瓤球。
pop() —— 刪除棧頂?shù)脑亍?br> top() —— 獲取棧頂元素。
getMin() —— 檢索棧中的最小元素敏弃。

示例:
輸入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
輸出:
[null,null,null,null,-3,null,0,-2]

解釋:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

數(shù)據(jù)結(jié)構(gòu)

  • 數(shù)組(棧)卦羡、鏈表(鏈棧)

算法思維

  • 遍歷、狀態(tài)機麦到、快照绿饵、棧特性(LIFO)

解題要點

  • 使用快照記錄狀態(tài)信息
  • 利用棧的 LIFO 特性,實現(xiàn)狀態(tài)信息的 更新/回滾

解題思路

一. Comprehend 理解題意
  • 需要自實現(xiàn)一個棧結(jié)構(gòu)
  • 除了基礎(chǔ)的入棧瓶颠、出棧拟赊、查看棧頂功能外,還需要實現(xiàn)一個查詢最小值的功能
二. Choose 選擇數(shù)據(jù)結(jié)構(gòu)與算法
解法一:使用數(shù)組實現(xiàn)棧結(jié)構(gòu)粹淋,棧的最小值通過遍歷數(shù)組獲得
  • 數(shù)據(jù)結(jié)構(gòu):數(shù)組
  • 算法思維:遍歷
三. Code 編碼實現(xiàn)基本解法
class MinStack {

        //1.聲明存放數(shù)據(jù)的數(shù)組和棧頂指針
        Integer[] arr;
        int index;

        /**
         * initialize your data structure here.
         */
        public MinStack() {
            //2.構(gòu)造器中進行參數(shù)初始化
            arr = new Integer[1000];
            index = -1;
        }

        public void push(int x) {
            //3.入棧 -- 自動裝箱
            arr[++index] = x;

            //數(shù)組擴容
            if (index == arr.length*0.8){
                Integer[] arr1 = new Integer[arr.length*2];
                for (int i=0; i<arr.length; i++){
                    arr1[i] = arr[i];
                }
                arr = arr1;
            }
        }

        public void pop() {
            if(index < 0) return;
            //4.出棧 -- 相當(dāng)于刪除棧頂元素 -- 棧頂賦值為 null
            arr[index--] = null;
        }

        public int top() {
            if (index < 0) return Integer.parseInt(null);
            //5.返回棧頂元素 -- 自動拆箱
            return arr[index];
        }

        public int getMin() {
            if (index < 0) return Integer.parseInt(null);

            //6.遍歷數(shù)組尋找最小值
            int minus = arr[0]; //最小值
            for (int i=1; i<=index; i++){
                minus = arr[i] < minus ? arr[i] : minus;
            }
            return minus;
        }
    }

執(zhí)行耗時:65 ms吸祟,擊敗了 7.35% 的Java用戶
內(nèi)存消耗:40.2 MB,擊敗了 55.30% 的Java用戶
時間復(fù)雜度:O(n) -- 數(shù)組的遍歷 O(n)桃移,數(shù)組的擴容 O(n)
空間復(fù)雜度:O(n) -- 數(shù)組的內(nèi)存空間 O(n)

四. Consider 思考更優(yōu)解

改變算法思維屋匕!

思路:
  • 每次獲取最小值時,都需要重新 遍歷 數(shù)組借杰,效率很低
  • 不難發(fā)現(xiàn)过吻,每個元素在被壓入棧頂?shù)臅r候,棧的最小值都只有 兩種狀態(tài)
    1.當(dāng)前元素為最小值(狀態(tài)一:某個新的數(shù)值)
    2.以前的最小值仍為最小值(狀態(tài)二:原數(shù)值)
  • 能否利用棧的特性第步,彈出棧頂元素的時候疮装,將最小值的狀態(tài)變化也一并彈出缘琅?
方法:
  • 讓每個元素都攜帶一個“快照”,記錄此元素入棧后(這一時刻)棧的最小值廓推。
  • 當(dāng)前棧的最小值 == 當(dāng)前棧頂元素快照中的值
  • 當(dāng)棧頂元素被彈出刷袍,上個元素成為棧頂,上個快照被啟用樊展,最小值回滾
解法二:使用鏈表實現(xiàn)棧結(jié)構(gòu)呻纹,棧的最小值由棧頂元素攜帶
  • 數(shù)據(jù)結(jié)構(gòu):鏈表(鏈棧)
  • 算法思維:狀態(tài)機、快照专缠、棧特性(LIFO)
五. Code 編碼實現(xiàn)最優(yōu)解
 class MinStack {

        //1.聲明一個內(nèi)部類 -- 鏈表節(jié)點
        private class Node{
            int val; //當(dāng)前節(jié)點值
            int min; //最小值快照 -- 當(dāng)前節(jié)點入棧后雷酪,棧的最小值

            Node next; //指針

            public Node(){}

            public Node(int val, int min, Node next){
                this.val = val;
                this.min = min;
                this.next = next;
            }
        }

        //2.聲明一個鏈表頭 -- 棧頂
        Node head;

        /**
         * initialize your data structure here.
         */
        public MinStack() {
            //3.初始化鏈棧
            head = null;
        }

        public void push(int x) {
            //4.節(jié)點入棧時,判斷鏈表長度
            if (head == null) {
                head = new Node(x,x,null);
            } else {
                //5.每次入棧時涝婉,比較最小值哥力,將此刻的最小值存入 new Node().min 中
                head = new Node(x,Math.min(x,head.min),head);
            }
        }

        public void pop() {
            //6.出棧時,直接彈出即可墩弯,最小值隨之回滾
            if (head != null) head = head.next;
        }

        public int top() {
            //7.查棧頂
            return head != null ? head.val : Integer.parseInt(null);
        }

        public int getMin() {
            //8.查最小值 -- 其實就是查當(dāng)前棧頂?shù)淖钚≈悼煺?            return head != null ? head.min : Integer.parseInt(null);
        }
    }

執(zhí)行耗時:6 ms吩跋,擊敗了 96.02% 的Java用戶
內(nèi)存消耗:40.3 MB,擊敗了 36.21% 的Java用戶
時間復(fù)雜度:O(1) -- 棧頂元素的直接查詢 O(1)
空間復(fù)雜度:O(n) -- 鏈棧的內(nèi)存空間 O(n)

六. Change 變形與延伸

=== 待續(xù) ===

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渔工,一起剝皮案震驚了整個濱河市锌钮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌引矩,老刑警劉巖梁丘,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異旺韭,居然都是意外死亡氛谜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門茂翔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來混蔼,“玉大人,你說我怎么就攤上這事珊燎。” “怎么了遵湖?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵悔政,是天一觀的道長。 經(jīng)常有香客問我延旧,道長谋国,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任迁沫,我火速辦了婚禮芦瘾,結(jié)果婚禮上捌蚊,老公的妹妹穿的比我還像新娘。我一直安慰自己近弟,他們只是感情好缅糟,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祷愉,像睡著了一般窗宦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上二鳄,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天赴涵,我揣著相機與錄音,去河邊找鬼订讼。 笑死髓窜,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的欺殿。 我是一名探鬼主播寄纵,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祈餐!你這毒婦竟也來了擂啥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤帆阳,失蹤者是張志新(化名)和其女友劉穎哺壶,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜒谤,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡山宾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鳍徽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片资锰。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖阶祭,靈堂內(nèi)的尸體忽然破棺而出绷杜,到底是詐尸還是另有隱情,我是刑警寧澤濒募,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布鞭盟,位于F島的核電站,受9級特大地震影響瑰剃,放射性物質(zhì)發(fā)生泄漏齿诉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望粤剧。 院中可真熱鬧歇竟,春花似錦、人聲如沸抵恋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽馋记。三九已至号坡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梯醒,已是汗流浹背宽堆。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留茸习,地道東北人畜隶。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像号胚,于是被迫代替她去往敵國和親籽慢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 題目:設(shè)計一個支持 push猫胁,pop箱亿,top 操作,并能在常數(shù)時間內(nèi)檢索到最小元素的棧弃秆。 push(x) -- 將...
    關(guān)山Kwan閱讀 217評論 0 0
  • 題目 設(shè)計一個支持 push届惋,pop,top 操作菠赚,并能在常數(shù)時間內(nèi)檢索到最小元素的棧脑豹。 push(x) -- 將...
    就是會把話說反閱讀 154評論 0 0
  • 查看題目詳情可點擊此處。 題目 設(shè)計一個支持 push衡查,pop瘩欺,top 操作,并能在常數(shù)時間內(nèi)檢索到最小元素的棧拌牲。...
    Cloneable閱讀 238評論 0 0
  • 題目描述 [最小棧] 設(shè)計一個支持 push俱饿,pop,top 操作塌忽,并能在常數(shù)時間內(nèi)檢索到最小元素的棧稍途。 push...
    一只可愛的檸檬樹閱讀 98評論 0 1
  • 設(shè)計一個支持 push ,pop ,top 操作装盯,并能在常數(shù)時間內(nèi)檢索到最小元素的棧坷虑。 push(x) —— 將元...
    放下梧菲閱讀 117評論 0 0