面试的时候,面试官让设计一个栈,要求有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 }