栈和队列面试题

  • 实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值)的时间复杂度为O(1)
    解题思路:将每个元素入栈两次,第一次表示要入栈的元素value,第二次表示当前栈中的最小值min。

    

代码实现:

我们还是要基于栈的基本操作的实现来编写这个代码。一个元素插入两次,一次表示入栈元素value,一次表示当前栈中的最小值min。需要注意的是,在入栈时,应当先入value,再入min。出栈时,每次出栈两个元素。

seqstack.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>

typedef char SeqStackType;

typedef struct MinStack{
    SeqStack stack;
}MinStack;
 
void MinStackPush(MinStack* min_stack,SeqStackType value);//入栈
void MinStackPop(MinStack* min_stack)//出栈
int MinStackTop(MinStack* min_stack,SeqStackType* value);//取栈顶元素
minstack.c:
#include "seqstack.h"

void MinStackPush(MinStack* min_stack,SeqStackType value){
    if(min_stack == NULL)
        return;
    SeqStackType min = value;
    SeqStackType top;
    int ret = GetTop(&min_stack->stack,&top);
    if(ret != 0){
        min = top < value ? top : value;
    }
    SeqStackPush(&min_stack->stack,value);
    SeqStackPush(&min_stack->stack,min);
    return;
}

void MinStackPop(MinStack* min_stack){
    if(min_stack == NULL)
        return;
    SeqStackPop(&min_stack->stack);
    SeqStackPop(&min_stack->stack);
}

int MinStackTop(MinStack* min_stack,SeqStackType* value){
    if(min_stack == NULL || value == NULL)
        return 0;
    return GetTop(&min_stack->stack,value);
}
#include "seqstack.h"

void testMinStack(){
    MinStack s;
    SeqStackType value;
    SeqStackInit(&s.stack);
    MinStackPush(&s,'d');
    int ret = MinStackTop(&s,&value);
    printf("ret expect 1, actual %d\n",ret);
    printf("top expect d, actual %c\n",value);
    MinStackPush(&s,'c');
    MinStackPush(&s,'b');
    MinStackPush(&s,'a');
    ret = MinStackTop(&s,&value);
    printf("ret expect 1, actual %d\n",ret);
    printf("top expect a, actual %c\n",value);
    MinStackPop(&s);
    ret = MinStackTop(&s,&value);
    printf("ret expect 1, actual %d\n",ret);
    printf("top expect b, actual %c\n",value);
}

int main(){
    testMinStack();
    return 0;
}

    结果演示:


  • 使用两个栈实现一个队列

定义两个栈,一个作为输入,一个作为输出。


上面这张图为入队列时的操作示意图。


上面这张图为出队列时的操作示意图。


上面这张图为取栈顶元素的操作示意图。

queby2stack.c:
typedef struct QueBy2Stack{
    SeqStack input;
    SeqStack output;
}QueBy2Stack;

void QueBy2StackInit(QueBy2Stack* q){
    if(q == NULL)
        return;
    //input用于入队列的场景
    //output用于出队列和取队首元素的场景
    SeqStackInit(&q->input);
    SeqStackInit(&q->output);
}

void QueBy2StackPush(QueBy2Stack* q,SeqStackType value){
    if(q == NULL)
        return;
    while(1){
        SeqStackType top;
        //先将所有output中的元素放到input中
        int ret = GetTop(&q->output,&top);
        if(ret == 0)
            break;
        SeqStackPop(&q->output);
        SeqStackPush(&q->input,top);
    }
    //把新元素value插入到input中
    SeqStackPush(&q->input,value);
    return;
}

void QueBy2StackPop(QueBy2Stack* q){
    if(q == NULL)
        return;
    //把所有input中的元素放到output中
    while(1){
        SeqStackType top;
        int ret = GetTop(&q->input,&top);
        if(ret == 0)
            break;
        SeqStackPop(&q->input);
        SeqStackPush(&q->output,top);
    }
    //将output的栈顶元素出栈
    SeqStackPop(&q->output);
}

int QueBy2StackFront(QueBy2Stack* q,SeqStackType* value){
    if(q == NULL || value == NULL)
        return 0;
    //将所有input中的元素放到output中
    while(1){
        SeqStackType top;
        int ret = GetTop(&q->input,&top);
        if(ret == 0)
            break;
        SeqStackPop(&q->input);
        SeqStackPush(&q->output,top);
    }
    return GetTop(&q->output,value);
}
test.c:
#include "seqstack.h"

