LeetCode Hot Topic 100 - Stack and Queue Topic (3)

1. Valid parentheses

20. Valid brackets (question link)

Idea:

1) Matching of the order of brackets: implemented using stack, when a left bracket is encountered, it is entered, and when a right bracket is encountered, it is output (guaranteed that the left bracket corresponds to the right bracket), otherwise the order does not match.

2) The number of brackets matches:

1>The left bracket is greater than the right bracket: Use the stack to implement it. When the left bracket comes in and the right bracket comes out, after traversing the character array, the stack is not empty at this time, which means that the number of left brackets is greater than the right bracket;

2>The right bracket is greater than the left bracket: When a right bracket is encountered, determine whether the stack is empty. If the stack is empty at this time, it means that the number of right brackets is greater than the left bracket;

typedef char  SDateType;
typedef struct Stack
{
	SDateType* a;
	int top;
	int capacity;

}Stack;
//初始化栈和销毁栈
void InitStack(Stack* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}
void DestoryStack(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;

}

//出栈和入栈
void StackPush(Stack* ps, SDateType x)
{
	assert(ps);
	//扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SDateType* tmp = (SDateType*)realloc( ps->a,newcapacity * sizeof(SDateType));
		if (tmp == NULL)
		{
			perror("realloc fail:");
			return;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;

	}
	//尾插
	ps->a[ps->top] = x;
	ps->top++;
}
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);//只少有一个元素,才能删除
	ps->top--;
}

//栈的有效个数和栈顶元素
int  StackSize(Stack* ps)
{
	assert(ps);
	return ps->top;
}
int   StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->a[ps->top - 1];
}

//栈是否为空
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == 0;
}
int isValid(char* s) {
	Stack ps;
	InitStack(&ps);

	while (*s)
	{
		if (*s == '[' || *s == '(' || *s == '{')
		{
			StackPush(&ps, *s);
			s++;
		}
		else

		{
			if (StackEmpty(&ps))
			{
				return false;
			}
			char tmp = StackTop(&ps);
			StackPop(&ps);
			if ((*s == ']' && tmp != '[') ||
				(*s == '}' && tmp != '{') ||
				(*s == ')' && tmp != '('))
			{
				return false;
			}

			s++;

		}
	}
	if (!StackEmpty(&ps))
	{
		return false;
	}
	else {
		return true;
	}
	DestoryStack(&ps);
}

2. Use queues to implement stacks 

225. Use queue to copy stack (topic link)

Idea: The stack is last in, first out, and the queue is first in, first out.

Implementing a stack using two queues

1) When pushing into the stack, selectthe queue with data to insert data;

2) When popping the stack, the first k-1 data in the data queue will be dequeued and merged into In empty queue, return and exitthe last data of data queue

typedef int QDateType;
typedef struct QueueNode
{
	QDateType val;
	struct QueueNode * next;
}QueueNode;
typedef struct Queue
{
	QueueNode *head;
	QueueNode *tail;
	QDateType size;
}Queue;

// 初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDateType x)
{
	assert(pq);
	QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
	
	node->val = x;
	node->next = NULL;
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = node;
		pq->size++;
	}
	else
	{
		pq->tail->next = node;
		pq->tail = node;
		pq->size++;
	}
}
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head != NULL);//只少保证一个节点
	QueueNode* del = pq->head;
	pq->head = pq->head->next;
	free(del);
	del = NULL;
	pq->size--;
	if (pq->head == NULL)//只有一个节点处理
	{
		pq->tail = NULL;
	}
}

// 返回队头和队尾
QDateType QueueFront(Queue* pq)
{
	assert(pq);
	return pq->head->val;
}
QDateType QueueBack(Queue* pq)
{
	assert(pq);
	return pq->tail->val;
}

// 获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}



bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head==NULL;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;

}
typedef struct {
    Queue q1;
     Queue q2;

} MyStack;


MyStack* myStackCreate() {
    MyStack* obj=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);
    return obj;

}

void myStackPush(MyStack* obj, int x) {
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else{
        QueuePush(&obj->q2,x);
    }
}
bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}

int myStackPop(MyStack* obj) {
    assert(!myStackEmpty(obj));
    Queue * empty=&obj->q1;
    Queue * nonempty=&obj->q2;
    if(!QueueEmpty(empty))
    {
        empty=&obj->q2;
        nonempty=&obj->q1;
    }
    while(QueueSize(nonempty)!=1)
    {
       int tmp= QueueFront(nonempty);
       QueuePush(empty,tmp);
        QueuePop(nonempty);
    }
     int tmp= QueueFront(nonempty);
      QueuePop(nonempty);
      return tmp;
}

int myStackTop(MyStack* obj) {
     assert(!myStackEmpty(obj));
    Queue * empty=&obj->q1;
    Queue * nonempty=&obj->q2;
    if(!QueueEmpty(empty))
    {
        empty=&obj->q2;
        nonempty=&obj->q1;
    }
    return QueueBack(nonempty);
}



void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);

}

3. Use stack to implement queue 

225. Use stack to implement queue (topic link)

Idea: The stack is last in, first out, and the queue is first in, first out.

1)Enqueue: s1 stack is used to put data on the top of the stack;

2)Dequeue: The s2 stack is used to pop out the top data of the stack. If s2 is empty, the data is exported from s1 to s2. (for example; the data in s1 is 1, 2, 3, and when it is entered into s2, it becomes 3, 2, 1), and then the data on the top of the stack of s2 is taken out, which satisfies the properties of the queue

 

