问题描述,实现一个栈,要求push,pop,min(返回最小值的操作)的时间复杂度为O(1)。
思路1:模拟实现一个栈,在成员变量中一个int类型的变量,用来保存最小值,每当push一个数据,都将push的数据与变量中保存的数据进行对比,如果,push数据小于保存的值,那么就将最小值更新为push进来的数据,反之,则不用替换。假想push(2,3,4,1),那么最后保存的最小值是1,时间复杂度也将会是1,因为操作的次数为常数。但是这种思路是错误的,原因在于,pop数据的时候不会更新最小数据,试想上面的例子,将1 pop出去,那么最小的值就变成了2,可是变量里面还是1,没有更新数据导致程序逻辑错误。
思路2:使用两个栈结构来维护两段内存,一个存储正常push的数据,一个存储最小数据。
那么,这么样就不用为更新最小数据而头疼。
1.定义一个类似栈结构的结构体(当然可以实现为模板将会更加方便)
typedef struct _stack { _stack() :_capacity(5) , _size(0) { _array = new int[5]; } ~_stack() { if (_array) { delete[] _array; _array = NULL; } } int* _array; //存储数据的数组 int _capacity; //容量 int _size; //有效数据 }stack;
2.定义一个类来管理两个结构体的对象
class Stack { public: Stack() :s() , minstack() {} bool pop(int* e) { if (s._size == 0) { return false; } int value = s._array[--s._size]; if (value == minstack._array[minstack._size - 1]) { --minstack._size; } *e = value; return true; } bool push(int value) { if (s._size >= s._capacity) { s._capacity = s._capacity * 2; int* tmp = new int[s._capacity]; int* cmp = new int[s._capacity]; for (int i = 0; i < s._size; i++) { tmp[i] = s._array[i]; } for (int i = 0; i < minstack._size; i++) { cmp[i] = minstack._array[i]; } delete[] s._array; delete[] minstack._array; s._array = tmp; minstack._array = cmp; } /* if (s._size == s._capacity) { return false; } */ if (minstack._size == 0 || value <= minstack._array[minstack._size - 1]) { minstack._array[minstack._size++] = value; } s._array[s._size++] = value; return true; } bool min(int* pMin) { if (minstack._size == 0) { return false; } *pMin = minstack._array[minstack._size - 1]; return true; } private: stack s; //用来维护正常数据栈 stack minstack; //用来维护最小数据栈 };
3.push函数实现细节
1).s维护的内存,正常压入数据
2).minstack维护的内存,当minstack._size == 0的时候,压入第一个数据,当要压入第二个数据的时候,需要和minstack维护的栈的top数据进行比较,如果压入数据比当前minstack的top数据小,则压入,否则则不压入。
4.pop函数的实现细节
1).首先由push会知道 s.top() >= minstack.top() 是恒成立的。
2).取到即将要被s栈即将要被pop出去的数据,用数据与minstack栈顶元素作比较,如果s.top() > minstack.top() 则只将s栈的栈顶元素pop出去而不用pop minstack的栈顶元素。如果s.top() == minstack.top(),则将s栈和minstack栈 的元素统统pop出去。
5.min实现细节
1).返回minstack的栈顶元素
6.测试用例
void Test() { Stack s; s.push(9); s.push(7); s.push(10); s.push(5); s.push(8); s.push(1); cout << "压入序列9 7 10 5 8 1" << endl; cout << "弹出序列" << endl; int value; while (s.pop(&value)) { cout << "pop " << value << "\t"; if (s.min(&value)) cout << "min value : " << value << endl; else cout << "there is no min value!" << endl; } }
以上就是本人在做本道面试题的一些想法,分享给大家。