问题:
假设有这样一个拥有3个操作的队列:
1. EnQueue(v): 将v加入队列中
2. DeQueue(): 使队列中的队首元素删除并返回此元素
3. MaxElement: 返回队列中的最大元素
设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低。
说一下我对解法三的理解,代码就不再赘述了
stackItem[]:栈数组,Link2NextMaxItem[]:保存最大值的位置值的数组,maxStackIndex:初始化Link2NextMaxItem[]过程中,保存最大值位置信息
例如要操作的数据为PUSH(2,6,4,8,9),那么先处理2,push(2),
2 6 4 8 9
↑
x=2,
stacktop=0,stackItem[0]=2,Max()<0,(因为maxStackIndex初始值为-1,所以返回-INF),
x>Max(){Link2NextMaxItem[0]=-1,
maxStackIndex=0;}
stackItem:
2 |
Link2NextMaxItem:
-1 |
下一个值
2 6 4 8 9
↑
x=6,
stacktop=1,stackItem[1]=6,Max()=2,(因为maxStackIndex=0,所以返回stackItem[0]),
x>Max(){Link2NextMaxItem[1]=0,
maxStackIndex=1;}
stackItem:
6 |
2 |
Link2NextMaxItem:
0 |
-1 |
下一个值
2 6 4 8 9
↑
x=4,
stacktop=2,stackItem[2]=4,Max()=6,(因为maxStackIndex=1,所以返回stackItem[1]),
x<Max()Link2NextMaxItem[2]=-1,
maxStackIndex不变,还是1;
stackItem:
4 |
6 |
2 |
Link2NextMaxItem:
-1 |
0 |
-1 |
下一个值
2 6 4 8 9
↑
x=8,
stacktop=3,stackItem[3]=8,Max()=6,(因为maxStackIndex=1,所以返回stackItem[1]),
x>Max(){Link2NextMaxItem[3]=1,
maxStackIndex=3;}
stackItem:
8 |
4 |
6 |
2 |
Link2NextMaxItem:
1 |
-1 |
0 |
-1 |
下一个值
2 6 4 8 9
↑
x=9,
stacktop=4,stackItem[4]=8,Max()=8,(因为maxStackIndex=3,所以返回stackItem[3]),
x>Max(){Link2NextMaxItem[4]=3,
maxStackIndex=4;}
stackItem:
9 |
8 |
4 |
6 |
2 |
Link2NextMaxItem:
3 |
1 |
-1 |
0 |
-1 |
此时maxStackIndex=4
所以,pop操作的时候,先弹出stackItem栈顶元素,9,
因为stacktop=4 等于 maxStackIndex=4,是当前最大值
然后maxStackIndex=Link2NextMaxItem[stacktop=4],根据上图maxStackIndex=3,
stacktop--;
下一次pop,弹出stackItem栈顶元素,8,
因为stacktop=3等于 maxStackIndex=3,是当前最大值
然后maxStackIndex=Link2NextMaxItem[stacktop=3],根据上图maxStackIndex=1,
stacktop--;
下一次pop,弹出stackItem栈顶元素,4,(无论是否是最大值都弹出栈顶元素了)
因为stacktop=2不等于 maxStackIndex=1,所以不是当前最大值
maxStackIndex仍然是1
stacktop--;
下一次pop,弹出stackItem栈顶元素,6,
因为stacktop=1等于 maxStackIndex=1,是当前最大值
然后maxStackIndex=Link2NextMaxItem[stacktop=1],根据上图maxStackIndex=0,
stacktop--;
最后弹出栈底元素,1
所以最大值的顺序是9,8,6,2。
在弹出8以后,弹出4后才能弹出6,所以,尽管4大于2,但是在这种栈的存储方式比较下,无法体现4。