棧、佇列面試題總結
阿新 • • 發佈:2019-01-31
倆個棧實現一個佇列
原理圖
注意一定要謹防pop時,容器內沒有元素而引發的錯誤。
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
if (stack1.empty()) {
cout << "佇列中無元素pop失敗" << endl;
exit(1);
}
while (!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
int ret = stack2.top();
stack2.pop();//這個pop挺重要的 ,必須pop這才符合 要不根本該元素一直是佇列的頭元素
while (!stack2.empty())
{
stack1.push(stack2.top());
stack2.pop();
}
return ret;
}
private:
stack<int> stack1;
stack<int> stack2;
};
倆個佇列實現一個棧
class Solution2
{
public:
void push(int node) {
queue1.push(node);
}
int pop() {
if (queue1.empty())
{
cout << "棧為空不能pop" << endl;
exit(2);
}
while (queue1.size()>1)
{
queue2.push(queue1.front());
queue1.pop();
}
int ret = queue1.front();
queue1.pop();
while (!queue2.empty())
{
queue1.push(queue2.front());
queue2.pop();
}
}
private:
queue<int> queue1;
queue<int> queue2;
};
實現一個棧Stack,要求實現Push、Pop、Min的時間複雜度為O(1)
思路
第一種方法定義倆個棧,一個儲存元素一個儲存min值。每次入棧時要比較如果該元素小於等於min棧的棧頂元素時就把該元素也向min棧中入棧,否則只入儲存元素的棧。出棧時如果該元素等於min棧的棧頂元素則倆個棧都要執行pop操作,否則只出儲存元素棧的元素。
第二種方法只是用一個棧。每次入棧時,入倆個元素。先入要入的元素,再入min值。每次入的時候要判斷,如果棧不為空,取棧頂元素。如果該元素小於棧頂元素就該元素入倆次,即從該元素後,該棧的最小元素得到了更新,否則先入該元素,再入原先棧頂的元素。出站棧時倆個倆個出。
方法2:
class Mystack{
public:
Mystack()
{}
void push(T data)
{
if (_s.empty())
{
_s.push(data);
_s.push(data);
}
else{
int min = _s.top();
if (data < min)
{
_s.push(data);
_s.push(data);
}
else{
_s.push(data);
_s.push(min);
}
}
}
void pop()
{
if (_s.empty()){
cout << "棧為空不能pop" << endl;
return;
}
_s.pop();
_s.pop();
}
T min()
{
return _s.top();
}
private:
stack<T> _s;
};
元素出棧、入棧順序的合法性。
舉個栗子:入棧的序列(1,2,3,4,5),出棧序列為(4,5,3,2,1),則合法。入棧的序列(1,2,3,4,5),出棧序列為(4,5,2,3,1),則不合法。也就是給你入棧序列,和出棧序列,看它符不符合一個棧的規律。
思路
因為棧是先進後出。所以出棧序列和入棧序列應該是反向的一組序列。但是有個例外,就是有一個元素先進然後立即出再入下一個元素,這種情況入棧序列和出棧序列就不再是反序的了。這樣的情況影響出棧的序列。所以可以用出棧序列中的第一個元素在入棧序列中找到相應的下標。因為該元素是第一個出棧的元素,在此之前沒有元素出棧。故在此之前進棧的元素嚴格遵循先進後出。而在該元素後入棧的元素可以遵循,也可以不遵循以例外的方式出棧所以是任意順序的。
所以我們只判斷在此之前是嚴格反序的話就是合法,不是嚴格反序就是非法。但是我們得在這樣判斷前,確保倆個數組元素都是相同的,所以我使用了倆段空間儲存這倆個數組的值,然後快排看了下這倆個數組的值是否都完全相同。
int partion(int*arr,int left,int right)
{
int begin = left;
int end = right;
int &key = arr[right];
while (begin < end)
{
while (begin < end&&arr[begin] <= key) ++begin;
while (begin < end&&arr[end] >= key) --end;
if (begin < end)
{
arr[begin] ^= arr[end];
arr[end] ^= arr[begin];
arr[begin] ^= arr[end];
}
}
if (begin != right) {
arr[begin] ^= key;
key ^= arr[begin];
arr[begin] ^= key;
}
return begin;
}
void quicksort(int*arr, int left ,int right)
{
if (left<right)
{
int Base = partion(arr, left, right);
quicksort(arr, left, Base - 1);
quicksort(arr, Base+1, right);
}
}
bool My_sort(int*test1, size_t len, int*test2, size_t len2)
{
std::sort(test1, test1+len);//sort的end為尾隨位置,可以用sort或者自己寫個快排什麼的基本上sort的時
std::sort(test2, test2 + len);//間複雜度是nlog2n
//quicksort(test1,0,len-1);
//quicksort(test2,0,len2-1);
for (size_t idx = 0; idx < len; ++idx)
{
if (test1[idx] != test2[idx]) return false;
}
return true;
}
bool stack_legal(int arr[],int arr_2[],size_t len ,size_t len_2)//這個方法時間複雜度O(nlog2)
{ // 空間複雜度O(n)
assert(arr != NULL&&arr_2 != NULL);
if (len != len_2) return false;
if (len == 0 ||len_2==0) return true;
if (len == 1&&len_2==1)
{
if (arr[0] == arr_2[0]) return true;
else return false;
}
int *test_arr = new int[len];
int *test_arr2 = new int[len_2];
memmove(test_arr, arr, len*sizeof(int));
memmove(test_arr2, arr_2, len_2*sizeof(int));
if (!My_sort(test_arr, len, test_arr2, len_2)) return false;
size_t pos = 0;
while (arr[pos] != arr_2[0])++pos;
size_t idx = 0;
while (pos > 0)
{
if (arr[idx] != arr_2[len_2 - 1 - idx]) return false;
idx++;
--pos;
}
return true;;
}
判斷一棵樹是否是完全二叉樹
思路
我主要使用了層序遍歷的思想,檢測每一層的節點的合法性。
①當出現了只有左子樹節點沒有右子樹的節點,那麼我給一個標記置為True,以後遍歷的每個節點再有子節點的話就不是完全二叉樹。
②如果當該層節點只有右子樹沒有左子樹那麼該樹不是完全二叉樹。
所以根據上面倆條規則來解決這個問題
該圖就是我所描述的幾種情況
程式碼
bool complete_tree(Node*Root)
{
if (Root == NULL) return true;
bool Last = false; //該標記表示是否發現只有一個左子節點的子樹
queue<Node*> qcon;
qcon.push(Root);
Node*pCur = NULL;
while (!qcon.empty())
{
pCur = qcon.front();
if (Last&&(pCur->_PLeft!=NULL||pCur->_PRight!=NULL))
{
return false;
}
if (pCur->_PLeft !=NULL&&pCur->_PRight!=NULL)
{
qcon.push(pCur->_PLeft);
qcon.push(pCur->_PRight);
}
if (pCur->_PLeft != NULL&&pCur->_PRight == NULL)
{
qcon.push(pCur->_PLeft);
Last =true;
}
if (pCur->_PRight != NULL&&pCur->_PLeft == NULL)
{
return false;
}
qcon.pop();
}
return true;
}