http://www.nowcoder.com/questionTerminal/4c776177d2c04c2494f2555c9fcc1e49
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
题目解读:实现一个支持push, pop, top, min的栈。
这题传统解决就是双栈
或者单栈但每个元素为{值,当前旧值},但这种方案需要双倍空间
本人另辟蹊径,使用转义符思路,在单栈中,通过转义符存入额外控制数据,空间复杂度约等于O(N),每个新的最小值,需要3倍空间进行存储,考虑到一般概率较低所以约等于无。
本方案优点是:数据结构很容易存储进文件,并且是顺序写入。双栈方案是无法顺序写入文件的。
首先该支持Min栈的数据结构由内栈、外栈嵌套而成,
内栈支持插入控制符,每个内栈元素为一个int或两个int。
外栈用1个内栈元素存储非min元素,或3个内栈元素存储新min元素。
我估摸着我可能是全网唯一用这个思路解的
class SpecialStack //支持转义符的栈,支持在一个数组中,插入普通值或控制符,并且读取时可以区分
{
public:
enum { SpecialMask = 0xFFFFFF00, SpecialFlag = 0x88888800 };
void push(int value)
{
raw_values.push_back(value);
if ((value & SpecialMask) == SpecialFlag) //如果值恰好属于特殊字,那么在随后插入一个转义符
raw_values.push_back(SpecialFlag);
}
void push_code(int8_t control)
{
raw_values.push_back(SpecialFlag | (int)control);
}
struct Ret
{
int value;
int8_t control;
int8_t size;
};
Ret peek(int pos) const
{
int v = raw_values[pos];
if ((v & SpecialMask) == SpecialFlag)
{
if ((v & 0xFF) == 0)
return { raw_values[pos - 1], 0, 2};
else
return { 0, int8_t(v & 0xFF), 1};
}
else
return { v, 0, 1};
}
std::pair<int, int8_t> pop()
{
Ret ret = peek(raw_values.size() - 1);
raw_values.resize(raw_values.size() - ret.size);
return { ret.value, ret.control};
}
bool empty() const { return raw_values.empty();}
std::vector<int> raw_values;
};
class Solution {
enum { NewMin = 1};
public:
void push(int value) {
if (value < m_min || values.empty())
{ //对于最小值,插入:旧min,新min,特殊控制符NewMin
values.push(m_min);
values.push(value);
values.push_code(NewMin);
m_min = value;
}
else
{
values.push(value);
}
}
void pop() {
std::pair<int, int8_t> item = values.pop();
if (item.second == NewMin) //弹出时,如果是“特殊控制符NewMin”,再弹出较新min,旧min,并将旧min赋值给当前m_min
{
values.pop();
m_min = values.pop().first;
}
}
int top() const {
auto item = values.peek(values.raw_values.size() - 1);
if (item.control == NewMin) //读取栈顶,如果是特殊控制符NewMin,那么读取前一个值
return values.peek(values.raw_values.size() - 1 - item.size).value;
else
return item.value;
}
int min() const {
return m_min;
}
private:
SpecialStack values;
int m_min = 0;
};