▶ 栈和队列的相互表示。发现内置的队列和栈结构都十分高效,相互表示后性能损失都很小。
▶ 第 225 题,用队列实现栈
● 自己的代码,3 ms,单队列实现,入栈 O(1),读取栈顶元素 O(n),出栈 O(n) 。
1 class MyStack 2 { 3 private: 4 queue<int> fakeStack; 5 public: 6 MyStack() 7 { 8 fakeStack = queue<int>(); 9 } 10 void push(int x) 11 { 12 fakeStack.push(x); 13 } 14 int pop() 15 { 16 if (fakeStack.empty()) 17 return -1; 18 int i, output; 19 if (fakeStack.size() == 1) 20 { 21 output = fakeStack.front(); 22 fakeStack.pop(); 23 return output; 24 } 25 for (i = 0;; i++) 26 { 27 output = fakeStack.front(), fakeStack.pop(); 28 if (i == fakeStack.size())// 注意这里 fakeStack.size() 已经发生了改变,不用再 -1 了 29 return output; 30 else 31 fakeStack.push(output); 32 } 33 } 34 int top() 35 { 36 if (fakeStack.empty()) 37 return -1; 38 if (fakeStack.size() == 1) 39 return fakeStack.front(); 40 int i, output; 41 for (i = 0;; i++) 42 { 43 output = fakeStack.front(), fakeStack.pop(); 44 fakeStack.push(output); 45 if (i == fakeStack.size() - 1) 46 return output; 47 } 48 } 49 bool empty() 50 { 51 return fakeStack.empty(); 52 } 53 };
● 大佬的代码,3 ms,队列 queue 具有成员函数 back(),可以用于读取队尾元素。单队列实现,入栈 O(1),读取栈顶元素 O(1),出栈 O(n) 。
1 class MyStack 2 { 3 int curr_size; 4 queue<int> q1, q2; 5 public: 6 MyStack() 7 { 8 curr_size = 0; 9 } 10 void push(int x) 11 { 12 q1.push(x); 13 curr_size++; 14 } 15 int pop() 16 { 17 if (q1.empty()) 18 return -1; 19 while (q1.size() != 1) 20 { 21 q2.push(q1.front()); 22 q1.pop(); 23 } 24 int temp = q1.front(); 25 q1.pop(); 26 curr_size--; 27 queue<int> q = q1; 28 q1 = q2; 29 q2 = q; 30 return temp; 31 } 32 int top() 33 { 34 return q1.back(); 35 } 36 bool empty() 37 { 38 return q1.empty(); 39 } 40 };
● 作弊,就使用内置栈结构,
1 class MyStack 2 { 3 private: 4 stack<int> st; 5 public: 6 MyStack() 7 { 8 st = stack<int>(); 9 } 10 void push(int x) 11 { 12 st.push(x); 13 } 14 int pop() 15 { 16 int output = st.top(); 17 st.pop(); 18 return output; 19 } 20 int top() 21 { 22 return st.top(); 23 } 24 bool empty() 25 { 26 return st.empty(); 27 } 28 };
▶ 第 232 题,用栈实现队列
● 自己的解法,2 ms,双栈实现,分别命名为 fakeQueueIn 和 fakeQueueOut,使用一个标记 store 来记录数据存放于哪个栈里,需要入队的时候把数据倒进 fakeQueueIn 中,需要读取队头或者出队的时候把数据倒入 fakeQueueOut 中,其他情况下不再调整数据的存放位置。
1 class MyQueue 2 { 3 private: 4 stack<int> fakeQueueIn,fakeQueueOut; 5 bool store; // true:数据存储在 fakeQueueIn 中 6 void moveBetweenStack(stack<int>& in, stack<int>& out) 7 { 8 int temp; 9 for (; !in.empty(); out.push(in.top()), in.pop()); 10 } 11 public: 12 MyQueue() 13 { 14 fakeQueueIn = stack<int>(); 15 fakeQueueOut = stack<int>(); 16 store = true; 17 } 18 void push(int x) 19 { 20 if (!store) 21 { 22 moveBetweenStack(fakeQueueOut, fakeQueueIn); 23 store = true; 24 } 25 fakeQueueIn.push(x); 26 } 27 int pop() 28 { 29 int output; 30 if (store) 31 { 32 moveBetweenStack(fakeQueueIn, fakeQueueOut); 33 store = false; 34 } 35 output = fakeQueueOut.top(); 36 fakeQueueOut.pop(); 37 return output; 38 } 39 int peek() 40 { 41 if (store) 42 { 43 moveBetweenStack(fakeQueueIn, fakeQueueOut); 44 store = false; 45 } 46 return fakeQueueOut.top(); 47 } 48 bool empty() 49 { 50 return fakeQueueIn.empty() && fakeQueueOut.empty(); 51 } 52 };
● 最快的解法,2 ms,压根没用 stack,用的 list
1 class MyQueue 2 { 3 public: 4 list<int> data; 5 list<int> buffer; 6 int dataSize; 7 MyQueue() : data{}, buffer{}, dataSize{ 0 } {} 8 void push(int x) { 9 if (dataSize == 0) 10 data.push_back(x); 11 else 12 buffer.push_back(x); 13 ++dataSize; 14 } 15 int pop() 16 { 17 --dataSize; 18 auto res = data.back(); 19 data.pop_back(); 20 if (data.empty()) 21 { 22 while (!buffer.empty()) 23 { 24 data.push_back(buffer.back()); 25 buffer.pop_back(); 26 } 27 } 28 return res; 29 } 30 int peek() 31 { 32 return data.back(); 33 } 34 bool empty() 35 { 36 return dataSize == 0; 37 } 38 };
● 作弊,使用内置的队列结构,3 ms
1 class MyQueue 2 { 3 private: 4 queue<int> qq; 5 public: 6 MyQueue() 7 { 8 qq = queue<int>(); 9 } 10 void push(int x) 11 { 12 qq.push(x); 13 } 14 int pop() 15 { 16 int output = qq.front(); 17 qq.pop(); 18 return output; 19 } 20 int peek() 21 { 22 return qq.front(); 23 } 24 bool empty() 25 { 26 return qq.empty(); 27 } 28 };