2008-02-14
Google面试题(六)
题目:对现在的Stack(栈)数据结构进行改进,加一个min()功能,使之能在常数,即O(1),时间内给出栈中的最小值。可对push()和pop()函数进行修改,但要求其时间复杂度都只能是O(1)。
分析:要使pop,push,min都是O(1),所以肯定要牺牲点空间
思路:1:在stack的数据结构中加两个个字段,如
typedef struct {
int data[MAX];
int top;
int min;
int second;
}stack;
pop,push的时候都去栈顶元素,所以是O(1)
min的时候取stack的min字段,所以也是O(1)
每次push的时候进行比较,如果当前push的元素比stack->min小,则用当前元素替换stack->min,用原来的min替换second。如果当前push的元素比stack->min大,但比second小,则用当前元素替换stack->second。于是达到了取min的效果,程序如下
int push(stack * s,int x){
ASSERT(s!=NULL);
if(s->top>=MAX)
{
printf("Stack overload!");
return -1;
}
s->data[s->top++]=x;
if(x<s->min)
s->min=x;
return 0;
}
每次pop的时候进行比较,如果pop的元素为min,则用second替换min。于是达到了取min的效果,程序如下
int pop(stack *s,int *x)
{
ASSERT(s!=NULL);
if(s->top<=0)
{
printf("Stack Empty!");
return -1;
}
(*x)=s->data[s->top--];
if(x==s->min) s->min=s->second;
return 0;
}
int min( stack *s,int *x )
{
ASSERT(s!=NULL);
(*x)=s->min;
return 0;
}
思路2:设置辅助栈ass,记录每个状态下的最小值,每次插入时,得到辅助栈当前值,和插入的值比较
如果小则插入到最小值栈的就是它,否则就是原来的最小值,通过这种方式,pop,push,min三个都是
O(1)算法的。
typedef struct {
int data[MAX];
int top;
}stack;
STATIC int push_stack(stack *s,int x)
{
ASSERT((s!=NULL));
if(s->top>=MAX)
{
printf("Stack overload");
return -1;
}
s->data[s->top++]=x;
return 0;
}
STATIC int pop_stack(stack *s,int *x)
{
ASSERT(s!=NULL);
if(s->top<=0)
{
printf("Stack Empty");
return -1;
}
(*x)=s->data[s->top--];
return 0;
}
int push(stack *main,stack *ass,int x)
{
ASSERT((main!=NULL)&&(ass!=NULL));
int temp;
pop_stack(ass,&temp);
push_stack(main,x);
if(x<temp)
{
push_stack(ass,temp);
push_stack(ass,x);
}
else
{
push_stack(ass,temp);
push_stack(ass,temp);
}
return 0;
}
int pop(stack *main,stack *ass,int *x)
{
ASSERT((main!=NULL)&&(ass!=NULL));
int temp;
pop_stack(ass,&temp);
pop_stack(main,x);
return 0;
}
int min(stack *ass,int *x)
{
ASSERT((main!=NULL)&&(ass!=NULL));
pop_stack(ass,x);
push_stack(ass,(*x));
return 0;
}
分析:要使pop,push,min都是O(1),所以肯定要牺牲点空间
思路:1:在stack的数据结构中加两个个字段,如
typedef struct {
int data[MAX];
int top;
int min;
int second;
}stack;
pop,push的时候都去栈顶元素,所以是O(1)
min的时候取stack的min字段,所以也是O(1)
每次push的时候进行比较,如果当前push的元素比stack->min小,则用当前元素替换stack->min,用原来的min替换second。如果当前push的元素比stack->min大,但比second小,则用当前元素替换stack->second。于是达到了取min的效果,程序如下
int push(stack * s,int x){
ASSERT(s!=NULL);
if(s->top>=MAX)
{
printf("Stack overload!");
return -1;
}
s->data[s->top++]=x;
if(x<s->min)
s->min=x;
return 0;
}
每次pop的时候进行比较,如果pop的元素为min,则用second替换min。于是达到了取min的效果,程序如下
int pop(stack *s,int *x)
{
ASSERT(s!=NULL);
if(s->top<=0)
{
printf("Stack Empty!");
return -1;
}
(*x)=s->data[s->top--];
if(x==s->min) s->min=s->second;
return 0;
}
int min( stack *s,int *x )
{
ASSERT(s!=NULL);
(*x)=s->min;
return 0;
}
思路2:设置辅助栈ass,记录每个状态下的最小值,每次插入时,得到辅助栈当前值,和插入的值比较
如果小则插入到最小值栈的就是它,否则就是原来的最小值,通过这种方式,pop,push,min三个都是
O(1)算法的。
typedef struct {
int data[MAX];
int top;
}stack;
STATIC int push_stack(stack *s,int x)
{
ASSERT((s!=NULL));
if(s->top>=MAX)
{
printf("Stack overload");
return -1;
}
s->data[s->top++]=x;
return 0;
}
STATIC int pop_stack(stack *s,int *x)
{
ASSERT(s!=NULL);
if(s->top<=0)
{
printf("Stack Empty");
return -1;
}
(*x)=s->data[s->top--];
return 0;
}
int push(stack *main,stack *ass,int x)
{
ASSERT((main!=NULL)&&(ass!=NULL));
int temp;
pop_stack(ass,&temp);
push_stack(main,x);
if(x<temp)
{
push_stack(ass,temp);
push_stack(ass,x);
}
else
{
push_stack(ass,temp);
push_stack(ass,temp);
}
return 0;
}
int pop(stack *main,stack *ass,int *x)
{
ASSERT((main!=NULL)&&(ass!=NULL));
int temp;
pop_stack(ass,&temp);
pop_stack(main,x);
return 0;
}
int min(stack *ass,int *x)
{
ASSERT((main!=NULL)&&(ass!=NULL));
pop_stack(ass,x);
push_stack(ass,(*x));
return 0;
}
评论
loveofgod
2008-02-18
在push时将每个数包装成一个结点,如果这样的话,当push的点很大时,空间复杂度会很高
loveofgod
2008-02-18
ddbird,那你说pop push min的复杂度多少,嗯对,push没问题,pop的时候会出问题
JohnnyJian
2008-02-16
引用
我认为min() O(1)的做法应该是在push时将每个数包装成一个结点,结点中两个数,一个是要压入的数,另一个记录压入前已经在栈中的的最小值。后面的就容易了,我不说了。
You're right!
ggggqqqqihc
2008-02-15
我认为min() O(1)的做法应该是在push时将每个数包装成一个结点,结点中两个数,一个是要压入的数,另一个记录压入前已经在栈中的的最小值。后面的就容易了,我不说了。
zuroc
2008-02-15
这个好像很简单?
还是我的理解有问题.........
还是我的理解有问题.........
JohnnyJian
2008-02-15
引用
min是O(1) 用堆就可以了,但是要pop push min 都 O(1) 似乎有难度。
RE,我就是这个意思……
ddbird
2008-02-15
min是O(1) 用堆就可以了,但是要pop push min 都 O(1) 似乎有难度。
ddbird
2008-02-15
引用
每次pop的时候进行比较,如果pop的元素为min,则用second替换min。于是达到了取min的效果,程序如下
int pop(stack *s,int *x)
int pop(stack *s,int *x)
连续push 5个数 然后连续pop 3次,second 是什么值???
光用一个second就能起到排序的作用??? 明显不对的!
loveofgod
2008-02-15
请问哪里错了?上面的解答难道不是O(1)吗?
JohnnyJian
2008-02-14
而且我怀疑求min是否有O(1)的算法,因为即使用优先队列,也要O(logN)的复杂度……
JohnnyJian
2008-02-14
这是官方的答案吗?好像都是错的哦……
发表评论
- 浏览: 52725 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
最近加入圈子
链接
最新评论
-
Axis Eclipse plug-in(代 ...
http://apache.justdn.org/ws/axis2/tools/ ...
-- by terryang -
Heritrix使用摘要
刚接手heritrix,试了一试,抓取文件很顺利,可是却发现了一个问题。 用h ...
-- by richiewlq -
Java图像技术
给个示例程序
-- by shenxiaolei -
校内网困局:还能走多久
最近好像上了开放API,具体没怎么看,就本人来看,开放API,暂时会加大校内的投 ...
-- by xiebiao110 -
Java解析JSON
如果要用org.json应该怎么解析?
-- by qiancaoduwu






评论排行榜