栈和队列面试题

面试题1:实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间复杂度为O(1)

解题思路:我们可以利用一个辅助栈(MinStack),用来存储最小值,在最开始的情况下两个栈同时入,当继续入栈时判断该元素是否小于或等于上一个入栈元素,若小于或等于则同时入两个栈,否则只入Stack,当出栈时用MinStack的栈顶元素和Stack栈顶元素比较,若相等则两个栈同时出栈,最后Stack的最小值就为MinStack的栈顶元素

MinStackNum.h

#pragma once
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include "Stack.h"

typedef  int DataType;

typedef struct Stack
{
	DataType  *_a;
	int _top;
	int _capacity;
}Stack;

typedef struct StackMin
{
	Stack s1;
	Stack s2;
}StackMin;
void StackInit(Stack *p);
void StackDestroy(Stack *p);
void StackPush(Stack *p, DataType x);
void StackPop(Stack *p);
DataType StackTop(Stack *p);
int StackEmpty(Stack *p);
int StackSize(Stack *p);

void StackMinInit(StackMin *ps);
void StackMinDestroy(StackMin *ps);
void StackMinPush(StackMin *ps,DataType x);
void StackMinPop(StackMin *ps);
int StackMinNum(StackMin *ps);

MinStackNum.c

#include "StackM.h"
#include "Stack.h"
void StackMinInit(StackMin *ps)
{
	StackInit(&ps->s1);
	StackInit(&ps->s2);
}
void StackMinDestroy(StackMin *ps)
{
	assert(ps);
	StackDestroy(&ps->s1);
	StackDestroy(&ps->s2);
}
void StackMinPush(StackMin *ps,DataType x)
{
	assert(ps);
	StackPush(&ps->s1, x);

	if (StackSize(&ps->s1) == 1)
	{
		StackPush(&ps->s2, StackTop(&ps->s1));
	}
	else
	{
		if (StackTop(&ps->s1) <= StackTop(&ps->s2))
			StackPush(&ps->s2, StackTop(&ps->s1));
	}
}
void StackMinPop(StackMin *ps)
{
	assert(ps);
	if (StackTop(&ps->s1) >= StackTop(&ps->s2))
	{
		StackPop(&ps->s1);
		StackPop(&ps->s2);
	}
	else
		StackPop(&ps->s1);
}
DataType StackMinNum(StackMin *ps)
{
	assert(ps);
	return StackTop(&ps->s2);
}

test.c

#include "Stack.h"
#include "StackM.h"
int main()
{
	StackMin ps;
	StackMinInit(&ps);
	StackMinPush(&ps, 5);
	StackMinPush(&ps, 4);
	StackMinPush(&ps, 2);
	StackMinPush(&ps, 3);
	StackMinPush(&ps, 1);
	StackMinPop(&ps);
	printf("栈的最小值为: %d\n", StackMinNum(&ps););
	StackMinDestroy(&ps);
	system("pause");
	return 0;
}

使用两个栈实现一个队列

解题思路:利用栈的先入后出特性,使用两个栈,一个栈s1负责入,一个栈s2负责出,这样s2的Top就相当于队列中的Front

QueueByTwoStack.h

#pragma once
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <stdlib.h>
typedef int DataType;

typedef struct Stack
{
	DataType* _a;
	int _top;		// 栈顶
	int _capacity;          // 容量 
}Stack;

// 两个栈实现一个队列
typedef struct QueueByTwoStack
{
	Stack s1;
	Stack s2;
}QueueByTwoStack;

void QueueInit(QueueByTwoStack* pq);
void QueueDestory(QueueByTwoStack* pq);
void QueuePush(QueueByTwoStack* pq, DataType x);
void QueuePop(QueueByTwoStack* pq);
DataType QueueFront(QueueByTwoStack* pq);
int QueueEmpty(QueueByTwoStack* pq);
int QueueSize(QueueByTwoStack* pq);
void TestQueue();

QueueByTwoStack.c

#include"QueueByTwoStack.h"
void QueueInit(QueueByTwoStack * pq)
{
	assert(pq);
	StackInit(&pq->s1);
	StackInit(&pq->s2);
}
void QueueDestory(QueueByTwoStack* pq)
{
	assert(pq);
	StackDestory(&pq->s1);
	StackDestory(&pq->s2);
}
void QueuePush(QueueByTwoStack* pq, DataType x)
{
	assert(pq);
	StackPush(&pq->s1, x);
}

void QueuePop(QueueByTwoStack* pq)
{
	//判断s2是否为空
	if (StackEmpty(&pq->s2))
	{
		StackPop(&pq->s2);
	}
	//若s1不为空则将s1的Top入到s2中,相当于将s1中的数据又倒了回来
	//这样就能保证s2的Top数据相当于队头数据
	else if (StackEmpty(&pq->s1))
	{
		while (StackEmpty(&pq->s1))
		{
			StackPush(&pq->s2, StackTop(&pq->s1));
			StackPop(&pq->s1);
		}
	}
}

DataType QueueFront(QueueByTwoStack* pq)
{
	assert(pq);
	return StackTop(&pq->s2);
}
int QueueEmpty(QueueByTwoStack* pq)
{
	assert(pq);
	return StackEmpty(&pq->s1) || StackEmpty(&pq->s2);
}
int QueueSize(QueueByTwoStack* pq)
{
	assert(pq);
	return StackSize(&pq->s1) + StackSize(&pq->s2);
}
void TestQueue()
{
}

