由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
JobHunting版 - 程序员面试题精选100题(02)-设计包含min函数的栈[数据结构]
相关主题
程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表FLGT某家,电面LC高频题顺利做出,还是挂了
两个面试题中国高考是检验人聪明的工具, 可惜码公的刷题不是
关于Inplace排序栈元素的解法?找2个sorted array中的第K小的元素,有O(lgn)方法吗?
Leetcode Min Stack问题找最大、第二大元素问题
问道indeed面试算法题这是什么数据结构?
教你进Google [3]问一下LA和湾区工作比较
面试题关于遍历二叉树的复杂度
怎么处理面试官一点都不愿意交流的情况?发个面经
相关话题的讨论汇总
话题: min话题: 最小值话题: push话题: pop话题: 函数
进入JobHunting版参与讨论
1 (共1页)
d**s
发帖数: 98
1
http://zhedahht.blog.163.com/blog/static/2541117420071289522817
程序员面试题精选100题(02)-设计包含min函数的栈[数据结构]
2007-02-28 21:52:28| 分类: 栈 | 标签:编程 就业 找工作 |字号大中小 订阅
题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数
min、push以及pop的时间复杂度都是O(1)。
分析:这是去年google的一道面试题。
我看到这道题目时,第一反应就是每次push一个新元素时,将栈里所有逆序元素排序。
这样栈顶元素将是最小元素。但由于不能保证最后push进栈的元素最先出栈,这种思路
设计的数据结构已经不是一个栈了。
在栈里添加一个成员变量存放最小元素(或最小元素的位置)。每次push一个新元素进
栈的时候,如果该元素比当前的最小元素还要小,则更新最小元素。
乍一看这样思路挺好的。但仔细一想,该思路存在一个重要的问题:如果当前最小元素
被pop出去,如何才能得到下一个最小元素?
因此仅仅只添加一个成员变量存放最小元素(或最小元素的位置)是不够的。我们需要
一个辅助栈。每次push一个新元素的时候,同时将最小元素(或最小元素的位置。考虑
到栈元素的类型可能是复杂的数据结构,用最小元素的位置将能减少空间消耗)push到
辅助栈中;每次pop一个元素出栈的时候,同时pop辅助栈。
参考代码:
#include
#include
template class CStackWithMin
{
public:
CStackWithMin(void) {}
virtual ~CStackWithMin(void) {}
T& top(void);
const T& top(void) const;
void push(const T& value);
void pop(void);
const T& min(void) const;
private:
T> m_data; // the elements of stack
size_t> m_minIndex; // the indices of minimum elements
};
// get the last element of mutable stack
template T& CStackWithMin::top()
{
return m_data.back();
}
// get the last element of non-mutable stack
template const T& CStackWithMin::top() const
{
return m_data.back();
}
// insert an elment at the end of stack
template void CStackWithMin::push(const T& value)
{
// append the data into the end of m_data
m_data.push_back(value);
// set the index of minimum elment in m_data at the end of m_minIndex
if(m_minIndex.size() == 0)
m_minIndex.push_back(0);
else
{
if(value < m_data[m_minIndex.back()])
m_minIndex.push_back(m_data.size() - 1);
else
m_minIndex.push_back(m_minIndex.back());
}
}
// erease the element at the end of stack
template void CStackWithMin::pop()
{
// pop m_data
m_data.pop_back();
// pop m_minIndex
m_minIndex.pop_back();
}
// get the minimum element of stack
template const T& CStackWithMin::min() const
{
assert(m_data.size() > 0);
assert(m_minIndex.size() > 0);
return m_data[m_minIndex.back()];
}
举个例子演示上述代码的运行过程:
步骤 数据栈 辅助栈 最小值
1.push 3 3 0 3
2.push 4 3,4 0,0 3
3.push 2 3,4,2 0,0,2 2
4.push 1 3,4,2,1 0,0,2,3 1
5.pop 3,4,2 0,0,2 2
6.pop 3,4 0,0 3
7.push 0 3,4,0 0,0,2 0
讨论:如果思路正确,编写上述代码不是一件很难的事情。但如果能注意一些细节无疑
能在面试中加分。比如我在上面的代码中做了如下的工作:
· 用模板类实现。如果别人的元素类型只是int类型,模板将能给面试官带来
好印象;
· 两个版本的top函数。在很多类中,都需要提供const和非const版本的成员
访问函数;
· min函数中assert。把代码写的尽量安全是每个软件公司对程序员的要求;
· 添加一些注释。注释既能提高代码的可读性,又能增加代码量,何乐而不
为?
总之,在面试时如果时间允许,尽量把代码写的漂亮一些。说不定代码中的几个小亮点
就能让自己轻松拿到心仪的Offer。
本文已经收录到《剑指Offer——名企面试官精讲典型编程题》一书中,有改动,书中
的分析讲解更加详细。欢迎关注。我在英文博客上提供了一种不需要辅助栈的算法。感
兴趣的读者请参考http://codercareer.blogspot.com/2011/09/no-02-stack-with-function-min.html
博主何海涛对本博客文章享有版权。网络转载请注明出处http://zhedahht.blog.163.com/。整理出版物请和作者联系。对解题思路有任何建议,欢迎在评论中告知,或者加我微博http://weibo.com/zhedahht或者http://t.163.com/zhedahht与我讨论。谢谢。
d**s
发帖数: 98
2
非常规的解法:
http://blog.csdn.net/anchor89/article/details/6055412
经典面试题:设计包含min函数的栈,O(1)空间实现方法
分类: 数据结构和算法 2010-12-04 22:20 2102人阅读 评论(10) 收藏 举报
题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数
min、push以及pop的时间复杂度都是O(1)。
注:这是06年一道Google的面试题.
先来说个常规解和他的一个优化,常规解的时间复杂度符合要求,但需要线性的额外空间.
常规解(参考 http://zhedahht.blog.163.com/blog/static/25411174200712895228171/):
除了题目要求的栈之外新开一个栈,用来记录最小值,每当在原栈中push数据后,与最小
值栈中的栈顶元素比较,如果新值较小,则在最小值栈中push新值;否则再次push栈顶元
素.
pop的时候,只要将最小值栈也pop一下就行了.
这样,min函数只需要返回最小值栈的栈顶元素即可.
常规解空间上的一个优化:
一般说来,最小值不会每次都需要更新,因此最小值栈里面会有很多重复元素.因此一个
简单的优化就是在新值只当<=原最小值时才pushIntoMin,注意这个==的条件是不可少的
,这是为了防止在pop的时候错误的pop最小值.pop的是, 当待pop值==最小值时
popMinStack, 其他时候不对最小值栈进行pop
下面说一种具有常数空间复杂度的方法:
在这个方法里,只需要额外开一个用于存放当前最小值的变量min即可.因此下面提到的
push和pop操作都是对于题目中要求的栈来操作的,当然,这也是这个算法里唯一的栈.
设push的参数为v_push,pop的返回值为v_pop.
先说下整体思路:因为栈中所有元素的值都不会小于当其为栈顶元素时min函数的值,所
以在栈中其实只需要保存某元素比相应最小值大出来的值就可以了.而对于最小值更新
的位置,栈元素肯定为0,因此可以利用这个位置来保存更多的信息,在这里是更新后前两
个最小值的差值,而这个值肯定是非正的.
根据上面的思路,push函数按照如下策略进行:
首先push (v_push-min),如果v_push < min,更新min为v_push.
相应的,pop函数按照如下策略进行(称栈顶元素为top):
如果top >= 0, v_pop = min+top, 如果top < 0, v_pop = min,然后更新min为min-top.
显然,对于min函数来说,只需要返回min空间的内容即可.
与张霄学长交流后,学长也讲了一个类似的方法:
push时候 如果 v_push >= min, v_push 直接入栈, 如果 v_push < min, 那么入栈的
是 2 * v_push - min, 然后 min = v_push. 出栈时, 如果栈顶的top >= min 直接出
,如果 top < min 则出现异常,将min作为pop的返回值,另外需要还原前一个最小值
,方法是 min = 2 * min - top
其实这两种方法在思路上是完全一样的,只是学长提供的方法里,栈中所有元素都比我的
方法里大v_push.不过,这种变化直接带来的好处是,在不更新最小值的情况下,压栈值和
出栈值都不需要额外的计算,在高级语言层面上,一次加减法运算比单纯的赋值至少多了
一次访存操作和一次alu的运算,这样估计来我的方法耗时会是学长方法的2倍左右,虽然
时间复杂度都是一样的.

订阅

【在 d**s 的大作中提到】
: http://zhedahht.blog.163.com/blog/static/2541117420071289522817
: 程序员面试题精选100题(02)-设计包含min函数的栈[数据结构]
: 2007-02-28 21:52:28| 分类: 栈 | 标签:编程 就业 找工作 |字号大中小 订阅
: 题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数
: min、push以及pop的时间复杂度都是O(1)。
: 分析:这是去年google的一道面试题。
: 我看到这道题目时,第一反应就是每次push一个新元素时,将栈里所有逆序元素排序。
: 这样栈顶元素将是最小元素。但由于不能保证最后push进栈的元素最先出栈,这种思路
: 设计的数据结构已经不是一个栈了。
: 在栈里添加一个成员变量存放最小元素(或最小元素的位置)。每次push一个新元素进

1 (共1页)
进入JobHunting版参与讨论
相关主题
发个面经问道indeed面试算法题
A家最近的设计题教你进Google [3]
问个面试题目面试题
问个关于set的题怎么处理面试官一点都不愿意交流的情况?
程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表FLGT某家,电面LC高频题顺利做出,还是挂了
两个面试题中国高考是检验人聪明的工具, 可惜码公的刷题不是
关于Inplace排序栈元素的解法?找2个sorted array中的第K小的元素,有O(lgn)方法吗?
Leetcode Min Stack问题找最大、第二大元素问题
相关话题的讨论汇总
话题: min话题: 最小值话题: push话题: pop话题: 函数