【程式設計師面試寶典】棧和佇列相關面試題
1、集合棧
題目描述:
請實現一種資料結構SetOfStacks,由多個棧組成,其中每個棧的大小為size,當前一個棧填滿時,新建一個棧。該資料結構應支援與普通棧相同的push和pop操作。
給定一個操作序列int[][2]ope(C++為vector<vector<int>>),每個操作的第一個數代表操作型別,若為1,則為push操作,後一個數為應push的數字;若為2,則為pop操作,後一個數無意義。請返回一個int[][](C++為vector<vector<int>>),為完成所有操作後的SetOfStacks,順序應為從下到上,預設初始的SetOfStacks為空。保證資料合法。
問題分析:
(1)首先建立一個存放長度達到size的棧vec,用來存放長度達到size的棧(vector<vector<int>>);
(2)在建立一個temp棧用來操作當前要進行操作的資料(vector<int>);
(3)進來之後for迴圈遍歷0~ope.size(),對於壓棧的情況ope[i][0]==1,先判斷棧temp棧中的元素是否達到size個,如果達到就將其先壓入vec棧中,再清空temp棧,執行temp的壓棧操作,否者直接將元素壓入到temp當中;
(4)對於出棧時,首先判斷temp棧是否為空,不為空則直接從temp中丟擲元素,否則讓temp指向vec棧的棧頂,然後讓vec和temp都執行元素出棧動作。
(5)最後如果temp中的元素個數不為空,則將temp壓入到vec當中,返回vec即可
程式碼實現
vector<vector<int> > setOfStacks(vector<vector<int> > ope, int size) {
vector<vector<int> > stack;
vector<int> temp;
for (int i = 0; i<ope.size(); i++){
if (ope[i][0] == 1){
if (temp.size() == size){
stack.push_back(temp);
temp.clear();
temp.push_back(ope[i][1]);
}
else
temp.push_back(ope[i][1]);
}
if (ope[i][0] == 2){
if (temp.size()>0){
temp.pop_back();
}
else{
temp = stack[stack.size() - 1];
temp.pop_back();
stack.pop_back();
}
}
}
if (temp.size() != 0)
stack.push_back(temp);
return stack;
}
2、兩個棧實現佇列
3、雙棧排序
題目描述:
請編寫一個程式,按升序對棧進行排序(即最大元素位於棧頂),要求最多隻能使用一個額外的棧存放臨時資料,但不得將元素複製到別的資料結構中。
給定一個int[]numbers(C++中為vector<int>),其中第一個元素為棧頂,請返回排序後的棧。請注意這是一個棧,意味著排序過程中你只能訪問到第一個元素。
測試樣例:[1,2,3,4,5]返回:[5,4,3,2,1] 問題分析: (1)首先建立一個輔助棧temp,用來存放最終要返回的棧; (2)將numbers的第一個元素push到輔助棧中,其後的過程就和插入排序的思路完全一樣,只不過再此使用vector的介面來進行實現的; (3)因為要對棧進行升序排序,所以若numbers[i]<temp.back()(小於棧頂)時,直接將其插入到後面,否則就需要在temp中遍歷找合適的位置在插入。 (4)所有元素都操作完之後,返回最後排好序的temp棧即可 程式碼實現:vector<int> twoStacksSort(vector<int> numbers) {
vector<int> temp;
int size = numbers.size();
if (size <= 1)
return numbers;
temp.push_back(numbers[0]);
for (int i = 1; i<size; ++i)
{
if (numbers[i] <= temp.back())
temp.push_back(numbers[i]);
else
{
vector<int>::iterator it;
for (it = temp.begin(); it != temp.end(); ++it)
{
if (*it<numbers[i])
break;
}
temp.insert(it, numbers[i]);
}
}
return temp;
}
4、貓狗收容所
題目描述:
有家動物收容所只收留貓和狗,但有特殊的收養規則,收養人有兩種收養方式,第一種為直接收養所有動物中最早進入收容所的,第二種為選擇收養的動物型別(貓或狗),並收養該種動物中最早進入收容所的。
給定一個操作序列int[][2]ope(C++中為vector<vector<int>>)代表所有事件。若第一個元素為1,則代表有動物進入收容所,第二個元素為動物的編號,正數代表狗,負數代表貓;若第一個元素為2,則代表有人收養動物,第二個元素若為0,則採取第一種收養方式,若為1,則指定收養狗,若為-1則指定收養貓。請按順序返回收養的序列。若出現不合法的操作,即沒有可以符合領養要求的動物,則將這次領養操作忽略。
測試樣例:[[1,1],[1,-1],[2,0],[2,-1]]返回:[1,-1] 問題分析: (1)根據題目要求,這道題考查的是我們的邏輯思想,問題的描述已經十分清晰,相應的用程式碼實現出來即可; (2)首先建立兩個vector<int>的變數vec和arr,分別儲存進入收容所中的動物和被領養的動物; (3)接下來就是分情況,若ope[i][0]==1表示有動物進來,只需要不斷的將其push到arr中,否則說明有動物將要被領養,對於要被領養的動物有三種情況。 (4)在arr棧不為空時,ope[i][1]==0,只需依次從arr中push,並將push後的資料從arr中erase掉,對於ope[i][1]==1/-1的情況,方法是一樣的,需要遍歷arr然後找到我們需要的元素,將其push到vec中,然後從arr中在erase掉。 (5)最後所有元素都處理完,只需要返回處理完後的res即可。 程式碼實現:vector<int> asylum(vector<vector<int> > ope)
{
vector<int> res, arr;
int size = ope.size();
if (ope.empty())
return arr;
for (int i = 0; i < size; i++)
{
if (ope[i][0] == 1)
{
res.push_back(ope[i][1]);
}
else if (ope[i][0] == 2)
{
if (!arr.empty())
{
if (ope[i][1] == 0)
{
res.push_back(arr[0]);
arr.erase(arr.begin());
}
else if (ope[i][1] == 1)
{
for (int j = 0; j < res.size(); j++)
{
if (arr[j]>0)
{
res.push_back(arr[j]);
arr.erase(arr.begin() + j);
break;
}
}
}
else if (ope[i][1] == 2)
{
for (int j = 0; j < res.size(); j++)
{
if (arr[j]>0)
{
res.push_back(arr[j]);
arr.erase(arr.begin() + j);
break;
}
}
}
}
}
return res;
}
}