导航

    面试的时候,面试官让设计一个栈,要求有Push、Pop和获取最大最小值的操作,并且所有的操作都能够在O(1)的时间复杂度完成。

    当时真没啥思路,后来在网上查了一下,恍然大悟,只能恨自己见识短浅、思路不够开阔,特地写个总结来学习一下。

    其实思路挺简单,只是没有接触过的话,一时反应不过来。我们将栈中的每个元素都增加两个索引号,一个最大元素索引一个最小元素索引,这样我们可以根据栈只能访问栈顶元素的特性,在每个元素入栈时记下当前栈里面的最大最小元素的索引号,这样我们通过对栈顶元素的访问,就可以随时拿到当前栈中最大最小元素了,这是典型的空间换时间思想。

    示例代码如下:

  1 #include<iostream>
  2 
  3 using namespace std;
  4 
  5 typedef int ElemType;
  6 
  7 class MinMaxStack
  8 {
  9 public:
 10     MinMaxStack() : m_size(0) { }
 11     ~MinMaxStack() { }
 12     
 13     bool Push(const ElemType& e)
 14     {
 15         if (m_size >= STACK_MAXIMUM) {
 16             return false;
 17         }
 18 
 19         // 如果是第一个元素,则将最大最小元素索引都设置为0
 20         if (m_size == 0) {
 21             m_stack[m_size].elem = e;
 22             m_stack[m_size].maxIndex = 0;
 23             m_stack[m_size].minIndex = 0;
 24         }
 25         else {
 26             int minIndex = m_stack[m_size - 1].minIndex;
 27             int maxIndex = m_stack[m_size - 1].maxIndex;
 28             m_stack[m_size].elem = e;
 29 
 30             // 设置插入元素的最大元素索引:
 31             // 若插入元素比当前最大元素大,则将其最大元素索引设置为它自己的索引
 32             // 否则,设置为前一个元素的最大元素索引
 33             if (e > m_stack[maxIndex].elem) {
 34                 m_stack[m_size].maxIndex = m_size;
 35             }
 36             else {
 37                 m_stack[m_size].maxIndex = maxIndex;
 38             }
 39 
 40             // 设置插入元素的最小元素索引
 41             // 若插入元素比当前最小元素小,则将其最小元素索引设置为它自己的索引
 42             // 否则,设置为前一个元素的最小元素索引
 43             if (e < m_stack[minIndex].elem) {
 44                 m_stack[m_size].minIndex = m_size;
 45             }
 46             else {
 47                 m_stack[m_size].minIndex = minIndex;
 48             }
 49         }
 50         m_size++;
 51 
 52         return true;
 53     }
 54 
 55     bool Pop(ElemType& e)
 56     {
 57         if (m_size == 0) {
 58             return false;
 59         }
 60         
 61         m_size--;
 62         e = m_stack[m_size].elem;
 63 
 64         return true;
 65     }
 66 
 67     int Size()
 68     {
 69         return m_size;
 70     }
 71 
 72     const ElemType& Min()
 73     {
 74         if (m_size == 0) {
 75             return INIT_VALUE;
 76         }
 77 
 78         int minIndex = m_stack[m_size - 1].minIndex;
 79         return m_stack[minIndex].elem;
 80     }
 81 
 82     const ElemType& Max()
 83     {
 84         if (m_size == 0) {
 85             return INIT_VALUE;
 86         }
 87 
 88         int maxIndex = m_stack[m_size - 1].maxIndex;
 89         return m_stack[maxIndex].elem;
 90     }
 91 
 92 private:
 93     struct StackNode
 94     {
 95         StackNode(const ElemType& e = INIT_VALUE, int min = 0, int max = 0)
 96             : elem(e), minIndex(min), maxIndex(max)
 97         {
 98         }
 99 
100         ElemType elem;
101         int minIndex;
102         int maxIndex;
103     };
104 
105     static const int STACK_MAXIMUM = 100;
106     static const ElemType INIT_VALUE;
107 
108     StackNode m_stack[STACK_MAXIMUM];
109     int m_size;
110 };
111 
112 const ElemType MinMaxStack::INIT_VALUE = -999;
113 
114 // 测试代码
115 int main()
116 {
117     MinMaxStack stack;
118     stack.Push(5);
119     stack.Push(3);
120     stack.Push(2);
121     stack.Push(6);
122     stack.Push(1);
123     stack.Push(7);
124     stack.Push(4);
125     stack.Push(9);
126 
127     cout << "size = " << stack.Size() << endl;
128     cout << "min = " << stack.Min() << endl;
129     cout << "max = " << stack.Max() << endl;
130     cout << "------------------------------------" << endl;
131     
132     ElemType e;
133     stack.Pop(e);
134     cout << "size = " << stack.Size() << endl;
135     cout << "min = " << stack.Min() << endl;
136     cout << "max = " << stack.Max() << endl;
137     cout << "pop = " << e << endl;
138     cout << "------------------------------------" << endl;
139 
140     stack.Pop(e);
141     cout << "size = " << stack.Size() << endl;
142     cout << "min = " << stack.Min() << endl;
143     cout << "max = " << stack.Max() << endl;
144     cout << "pop = " << e << endl;
145     cout << "------------------------------------" << endl;
146 
147     stack.Pop(e);
148     cout << "size = " << stack.Size() << endl;
149     cout << "min = " << stack.Min() << endl;
150     cout << "max = " << stack.Max() << endl;
151     cout << "pop = " << e << endl;
152     cout << "------------------------------------" << endl;
153 
154     stack.Pop(e);
155     cout << "size = " << stack.Size() << endl;
156     cout << "min = " << stack.Min() << endl;
157     cout << "max = " << stack.Max() << endl;
158     cout << "pop = " << e << endl;
159     cout << "------------------------------------" << endl;
160 
161     stack.Pop(e);
162     cout << "size = " << stack.Size() << endl;
163     cout << "min = " << stack.Min() << endl;
164     cout << "max = " << stack.Max() << endl;
165     cout << "pop = " << e << endl;
166     cout << "------------------------------------" << endl;
167 
168     return 0;
169 }