void TestQueBy2Stack(){
    QueBy2Stack q;
    SeqStackType value;
    QueBy2StackInit(&q);
    QueBy2StackPush(&q,'a');
    QueBy2StackPush(&q,'b');
    QueBy2StackPush(&q,'c');
    QueBy2StackPush(&q,'d');
    
    int ret = QueBy2StackFront(&q,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("top except a,actual %c\n",value);

    QueBy2StackPop(&q);
    ret = QueBy2StackFront(&q,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("top except b,actual %c\n",value);

    QueBy2StackPop(&q);
    ret = QueBy2StackFront(&q,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("top except c,actual %c\n",value);

    QueBy2StackPop(&q);
    ret = QueBy2StackFront(&q,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("top except c,actual %c\n",value);

    QueBy2StackPop(&q);
    ret = QueBy2StackFront(&q,&value);
    printf("ret expect 0,actual %d\n",ret);
}

int main(){
    TestQueBy2Stack();
    return 0;
}

结果演示:


  • 使用两个队列实现一个栈

这里我们可以定义两个空队列,将所有元素依次入队列到其中一个队列中。栈要求后进先出,所以在进行入栈操作时,在非空的队列中进行push操作即可。


如上图所示,在进行出栈操作时,我们要先依次将非空队列from中的元素放到另外一个空队列to中,直至from中只剩下一个元素,然后进行pop操作即可。

上图为取栈顶元素的操作示意图。

stackbu2que.c:
typedef struct StackBy2Queue{
    SeqQueue queue1;
    SeqQueue queue2;
}StackBy2Queue;

void StackBy2QueueInit(StackBy2Queue* stack){
    if(stack == NULL)
        return;
    SeqQueueInit(&stack->queue1);
    SeqQueueInit(&stack->queue2);
}

void StackBy2QueuePush(StackBy2Queue* stack,SeqQueueType value){
    if(stack == NULL)
        return;
    //取两个队列中非空的元素进行插入
    SeqQueue* input = stack->queue1.size!=0 ? &stack->queue1 : &stack->queue2;
    SeqQueuePush(input,value);
}

void StackBy2QueuePop(StackBy2Queue* stack){
    if(stack == NULL)
        return;
    //若为空栈
    if(stack->queue1.size == 0 && stack->queue2.size == 0)
        return;
    //先弄清楚谁往谁里面放元素
    SeqQueue* from = NULL;
    SeqQueue* to =NULL;
    if(stack->queue1.size > 0){
        from = &stack->queue1;
        to = &stack->queue2;
    }
    else{
        from = &stack->queue2;
        to = &stack->queue1;
    }
    //把from中的元素放到to中
    //并且一直放,直至from中只剩一个元素
    while(1){
        if(from->size == 1)
            //此时from中只剩下一个元素,此时from中的队首元素就是栈顶元素
            break;
        SeqQueueType value;
        SeqQueueFront(from,&value);
        SeqQueuePop(from);
        SeqQueuePush(to,value);
    }
    //把最后一个元素删除
    SeqQueuePop(from);
    return;
}

int StackBy2QueueTop(StackBy2Queue* stack,SeqQueueType* output_value){
    if(stack == NULL || output_value == NULL)
        return 0;
    if(stack->queue1.size == 0 && stack->queue2.size == 0)
        return 0;
    //先弄清楚谁往谁里面放元素
    SeqQueue* from = NULL;
    SeqQueue* to =NULL;
    if(stack->queue1.size > 0){
        from = &stack->queue1;
        to = &stack->queue2;
    }
    else{
        from = &stack->queue2;
        to = &stack->queue1;
    }
    //把from中的元素放到to中
    while(1){
        if(from->size == 0)
            break;
        SeqQueueFront(from,output_value);
        SeqQueuePop(from);
        SeqQueuePush(to,*output_value);
    }
    return 1;
}

#include "seqqueue.h"
#define PRINT_HEADER printf("\n============%s============\n",__FUNCTION__)

void TestStack(){
    PRINT_HEADER;
    StackBy2Queue stack;
    StackBy2QueueInit(&stack);
    StackBy2QueuePush(&stack,'a');
    StackBy2QueuePush(&stack,'b'); 
    StackBy2QueuePush(&stack,'c'); 
    StackBy2QueuePush(&stack,'d');

    SeqQueueType value;
    int ret = StackBy2QueueTop(&stack,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("value expect d,actual %c\n",value);

    StackBy2QueuePop(&stack);
    ret = StackBy2QueueTop(&stack,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("value expect c,actual %c\n",value);
    
    StackBy2QueuePop(&stack);
    ret = StackBy2QueueTop(&stack,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("value expect b,actual %c\n",value);

    StackBy2QueuePop(&stack);
    ret = StackBy2QueueTop(&stack,&value);
    printf("ret expect 1,actual %d\n",ret);
    printf("value expect a,actual %c\n",value);

    StackBy2QueuePop(&stack);
    ret = StackBy2QueueTop(&stack,&value);
    printf("ret expect 0,actual %d\n",ret);
    
    return;
}

int main(){
    TestStack();
    return 0;
}

结果演示:

  • 元素入栈、出栈顺序的合法性

stackorder.c:
#include "seqstack.h"
#include<stddef.h>

int StackOrder(char input[],size_t input_size,char output[],size_t output_size){
    SeqStack stack;
    SeqStackInit(&stack);
    //1.循环的将input中的元素入栈
    size_t i = 0;
    int output_index = 0;
    for(;i < input_size;i++){
        SeqStackPush(&stack,input[i]);
        char top;
        int ret = GetTop(&stack,&top);
        if(ret == 0)
            //栈已空,准备进行最终判断
            break;
    //2.取栈顶元素与output_index指向的元素作比较
        while(1){
            //3.若不相等,继续循环取下一个input中的元素入栈                                                                                                                                      
            //4.若相等
            //a)将output_index往后移
            //b)将栈顶元素出栈
            //c)循环的比较栈顶元素与output_index指向的元素的值
            if(output_index >= output_size){
                //output序列已经遍历完毕,需要进行最终判断
                break;
            }
            if(top != output[output_index]){
                break;
            }
            ++output_index;
            SeqStackPop(&stack);
        }
    }
    //5.若最终栈为空且output_index指向output数组中的最后一个元素的下一个元素,则认为可以变换得到
    if(stack.size == 0 && output_index == output_size){
        return 1;
    }
    //否则无法变换得到
    return 0;
}
test.c:
#include "seqstack.h"

void TestStackOrder(){
    SeqStack stack;
    SeqStackInit(&stack);
    char input[] = "abcde";
    char output1[] = "decba";
    char output2[] = "deabc";
    int size = sizeof(input)/sizeof(input[0]);

    int ret = StackOrder(input,size,output1,size);
    printf("ret expect 1,actual %d\n",ret);
    ret = StackOrder(input,size,output2,size);
    printf("ret expect 0,actual %d\n",ret);
    return;
}

int main(){
    TestStackOrder();
    return 0;
}

结果演示:


  • 一个数组实现两个栈(共享栈)

sharedstack.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>

#define MaxSize 100

typedef int SharedStackType;
typedef struct SharedStack{
    int arr[MaxSize];
    int top1;
    int top2;
}SharedStack;
sharedstack.c:
#include "sharedstack.h"

void SharedStackInit(SharedStack* s){
    if(s == NULL)
        return;
    s->top1 = 0;
    s->top2 = MaxSize;
}

void SharedStackPush(SharedStack* s,SharedStackType value,SharedStackType which){
    if(s == NULL)
        return;
    if(s->top1 >= s->top2)
        //栈满
        return;
    if(which != 1 && which != 2)
        //既不在栈1也不在栈2
        //非法输入
        return;
    if(which == 1){
        s->arr[s->top1++] = value;
    }
    else{
        s->arr[--s->top2] = value;
    }
    return;
}

int IsEmpty(SharedStack* s,SharedStackType which){
    if(s == NULL)
        return 0;
    if(which != 1 && which != 2)
        return 0;
    if(which == 1){
        return s->top1==0 ? 1:0;
    }
    else{
        return s->top2==MaxSize? 1:0;
    }
    return 0;
}

void SharedStackPop(SharedStack* s,SharedStackType which){
    if(s == NULL)
        return;
    if(IsEmpty(s,which)){
        //栈为空
        return;
    }
    if(which != 1 && which != 2){
        return;
    }
    if(which == 1){
        s->top1--;
    }
    else{
        s->top2++;
    }
    return;
}

int SharedStackTop(SharedStack* s,SharedStackType which){
    if(s == NULL)
        return 0;
    if(IsEmpty(s,which))
        return 0;
    if(which == 1){
        return s->arr[s->top1-1];
    }
    else{
        return s->arr[s->top2];
    }
    return 0;
}
test.c:
#include"sharedstack.h"
 
void TestSharedStack(){
    SharedStack s;
    SharedStackInit(&s);
    SharedStackPush(&s,1,1);
    SharedStackPush(&s,2,1);
    SharedStackPush(&s,3,1);
    SharedStackPush(&s,4,1);
    int ret1 = SharedStackTop(&s,1); 
    printf("ret1 expect 4,actual %d\n",ret1);
    SharedStackPop(&s,1);
    SharedStackPop(&s,1);
    ret1 = SharedStackTop(&s,1);
    printf("ret1 expect 2,actual %d\n",ret1);
    

    SharedStackPush(&s,5,2);
    SharedStackPush(&s,6,2);     
    SharedStackPush(&s,7,2);     
    SharedStackPush(&s,8,2);
    int ret2 = SharedStackTop(&s,2); 
    printf("ret2 expect 8,actual %d\n",ret2);
    SharedStackPop(&s,2);
    SharedStackPop(&s,2);
    ret2 = SharedStackTop(&s,2);
    printf("ret2 expect 6,actual %d\n",ret2);   

}

int main(){
    TestSharedStack();
}

结果演示:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值