[面試題]堆來模擬棧
阿新 • • 發佈:2018-12-19
#pre 面試的時候遇到的,面試官要求手寫程式碼。問題本身不難,但是需要注意自己的想法是否最優
#問題分析 堆是後進先出,棧是先進先出,所以自然而然有了想法1,用棧去儲存資料,如果需要返回資料,那麼新建一個棧,把原來棧所有的東西彈出來,退出最底部的元素,返回給外部,然後將棧還原。
//使用語言java import java.util.*; //這裡假定訪問方式是單執行緒,如果多執行緒訪問 需要對stack進行保護 public class Solution{ Stack<Object> valueStack; public Solution(){ //這部分宣告不確定,java中可能是這麼呼叫的 valueStack = new ArrayList<>(); } //返回值表明壓棧是否成功 public boolean push(Object value){ //棧溢位的時候會返回異常 try{ valueStack.push(value); }catch(Exception e){ return false; } return true; } //假定儲存的元素不會是null public Object pop(){ if(valueStack.size() <= 0){ return null; } Stack cacheStack = new ArrayList<>(); while(valueStack.size() > 0){ cacheStack.push(valueStack.pop()); } Object reval = cacheStack.pop(); while(cacheStack.size() > 0){ valueStack.push(cacheStack.pop()); } return reval; } }
#提示1:棧為什麼還原 在想法1的基礎上,在我們每次彈出一個元素的時候我們需要將棧反轉一次,然後還原回來,如果連續遇到兩次彈出操作,這個還原操作反而是浪費時間的操作,所以這裡可以得到想法2,我們可以通過狀態量來檢測這個連續彈出的情況,如果不是連續彈出,然後就可以不用還原棧。
//使用語言java import java.util.*; //這裡假定訪問方式是單執行緒,如果多執行緒訪問 需要對stack進行保護 public class Solution{ Stack<Object> valueStack; Stack<Object> cacheStack; boolean inOrigin; public Solution(){ //這部分宣告不確定,java中可能是這麼呼叫的 valueStack = new ArrayList<>(); cacheStack = new ArrayList<>(); inOrigin = true; } //返回值表明壓棧是否成功 public boolean push(Object value){ if(value == null){ return false; } //棧溢位的時候會返回異常 try{ if(!inOrigin){ while(cacheStack.size() > 0){ valueStack.push(cacheStack.pop()); } inOrigin = true; } valueStack.push(value); }catch(Exception e){ return false; } return true; } //假定儲存的元素不會是null public Object pop(){ if(inOrigin){ while(valueStack.size() > 0){ cacheStack.push(valueStack.pop()); } inOrigin = false; } if(cacheStack.size() <= 0){ return null; } Object reval = cacheStack.pop(); return reval; } }
#提示2:棧有沒有必要還原 重新思考資料的表示,這裡假設存在兩個棧(baseStack和reverseStack),資料儲存在baseStack中,在時間點A,如果需要彈出元素,那麼reverseStack會按照逆序儲存這個時間點A時baseStack中所剩下的元素,之後新增的所有元素都是在reverseStack中元素之後的,在reverseStack元素沒有彈完之前,後續新增的元素不需要壓入到reverseStack,也就是後續新增的元素可以直接堆積在baseStack中,而我們之前還原棧的操作,只是保證在彈出棧的時候,reverseStack中按照順序儲存了所有資料。由此我們得到了想法3,我們宣告兩個棧(baseStack和reverseStack),在彈出時,如果reverseStack沒有元素,那麼就將baseStack的元素以此放入到reverseStack中,然後彈出尾部,在壓入時,資料直接壓入到baseStack中。
//使用語言java
import java.util.*;
//這裡假定訪問方式是單執行緒,如果多執行緒訪問 需要對stack進行保護
public class Solution{
Stack<Object> valueStack;
Stack<Object> cacheStack;
public Solution(){
//這部分宣告不確定,java中可能是這麼呼叫的
valueStack = new ArrayList<>();
cacheStack = new ArrayList<>();
}
//返回值表明壓棧是否成功
public boolean push(Object value){
if(value == null){
return false;
}
//棧溢位的時候會返回異常
try{
valueStack.push(value);
}catch(Exception e){
return false;
}
return true;
}
//假定儲存的元素不會是null
public Object pop(){
if(cacheStack.size() <= 0){
while(valueStack.size() > 0){
cacheStack.push(valueStack.pop());
}
if(cacheStack.size() <= 0){
return null;
}
}
Object reval = cacheStack.pop();
return reval;
}
}
#總結 在操作資料的時候需要進行仔細分析,儘可能避免無意義的操作。