test.c

#include"QueueByTwoStack.h"
int main()
{
	Stack s;
	int i = 0;
	StackInit(&s);
	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	StackPush(&s, 4);
	StackPush(&s, 5);
	for (i = 0; i < 5; i++)
	{
		printf("%d ", StackTop(&s));
		StackPop(&s);
	}
	printf("\n");
	StackDestory(&s);
	system("pause");
	return 0;
}


使用两个队列实现一个栈

解题思路:入队时,直接压入q1中, 出队时,判断若q2是否为空,如果q2为空,则将q1中的前n-1个元素倒入q2中,然后再Pop掉q1中的最后一个元素. 否则q1空,则将q2中的前n-1元素倒入q1中,然后再Pop掉q2中的最后一个元素, 始终保持栈顶元素为q1或q2中非空队列的队尾元素为栈顶元素;

StackByTwoQueue.h

#pragma once
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <stdlib.h>
typedef int DataType;
typedef struct QueueNode
{
	struct QueueNode* _next;
	DataType _data;
}QueueNode;

typedef struct Queue
{
	QueueNode* _front; // 队头
	QueueNode* _back;  // 队尾
}Queue;

typedef struct Stack
{
	Queue q1;
	Queue q2;
}Stack;

void StackInit(Stack* ps);
void StackDestory(Stack* ps);
void StackPush(Stack* ps, DataType x);
void StackPop(Stack* ps);
DataType StackTop(Stack* ps);
int StackEmpty(Stack* ps);
int StackSize(Stack* ps);
void TestStack();

StackByTwoQueue.c

#include "StackByTwoQueue.h"

void StackInit(Stack* ps)
{
	assert(&ps->q1);
	QueueInit(&ps->q1);
	QueueInit(&ps->q2);
}
void StackDestory(Stack* ps)
{
	assert(ps);
	QueueDestory(&ps->q1);
	QueueDestory(&ps->q2);
}
void StackPush(Stack* ps, DataType x)
{
	assert(ps);
	QueuePush(&ps->q1, x);
}
void StackPop(Stack* ps)
{
	assert(ps);
	assert(&ps->q1 || &ps->q2);
	//判断q1是否为空
	if (QueueEmpty(&ps->q1))
	{
		while (QueueSize(&ps->q1) != 1)
		{
			QueuePush(&ps->q2, QueueFront(&ps->q1));
			QueuePop(&ps->q1);
		}
		QueuePop(&ps->q1);
	}
	else
	{
		while (QueueSize(&ps->q2) != 1)
		{
			QueuePush(&ps->q1, QueueFront(&ps->q2));
			QueuePop(&ps->q2);
		}
		QueuePop(&ps->q2);
	}
}
DataType StackTop(Stack* ps)
{
	assert(ps);
	if (QueueEmpty(&ps->q1))
		return (&ps->q1)->_back->_data;
	else if (QueueEmpty(&ps->q2))
		return (&ps->q2)->_back->_data;
	else perror("Top Empty");
}
int StackEmpty(Stack* ps)
{
	assert(ps);
	return (QueueEmpty(&ps->q1) || QueueEmpty(&ps->q2));
}
int StackSize(Stack* ps)
{
	assert(ps);
	return (QueueSize(&ps->q1) + QueueSize(&ps->q2));
}
void TestStack()

test.c

#include "StackByTwoQueue.h"
int main()
{
	Stack s;
	int i = 0;
	StackInit(&s);
	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	StackPush(&s, 4);
	StackPush(&s, 5);
	while (StackEmpty(&s))
	{
		printf("%d ", StackTop(&s));
		StackPop(&s);
	}
	printf("\n");
	StackDestory(&s);
	system("pause");
	return 0;
}

元素出栈、入栈顺序的合法性。如入栈的序列(1,2,3,4,5),出栈序列为

(4,5,3,2,1)

解题思路 : 我们可以将数组1的元素入栈 ,每入一个元素, 就将栈顶元素和数组2中的数据比较, 如果相同则出栈,然后在用栈顶元素和数组2的下一个元素比较, 如果相等继续出栈, 直到不相等为止,  如果不相同数组1就继续入栈, 当数组1全部入栈时, 循环结束, 然后只需要判断栈是否为空, 若栈为空则合法, 否则不合法.

int JudgeStack(int arv[], int arg[], int length1, int length2)
{
	Stack ps;
	int len1 = 0;
	int len2 = 0;
	StackInit(&ps);
	if ((length1 != length2) || arv == NULL || arg == NULL)
	{
		return -1;
	}
	while (len1 < length1)
	{
		StackPush(&ps, arv[len1]);
		len1++;
                //当数组2元素等于栈顶元素时,直到不相等或者数组2无元素时
		while ((len2 < length2) &&
			(arg[len2] == StackTop(&ps)))
		{
			StackPop(&ps);
			len2++;
		}
	}
        //空则合法
	if (StackEmpty(&ps))
	{
		StackDestroy(&ps);
		return 0;
	}
        //非空不合法
	else
	{
		StackDestroy(&ps);
		return 1;
	}
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值