leetcode每日刷题

每日鸡汤:

                🚀专注你的梦想,做自己的英雄。

目录

🏆一、栈的压入、弹出序列

🖊①引入栈实现

🖊②模拟栈实现

🏆二、包含min函数的栈

🖊①倒栈求min

🖊②辅助栈存最小

今天给大家分享两道的题目,因为博主用的是C写的,所以需要调用栈,但是每个代码都放一个显得冗余,所以先把栈放在这里吧。

typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps,STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
bool StackEmpty(ST* ps);
int StackSize(ST* ps);


void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//只能尾插
	if (ps->top==ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newCapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	--ps->top;
}
STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top - 1];
}
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

🏆一、栈的压入、弹出序列

来源: leetcode:栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。

 通过题目我们知道pushedpoped的元素个数一样,而且里面都不会出现重复元素。我们通过栈来解决这道题目。

🖊①引入栈实现

1、我们引入一个栈,设立一个pos指针指向pushed数组,设立一个pt指针指向poped数组。我们先遍历pushed数组,如果pos指针指向的元素和pt指针指向的元素不相同,那么就入栈,然后pos++

2、如果pos指针指向的元素和pt指针指向的元素相同,如果栈不空,我们就要判断栈顶元素和pt指向poped数组元素是否一样,如果一样就pop出栈,pt++,如果不一样就break

3、遍历完pushed数组,我们成功的标志是pt指向的poped数组能否走完!也就等价于栈是否为空,如果不空,就返回false。最后栈空或者pt走完poped数组就返回true

bool validateStackSequences(int* pushed, int pushedSize, int* popped, int poppedSize)
{
    ST st;
    StackInit(&st);
    int pos=0;
    int pt=0;
    while(pos<pushedSize)
    {
        if(pushed[pos]==popped[pt])
        {
            pos++;
            pt++;
            while(!StackEmpty(&st))
            {
                if(StackTop(&st)==popped[pt])
                {
                    StackPop(&st);
                    pt++;
                }
                else
                    break;
            }
        }
        else
        {
            StackPush(&st,pushed[pos]);
            pos++;
        }
    }
    while(!StackEmpty(&st))
    {
        if(StackTop(&st)==popped[pt])
        {
            StackPop(&st);
            pt++;
        }
        else
        {
            return false;
        }
    }
    StackDestory(&st);
    return true;

}

🖊②模拟栈实现

1、上一种方式还有缺陷,我们其实对于不需要返回的空间,比如栈。如果我们不需要调用它的接口,比如这道题,大可不必引入栈,我们模拟一个栈(数组模拟)即可,开一个局部变量就行。

2、上面博主说过,判断为true的条件有两个,一个为pt指针能否成功遍历结束poped数组;一个为栈最后是否为空。上面的引入栈博主使用的是前一种方式,这里博主采用第二种方式,只需遍历一遍pushed数组,然后判断模拟栈是否为空

bool validateStackSequences(int* pushed, int pushedSize, int* popped, int poppedSize)
{
    //top能不能返回到0
    if(pushedSize<1)
        return true;
    int stack[pushedSize];//数组模拟栈
    int top=0;
    for(int i=0,j=0;i<pushedSize;++i)
    {
        stack[top++]=pushed[i];
        while(top>0&&stack[top-1]==popped[j])
        {
            top--;
            j++;
        }
    }
    return top==0;//判断是否为空

}

🏆二、包含min函数的栈

来源:leetcode、包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

🖊①倒栈求min

 这道题目比较有意思的就是求栈中最小数的接口函数。

我们想写求栈中最小数的接口,创建两个栈st1和st2st1用于pushst2只有在求栈中最小数的时候,我们把st1中的数据不断pop,push到st2,然后在这个过程中找到最小的返回;需要注意我们找到最小后还需要把st2的数据再pop,push到st1.

时间复杂度:O(N)

空间复杂度:O(N)

typedef struct 
{
    ST st1;
    ST st2;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() 
{
    MinStack* obj=(MinStack*)malloc(sizeof(MinStack));
    StackInit(&obj->st1);
    StackInit(&obj->st2);
    return obj;
}

void minStackPush(MinStack* obj, int x) 
{
    StackPush(&obj->st1,x);
}

void minStackPop(MinStack* obj) 
{
    if(!StackEmpty(&obj->st1))
    {
        StackPop(&obj->st1);
    }

}

int minStackTop(MinStack* obj) 
{
    if(!StackEmpty(&obj->st1))
    {
        return StackTop(&obj->st1);
    }
    return -1;
}

int minStackMin(MinStack* obj) 
{
    int min=StackTop(&obj->st1);
    while(!StackEmpty(&obj->st1))
    {
        if(StackTop(&obj->st1)<min)
            min=StackTop(&obj->st1);
        StackPush(&obj->st2,StackTop(&obj->st1));
        StackPop(&obj->st1);
    }
     while(!StackEmpty(&obj->st2))
    {
        StackPush(&obj->st1,StackTop(&obj->st2));
        StackPop(&obj->st2);
    }
    return min;
}

void minStackFree(MinStack* obj) 
{
    StackDestory(&obj->st1);
    StackDestory(&obj->st2);
    free(obj);
}

🖊②辅助栈存最小

上面的时间复杂度能否再降呢?是可以的!因为我们上面主要麻烦的就是求最小需要倒栈,如果我们把最小的数都放到st2只要取最小就到st2取。这样时间复杂度为O(1)。可能说的抽象,具体来说:

1、在st2 pushINT_MAX(这有利于我们存放第一个最小的数,也省去判断是否为第一个数),当我们往st1里面push数据时,把它和st2栈顶的元素比较,取最小存放到st2中st2中栈的元素始终比st1多一个INT_MAX(需要注意)。

2、当调用取最小的接口时直接取st2的栈顶元素就是当前st1栈中的最小值,当pop掉一个元素时,st1和st2都需要pop掉栈顶

我再来解释一下:

为什么往st1里面push数据要和st2栈顶比较,并取最小放到st2呢?

 比如这样,当往st1里面依次存-2,-1,0.对应st2里面存放的是-2,-2,-2。这样存会方便我们在取栈中最小时可以直接拿到,最小,因为只要st1中的-2没有被pop掉,栈中最小的始终为-2.而在pop一并pop掉st1和st2的栈顶元素可以保证st2中始终存的是当前st1中最小的元素!!!

typedef struct 
{
    ST st1;
    ST st2;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() 
{
    MinStack* obj=(MinStack*)malloc(sizeof(MinStack));
    StackInit(&obj->st1);
    StackInit(&obj->st2);
    StackPush(&obj->st2,INT_MAX);
    return obj;
}

void minStackPush(MinStack* obj, int x) 
{
    int min=x<StackTop(&obj->st2)?x:StackTop(&obj->st2);
    StackPush(&obj->st1,x);
    StackPush(&obj->st2,min);
}

void minStackPop(MinStack* obj) 
{
    if(!StackEmpty(&obj->st1))
    {
        StackPop(&obj->st2);
        StackPop(&obj->st1);
    }

}

int minStackTop(MinStack* obj) 
{
    if(!StackEmpty(&obj->st1))
    {
        return StackTop(&obj->st1);
    }
    return -1;
}

int minStackMin(MinStack* obj) 
{
    if(!StackEmpty(&obj->st1))//因为我们刚开始存了一个int_max
        return StackTop(&obj->st2);
    return -1;
}

void minStackFree(MinStack* obj) 
{
    StackDestory(&obj->st1);
    StackDestory(&obj->st2);
    free(obj);
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值