我在接受采访时被问到这个问题:
设计一个数据结构,允许所有这些操作保持不变,O(1)
,时间:
[1, 22, 44, 56, 99, 98, 56]
的范围是98
。我使用带有两个变量max
和min
的自定义堆栈设计了这个,但是在弹出min或max元素后这不起作用。
我尝试了什么:
我使用了一个带有两个额外变量max和min的堆栈:
DS
{
top, //Top of the Stack
min, //Min till now
max //Max till now
}
Push(DS, elem)
Push_Stack(DS.top, elem)
if elem < DS.min
DS.min = elem
if elem > DS.max
DS.max = elem
Range(DS)
return DS.max - DS.min
Pop(DS)
x = Pop_Stack(DS.top)
if (x == DS.min)
DS.min = Find_New_Min(DS.top) //This takes linear time using this approach
if (x == DS.max)
DS.max = Find_New_Max(DS.top)
答案 0 :(得分:5)
实现一个包含范围函数的“堆栈”,并在内部使用三个堆栈。
第一个内部堆栈将代表被推送和弹出的“真实”堆栈。
如果新元素大于或等于其上的内容,则仅推送第二个内部堆栈。
如果新元素小于或等于其上的元素,则仅推送第三个内部堆栈。
现在,无论何时需要计算范围,只需查看第二个和第三个堆栈的顶部并进行一些简单的数学运算。
每当一个元素需要从'真正的'堆栈中弹出时,检查该元素是否也位于其他两个堆栈的顶部,如果是,则将其从这些堆栈中弹出。
由于你必须以相反的顺序从主堆栈中弹出项目,所以你不会错过其他两个堆栈中的任何东西......这意味着第二个和第三个内部堆栈的顶部将始终是最大和最小。
答案 1 :(得分:1)
这与Bryon Lo的答案类似,但在他发布我commented same
之前维持3个筹码
休息是不言自明的
push(T value)
{
if (value <= min())
{
s2.push(value);
}
if(value >= max())
{
s3.push(value);
}
s1.push(value);
}
T pop()
{
T value = s1.pop();
if (value == min())
{
s2.pop();
}
return value;
}
T min()
{
if (s2.isEmpty())
{
return MAX_VALUE;
}
else {
return s2.peek();
}
}
T max()
{
if (s3.isEmpty())
{
return MIN_VALUE;
}
else
{
return s3.peek();
}
}