typedef int  SDateType;
typedef struct Stack
{
	SDateType* a;
	int top;
	int capacity;

}Stack;
//初始化栈和销毁栈
void InitStack(Stack* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}
void DestoryStack(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;

}

//出栈和入栈
void StackPush(Stack* ps, SDateType x)
{
	assert(ps);
	//扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SDateType* tmp = (SDateType*)realloc( ps->a,newcapacity * sizeof(SDateType));
		if (tmp == NULL)
		{
			perror("realloc fail:");
			return;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;

	}
	//尾插
	ps->a[ps->top] = x;
	ps->top++;
}
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);//只少有一个元素,才能删除
	ps->top--;
}

//栈的有效个数和栈顶元素
int  StackSize(Stack* ps)
{
	assert(ps);
	return ps->top;
}
int   StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->a[ps->top - 1];
}

//栈是否为空
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == 0;
}



typedef struct {
    Stack s1;
    Stack s2;
    
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue* )malloc(sizeof(MyQueue));
    InitStack(&obj->s1);
    InitStack(&obj->s2);
    return obj;

}

void myQueuePush(MyQueue* obj, int x) {
    StackPush(&obj->s1,x);
}

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->s1)&&StackEmpty(&obj->s2);
}

int myQueuePop(MyQueue* obj) {
    assert(!myQueueEmpty(obj));
    if(StackEmpty(&obj->s2))
    {
       while(!StackEmpty(&obj->s1))
       {
          int tmp= StackTop(&obj->s1);
          StackPush(&obj->s2,tmp);
          StackPop(&obj->s1);
       }
      
    }
     int tmp= StackTop(&obj->s2);
       StackPop(&obj->s2);
       return tmp;
}

int myQueuePeek(MyQueue* obj) {
     assert(!myQueueEmpty(obj));
    if(StackEmpty(&obj->s2))
    {
       while(!StackEmpty(&obj->s1))
       {
          int tmp= StackTop(&obj->s1);
          StackPush(&obj->s2,tmp);
          StackPop(&obj->s1);
       }
       
    }
    return StackTop(&obj->s2);
}



void myQueueFree(MyQueue* obj) {
    
   DestoryStack(&obj->s1);
   DestoryStack(&obj->s2);
   free(obj);



}

 4. Design Circular Queue

622. Design circular queue (topic link)

Idea 1: Array

With front as the subscript of the queue head and tail as the subscript of the next element at the end of the queue, there are k pieces of data in total, and k+1 integer-sized spaces are opened to facilitate the distinction between the queue being empty, full and one element.

1) The queue is empty, front=tail

2) The queue has 1 element, front+1=tail

3) The queue is full, (tail+1)%(k+1)==front

 

typedef struct {
    int *a;
    int front;
    int rear;
    int n;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    int * tmp=(int *)malloc(sizeof(int)*(k+1));
    obj->a=tmp;
    obj->front=0;
    obj->rear=0;
    obj->n=k;
    return obj;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    if((obj->rear+1)%(obj->n+1)==obj->front)
    {
        return true;
    }
    return false;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull( obj))
    {
        return false;
    }
    obj->a[obj->rear]=value;
    obj->rear++;
    obj->rear=obj->rear%(obj->n+1);
    return true;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    if(obj->front==obj->rear)
    {
        return true;
    }
    return false;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty( obj))
    {
        return false;
    }
    obj->front++;
    obj->front=obj->front%(obj->n+1);
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty( obj))
    {
        return -1;
    }
    return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty( obj))
    {
        return -1;
    }
    return  obj->a[(obj->rear-1+obj->n+1)%(obj->n+1)];
}




void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

Idea 2: One-way circular linked list

With head as the head node of the queue and tail as the next node of the tail node of the queue, there are k data in total, and a circular one-way linked list of k+1 nodes is opened to facilitate the distinction between the queue being empty, full and one element.

1) The queue is empty, head=tail

2) The queue is 1 element, head->next=tail

3) The queue is full, tail->next=head

 

typedef struct QueueNode
{
	int val;
	struct QueueNode * next;
}QueueNode;

QueueNode* BuyNode(int x)
{
    QueueNode* node=(QueueNode*)malloc(sizeof(QueueNode));
    node->val=x;
    node->next=NULL;
    return node;
}
typedef struct MyCircularQueue{
   QueueNode *head;
	QueueNode *tail;
    QueueNode * pretail;
	int n;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    QueueNode* node=BuyNode(0);
    obj->pretail=NULL;
    obj->head=obj->tail=node;
    obj->n=(k+1);
    QueueNode* cur=obj->tail;
    while(k--)
    {
       QueueNode* node=BuyNode(0);
     
      cur->next=node;
        cur= cur->next;
    }
   
   cur->next=obj->head;
    return obj;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    if(obj->tail->next==obj->head)
    {
        return true;
    }
    return false;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull( obj))
    {
        return false;
    }
    obj->tail->val=value;
    obj->pretail=obj->tail;
    obj->tail=obj->tail->next;
   
     
    return true;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    if(obj->head==obj->tail)
    {
        return true;
    }
    return false;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty( obj))
    {
        return false;
    }
    obj->head=obj->head->next;
   
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty( obj))
    {
        return -1;
    }
    return obj->head->val;
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty( obj))
    {
        return -1;
    }
    return  obj->pretail->val;
}




void myCircularQueueFree(MyCircularQueue* obj) {
   while(obj->n--)
   {
       QueueNode*next=obj->head->next;
       free(obj->head);
       obj->head=next;
   }
   obj->head=NULL;
    free(obj);
}

Guess you like

Origin blog.csdn.net/zhoubancheng/article/details/134538488