这学期大三了,身边的同学都在准备找实习了,就业压力挺大的说,最近为了准备求职的笔试,很长时间都没有写博客了。最近都在学习C++和数据结构,现在接触算法,以前算法课堂没有好好上,只是把实验题做了就一了百了,没有大的提升,所以现在想在准备笔试的时候把算法好好的补一补,于是在这里记录自己的学习过程。
今天学习了一个挺有趣的算法,是微软面试100题中的题目。题目如下:
设计包含min函数的栈。定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min,push,以及pop的时间复杂度都是O(1)。
首先描述一下这个算法的要求:
如果向栈插入数据:2 6 4 1 5,每次插入数据之后,调用min函数可以获得此栈中的最小值。而且要求min,push,以及pop的时间复杂度都是常数级别。
通过这样,可以选择使用辅助栈的方法实现,辅助栈保存最小值的位置,用空间消耗换取高效的时间复制度。
现在设计一个数据结构,使用两个向量保存数据,向量1保存栈的数据,向量2保存当前序列1中最小值的位置。
类的设计如下:
template <class T>
class StackMin
{
public:
void Push(T);
void Pop();
void display(ostream &out) const;
vector<T> datas;
vector<size_t> minStack;
T min() const;
};
比如,插入序列(push)2 6 4 1 5的过程如下:
A B
5 3 /此时最小值还是1
1 3 //此时最小值发生变化,1是最小值,所以把1的下标3压入向量2中
4 0 //此时2依然是最小值
6 0 //此时2依然是最小值
2 0 //此时只有一个元素,所以最小值就是它自己在向量1中的位置0
实现的伪代码
push data ==> A
if data is minimun or B is empty
then push data's subscript in A ==> B
C++实现
template <class T>
void StackMin<T>::Push(T data)
{
datas.push_back(data);
if(minStack.empty() || data < datas[minStack.back()])
{
minStack.push_back(datas.size()-1);
}
}
pop的过程如下:
A B
5 不发生变化,因为5不是最小值
1 把1的下标--3弹出,因为最小值被弹出,A中的最小值发生了改变
4 不发生变化,因为4不是最小值
6 不发生变化,因为6不是最小值
2 把2的下标--0弹出,因为此时2是最小值
if A is empty
then do nothing
if A.topValue == A[B.topvalue]
then pop one value from B
pop one value from A
C++实现
template <class T>
void StackMin<T>::Pop()
{
assert(!datas.empty());
if(datas.back() == datas[minStack.back()])
{
minStack.pop_back();
}
datas.pop_back();
}
min函数的实现就是取出向量B的栈顶元素作为向量A的下标,访问向量A即为当前的最小值
if A is empty or B is empty
then do nothing
return A[B.topValue]
C++实现
template <class T>
T StackMin<T>::min() const
{
assert(!datas.empty() && !minStack.empty());
return datas[minStack.back()];
}
以上就是整个操作过程的实现的分析和伪代码。
本次学习算法的体会是,算法很重要,也很有趣,做算法之前应当先分析好再开始实现代码,已节省时间和更深地体会算法的过程。在这里写下自己学习算法的过程,本人还是一位小菜逼,希望各位多多指教!