【面試現場】如何實現可以獲取最小值的棧?
點選上方“程式人生”,選擇“置頂公眾號”
第一時間關注程式猿(媛)身邊的故事
作者
channingbreeze
已獲原作者授權,如需轉載,請聯絡原作者。
小史是一個應屆生,雖然學的是電子專業,但是自己業餘時間看了很多網際網路與程式設計方面的書,一心想進BAT。
今天他又去BAT中的一家面試了。
簡單的自我介紹後,面試官給了小史一個問題。
【面試現場】
如何實現可以獲取最小值的棧
基礎資料結構靈活運用
題目:我現在需要實現一個棧,這個棧除了可以進行普通的push、pop操作以外,還可以進行getMin的操作,getMin方法被呼叫後,會返回當前棧的最小值,你會怎麼做呢?你可以假設棧裡面存的都是int整數。
小史熟練地把程式碼寫了出來。
import java.util.ArrayList;
import java.util.List;
/**
* @author xiaoshi on 2018/9/1.
*/
public class MinStack {
private List<Integer> data = new ArrayList<Integer>();
private List<Integer> mins = new ArrayList<Integer>();
public void push(int num) {
data.add(num);
if (mins.size() == 0) {
// 初始化mins
mins.add(num);
} else {
// 輔助棧mins每次push當時最小值
int min = getMin();
if (num >= min) {
mins.add(min);
} else {
mins.add(num);
}
}
}
public int pop () {
// 棧空,異常,返回-1
if(data.size() == 0) {
return -1;
}
// pop時兩棧同步pop
mins.remove(mins.size() - 1);
return data.remove(data.size() - 1);
}
public int getMin() {
// 棧空,異常,返回-1
if(mins.size() == 0) {
return -1;
}
// 返回mins棧頂元素
return mins.get(mins.size() - 1);
}
}
【請教大神】
小史回到學校,把面試的情況和計算機學院的呂老師說了一下。
【異常情況處理】
呂老師:面試官已經提出了你的異常處理有點問題,當棧內為空的時候,你返回-1,但是如果使用者push過-1,那麼你返回-1的時候,是使用者push進來的值,還是棧為空,就不得而知了。
小史咬咬牙:那就再定義一個類,裡面包括一個int的data和一個boolean的isSuccess,正常情況下isSuccess是true,棧為空的話,isSuccess是false。這樣就能區分開了吧?
小史突然一拍大腿:對哦,我可以用一個包裝類Integer來定義返回值,如果是空,就代表棧為空就行了。它和int的區別就是它多了一個null,正好用來返回異常情況。
呂老師:嗯,越來越好,但是還是有點問題。你並沒有站在使用者的角度考慮問題。使用你這個棧的人,在pop的時候,他並不知道可能返回null,如果他不做判斷,後面的程式碼就可能丟擲空指標了。
呂老師發來一個表情。
呂老師:沒錯,最關鍵的是,你顯式丟擲異常,如果使用者不捕獲,那麼編譯就會報錯,這樣就把錯誤暴露在編譯階段,並且不需要和任何人商量所謂的特殊返回值了。
【演算法優化】
呂老師一眼看穿了小史的心思。
小史想了想:明白了,我可以在push的時候判斷一下,如果比最小值還大,就不加入輔助棧。pop的時候,如果不是最小值,輔助棧就不出棧。這樣一來,輔助棧就不會有大量重複元素了。
小史:push的時候進行判斷,如果數值比當前最小值大,就不動mins棧了,這樣mins棧中不會儲存大量冗餘的最小值。pop的時候同樣進行判斷,只有pop出的數就是當前最小值的時候,才讓mins出棧。
小史:如果push一個和最小值相等的元素,還是要入mins棧。不然當這個最小值pop出去的時候。data中還會有一個最小值元素,而mins中卻已經沒有最小值元素了。
小史:mins棧中改存最小值在data陣列中的索引。這樣一來,當push了與最小值相同元素的時候,就不需要動mins棧了。而pop的時候,pop出的元素的索引如果不是mins棧頂元素,mins也不出棧。同時,獲取最小值的時候,需要拿到mins棧頂元素作為索引,再去data陣列中找到相應的數作為最小值。
理解了演算法之後,小史的程式碼寫起來也是非常快,不一會兒就寫好了:
import java.util.ArrayList;
import java.util.List;
/**
* @author xiaoshi on 2018/9/1.
*/
public class MinStack {
private List<Integer> data = new ArrayList<Integer>();
private List<Integer> mins = new ArrayList<Integer>();
public void push(int num) throws Exception {
data.add(num);
if(mins.size() == 0) {
// 初始化mins
mins.add(0);
} else {
// 輔助棧mins push最小值的索引
int min = getMin();
if (num < min) {
mins.add(data.size() - 1);
}
}
}
public int pop() throws Exception {
// 棧空,丟擲異常
if(data.size() == 0) {
throw new Exception("棧為空");
}
// pop時先獲取索引
int popIndex = data.size() - 1;
// 獲取mins棧頂元素,它是最小值索引
int minIndex = mins.get(mins.size() - 1);
// 如果pop出去的索引就是最小值索引,mins才出棧
if(popIndex == minIndex) {
mins.remove(mins.size() - 1);
}
return data.remove(data.size() - 1);
}
public int getMin() throws Exception {
// 棧空,丟擲異常
if(data.size() == 0) {
throw new Exception("棧為空");
}
// 獲取mins棧頂元素,它是最小值索引
int minIndex = mins.get(mins.size() - 1);
return data.get(minIndex);
}
}
【小史的疑惑】
吃飯的時候,小史提出了心中埋藏已久的疑惑。
呂老師:資料結構和演算法的設計是一個程式設計師的內功,工作時雖然用不到這麼細,但是你在學習其他知識的底層原理的時候,到處都是資料結構和演算法。
相關推薦
【面試現場】如何實現可以獲取最小值的棧?
點選上方“程式人生”,選擇“置頂公眾號”第一時間關注程式猿(媛)身邊的故事作者channingb
如何實現可以獲取最小值的棧?
小史是一個應屆生,雖然學的是電子專業,但是自己業餘時間看了很多網際網路與程式設計方面的書,一心想進BAT。 今天他又去BAT中的一家面試了。 簡單的自我介紹後,面試官給了小史一個問題。 面試現場 題目:我現在需要實現一個棧,這個棧除了可以進行普通的pus
【面試現場】為什麼要分穩定排序和非穩定排序?
點選上方“程式人生”,選擇“置頂公眾號”第一時間關注程式猿(媛)身邊的故事作者channingb
【做題】POI2011R1 - Plot——最小圓覆蓋&倍增
增加 key void str ref 時間 cnblogs 答案 思路 原文鏈接 https://www.cnblogs.com/cly-none/p/loj2159.html 題意:給出\(n\)個點,你需要按編號將其劃分成不超過\(m\)段連續的區間,使得所有每個區
Java不確定參數的個數函數方法,實現求最小值
string 方法 argv 其中 span pub package values @param package 參數個數不確定方法; /** * @ClassName Test * @Description TODO * @Author cherry * @D
棧表中獲取最小值,時間複雜度為O(1)
近期複習資料結構,看到網上有一道演算法題,該題目曾經是google的一道面試題,國內的網際網路公司也紛紛效仿。我也順便複習之。 題目內容為:對現在的stack(棧)資料結構進行改進,加一個
1.給棧新增一個獲取最小值的方法(元素為Integer型),要求時間複雜度為O(1)
分析:在資料結構與演算法中,當要求時間複雜度最小時基本都是要犧牲空間複雜度。棧是先進後出,此處要求用棧實現一個獲取最小值的方法且時間複雜度為O(1),首先考慮的方向就是再借助一個棧來實現,這個棧主要用來儲存最小值序列(這個地方可以思考一下為什麼不能用一個變數來儲存最小值)。 下面直接附上程式碼:
【動態規劃】數字三角形最大值(一)(遞迴)
題目:數字三角形,形如 3 3 2 4 5 1 1 3 4 1 每個點只能選擇向左或向右走,取一條路徑,使得路徑上數字和最大。 無需求出路徑,求出最大值。 輸入n,和 n 行數字三角形 n<
【JavaEE筆記】Struts2 (三) ognl、值棧操作等
一. ognl概述 1. 在web階段,學習過EL表示式,EL表示式在JSP中獲取域物件裡面的值 2. ognl是一種表示式,這個表示式功能更加強大 i.在struts2裡面操作值棧資料 ii.
【LeetCode-面試演算法經典-Java實現】【064-Minimum Path Sum(最小路徑和)】
原題 Given a m x n grid filled with non-negative numbers, find a path from top left to botto
【資料結構】實現一個棧要求實現Push(出棧)Pop(入棧)Min(返回最小值)的時間 複雜度為O(1)
文章目錄 思路 MinStack.h MinStack.c Test.c 棧的基本實現: https://blog.csdn.net/weixin_41892460/article/details/8297385
【面試題】實現一個棧,要求Push(入棧),Pop(出棧),Min(返回最小值的操作)的時間複雜度為O(1)
問題描述:實現一個棧,要求Push(入棧),Pop(出棧),Min(返回最小值的操作)的時間複雜度為O(1) 分析問題:要記錄從當前棧頂到棧底元素的最小值,很容易想到用一個變數,每push一個元素更新一次變數的值。那麼問題來了,當執行pop操作時,上一次的最小值就找不到
【資料結構】實現一個棧,要求實現Push(出棧)、Pop(入棧)、Min(返回最小值的操作)的時間複雜度為O(1)
實現一個棧,要求實現Push(出棧)、Pop(入棧)、Min(返回最小值的操作)的時間複雜度為O(1) 在棧中操作的話,push和pop的時間複雜度就是O(1),所以我們只用實現Min(返回最小值的操作)的時間複雜度為O(1), 思想就是用兩個棧,一個就是普通的存取資料的
【棧佇列】實現一個棧Stack,要求實現Push(出棧)、Pop(入棧)、Min(返回最小值的操作)的時間複雜度為O(1)
問題分析 要記錄從當前棧頂到棧底元素的最小值,很容易想到用一個變數,每push一個元素更新一次變數的值。那麼問題來了,當執行pop操作時,上一次的最小值就找不到了。 解決方法 方法1、 使用一個棧。元素x入棧時,執行一次push(x),再push(min
【BZOJ2424】[HAOI2010]訂貨 最小費用流
需求 bfs pop 容量 family light 成本 pri || 【BZOJ2424】[HAOI2010]訂貨 Description 某公司估計市場在第i個月對某產品的需求量為Ui,已知在第i月該產品的訂貨單價為di,上個月月底未銷完的單位產品要付存貯費用
【BZOJ1336】[Balkan2002]Alien最小圓覆蓋 隨機增量法
tmp style i++ 5.1 logs eps light rip 個數 【BZOJ1336】[Balkan2002]Alien最小圓覆蓋 Description 給出N個點,讓你畫一個最小的包含所有點的圓。 Input 先給出點的個數N,2<
MT【61】含參數二次函數最大最小值
tco pla 最大 back inline 我們 最小 但是 alt 評:此類題目在高考中作為壓軸題也曾考過,一般通性通法都如上面的做法,但是我們如果可以站在包絡的角度,很多問題將變得很清晰:MT【61】含參數二次函數最大最小值
【十一】找出一組數組中最大值、最大值的角標、最小值、最小值的角標及平均數
思路 原來 比較 快捷 兩個 span div 選擇排序 分數 需求:現有一組評委打分的數據。 求出他們的最大值與最小值。 最大值最小值的角標 去除最大值與最小值後的平均數 代碼: 1 <?php 2 $arr=array(1,2,3,4); 3
Codeforces Round #283 (Div. 2) A. Minimum Difficulty【一個數組定義困難值是兩個相鄰元素之間差的最大值。 給一個數組,可以去掉任意一個元素,問剩余數列的困難值的最小值是多少】
分析 options force minimum sta cif als 最小 技術分享 A. Minimum Difficulty time limit per test 2 seconds memory limit per test 256 mega
Codeforces 455C Civilization:樹的直徑 + 並查集【合並樹後直徑最小】
font name read amp find() edge ceil -s class 題目鏈接:http://codeforces.com/problemset/problem/455/C 題意: 給你一個森林,n個點,m條邊。 然後有t個操作。共有兩種操