• DS博客作业02--栈和队列


    0.PTA得分截图

    1.本周学习总结

    1.1 总结栈和队列内容

    1.栈的存储结构及操作

    1.栈

    1.栈(stack):是限定仅在表尾进行插入和删除操作的线性表。其中,允许插入和删除的一端被称为栈顶(top),另一端被称为栈底(bottom),不含任何数据元素的栈被称为空栈。栈又被称为后进先出(Last In First Out)的线性表,简称LIFO结构。
    栈的插入操作为进栈,栈的删除操作为出栈。

    2.栈的抽象数据类型
    ADT 栈(stack)
    Data
    同线性表。元素具有相同类型,相邻元素具有前驱和后继关系。
    Operation
    InitStack(S):初始化操作,建立一个空栈S。
    DestoryStack(
    S):若栈存在,则销毁它。
    ClearStack(S):将栈清空。
    StackEmpty(S):若栈为空,返回true,否则返回false。
    GetTop(S,
    e):若栈存在且非空,用e返回S的栈顶元素。
    Push(S,e):若栈S存在,插入新元素e到栈S中并称为栈顶元素
    Pop(
    S,*e):删除栈S中栈顶元素,并用e返回其值
    StackLength(S):返回栈S的元素个数
    endADT

    2.栈的存储结构

    (1)栈顺序结构定义

    #define OK 1
    #define ERROR 0
    typedef int SElemType;    //SElemType类型根据实际情况而定,这里假设为int
    typedef struct
    {
        SElemType data[MAXSIZE];    //栈存储空间大小MAXSIZE
        int top;    //用于栈顶指针
    }SqStack;
    

    (2)共享栈

    3.栈的顺序存储结构
    栈类型SqStack:

    typedef struct 
    {  ElemType data[MaxSize]; 
       int top;		//栈顶指针
    } Stack;
    typedef Stack *SqStack;
    



    顺序栈4要素:
    栈空条件:top=-1
    栈满条件:top=MaxSize-1
    进栈e操作:top++; st->data[top]=e
    退栈操作:e=st->data[top]; top--;
    顺序栈中实现栈的基本运算算法
    (1)初始化栈initStack(&s)

    void InitStack(SqStack &s)
    {  s=new Stack;     
        s->top=-1;
      }
    

    (2)销毁栈ClearStack(&s)

    void DestroyStack(SqStack &s)
    {
      delete s;
    }
    

    (3)判断栈是否为空StackEmpty(s)

    bool StackEmpty(SqStack s)
    {
      return(s->top==-1);
    }
    

    (4)进栈操作(从栈顶插入一个元素)
    算法思路:
    a.判定是否栈满;
    b.栈顶加1;
    c.将元素插入到
    实现:插入元素e为新的栈顶元素

    Status Push(SqStack *S,SElemType e)
    {
        if(S->top==MAXSIZE-1)    //栈顶=MAXSIZE-1,即数组的最后一个存储位置,说明栈满
        {
            return ERROR;
        }
        S->top++;    //栈顶加1
        S->data[S->top]=e;    //将元素入栈
        return OK;
    }
    

    (5)出栈操作(从栈顶删除一个元素)
    算法思路:
    a.判定栈是否为空;
    b.将栈顶元素保存到指针变量e所指向的存储位置中;
    c.栈顶减1.
    实现:若栈不为空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR

    Status Pop(SqStack *S,SElemType *e)
    {
        if(S->top==-1)    //空栈
        {
            return ERROR;
        }
        *e=S->data[S->top];
        S->top--;
        return OK;
    }
    

    (6)取栈顶元素GetTop(s)
    在栈不为空的条件下,将栈顶元素赋给e。

    bool GetTop(SqStack *s,ElemType &e)
    {	
       if (s->top==-1)	//栈为空的情况    
        return false;
        e=s->data[s->top];	    
        return true;
    }
    

    2.栈的应用

    ------------恢复内容开始------------

    0.PTA得分截图

    1.本周学习总结

    1.1 总结栈和队列内容

    1.栈的存储结构及操作

    1.栈

    1.栈(stack):是限定仅在表尾进行插入和删除操作的线性表。其中,允许插入和删除的一端被称为栈顶(top),另一端被称为栈底(bottom),不含任何数据元素的栈被称为空栈。栈又被称为后进先出(Last In First Out)的线性表,简称LIFO结构。
    栈的插入操作为进栈,栈的删除操作为出栈。

    2.栈的抽象数据类型
    ADT 栈(stack)
    Data
    同线性表。元素具有相同类型,相邻元素具有前驱和后继关系。
    Operation
    InitStack(S):初始化操作,建立一个空栈S。
    DestoryStack(
    S):若栈存在,则销毁它。
    ClearStack(S):将栈清空。
    StackEmpty(S):若栈为空,返回true,否则返回false。
    GetTop(S,
    e):若栈存在且非空,用e返回S的栈顶元素。
    Push(S,e):若栈S存在,插入新元素e到栈S中并称为栈顶元素
    Pop(
    S,*e):删除栈S中栈顶元素,并用e返回其值
    StackLength(S):返回栈S的元素个数
    endADT

    2.栈的存储结构

    1.栈的顺序存储结构
    栈类型SqStack:

    typedef struct 
    {  ElemType data[MaxSize]; 
       int top;		//栈顶指针
    } Stack;
    typedef Stack *SqStack;
    



    顺序栈4要素:
    栈空条件:top=-1
    栈满条件:top=MaxSize-1
    进栈e操作:top++; st->data[top]=e
    退栈操作:e=st->data[top]; top--;
    顺序栈中实现栈的基本运算算法
    (1)初始化栈initStack(&s)

    void InitStack(SqStack &s)
    {  s=new Stack;     
        s->top=-1;
      }
    

    (2)销毁栈ClearStack(&s)

    void DestroyStack(SqStack &s)
    {
      delete s;
    }
    

    (3)判断栈是否为空StackEmpty(s)

    bool StackEmpty(SqStack s)
    {
      return(s->top==-1);
    }
    

    (4)进栈操作(从栈顶插入一个元素)
    算法思路:
    a.判定是否栈满;
    b.栈顶加1;
    c.将元素插入到
    实现:插入元素e为新的栈顶元素

    Status Push(SqStack *S,SElemType e)
    {
        if(S->top==MAXSIZE-1)    //栈顶=MAXSIZE-1,即数组的最后一个存储位置,说明栈满
        {
            return ERROR;
        }
        S->top++;    //栈顶加1
        S->data[S->top]=e;    //将元素入栈
        return OK;
    }
    

    (5)出栈操作(从栈顶删除一个元素)
    算法思路:
    a.判定栈是否为空;
    b.将栈顶元素保存到指针变量e所指向的存储位置中;
    c.栈顶减1.
    实现:若栈不为空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR

    Status Pop(SqStack *S,SElemType *e)
    {
        if(S->top==-1)    //空栈
        {
            return ERROR;
        }
        *e=S->data[S->top];
        S->top--;
        return OK;
    }
    

    (6)取栈顶元素GetTop(s)
    在栈不为空的条件下,将栈顶元素赋给e。

    bool GetTop(SqStack *s,ElemType &e)
    {	
       if (s->top==-1)	//栈为空的情况    
        return false;
        e=s->data[s->top];	    
        return true;
    }
    

    2.栈链式存储结构
    定义:

    typedef int ElemType;
    typedef struct linknode
    {  ElemType data;			//数据域
       struct linknode *next;	//指针域
    } LiNode,*LiStack;
    

    链栈中实现栈的基本运算算法:
    (1)初始化栈initStack(&s)

    void InitStack(LiStack &s)
    {  s=new LiNode;
       s->next=NULL;
    }
    


    (2)销毁栈ClearStack(&s)
    释放栈s占用的全部存储空间。同链表删除:

    void DestroyStack(LiStack &s)
    { LiStack p;
       while (s!=NULL)
       {	  p=s; 	
           s=s->next;
           free(p); 
       }
     }
    

    3)判断栈是否为空StackEmpty(s)
    栈S为空的条件是s->next==NULL,同空链表

    bool StackEmpty(LiStack s)
    {
       return(s->next==NULL);
    }
    

    (4)进栈Push(&s,e)
    将新数据节点插入到头节点之后。对应算法如下:

    void Push(LiStack &s,ElemType e)
    {  LiStack p;
       p=new LiNode;
       p->data=e;		//新建元素e对应的节点*p
       p->next=s->next;	//插入*p节点作为开始节点
       s->next=p;
    }
    

    (5)出栈Pop(&s,&e)
    在栈不为空的条件下,将头节点后继数据节点的数据域赋给e

    bool Pop(LiStack &s,ElemType &e)
    {  LiStack p;
       if (s->next==NULL)		//栈空的情况
    	return false;
       p=s->next;			//p指向开始节点
       e=p->data;
       s->next=p->next;		//删除*p节点
       free(p);				//释放*p节点
       return true;
    }
    

    6)取栈顶元素GetTop(s,e)
    在栈不为空的条件下,将头节点后继数据节点的数据域赋给e。

    bool GetTop(LiStack s,ElemType &e)
    {  if (s->next==NULL)	//栈空的情况
    	return false;
       e=s->next->data;
       return true;
    }
    

    stack容器:

    #include<stack>
    1.stack<int>  s:初始化栈,参数表示元素类型
    2.s.push(t):入栈元素t
    3.s.top():返回栈顶元素
    4.s.pop():出栈操作只是删除栈顶元素,并不返回该元素。
    5.s1.empty(),当栈空时,返回true。
    6.s1.size():访问栈中的元素个数
    

    2.栈的应用

    表达式求值
    中缀转后缀表达式
    中缀表达式:运算符号位于两个运算数之间。如 ,a + b *c - d / e
    后缀表达式:运算符号位于两个运算数之后。如, a b c *+ d e /- 
    exp:字符数组
    a + b * c - d / e * f
    postexp:后缀表达式数组
    a b c d e f
    1.优先级比栈顶运算符高入栈
    2.低或相等,出栈,写入后缀表达式
    例如:对于表达式“(56-20)/(4+2)”,其转换成后缀表达式的过程 如下:



    表达式“(56-20)/(4+2)”
    后缀表达式:
    56#20#-4#2#+/
    对后缀表达式postexp求值

    while (从postexp读取字符ch,ch!='')
    {    若ch为数字,将后续所有数字构成一个整数存放数值栈st中。
         若ch为“+”,则从数值栈st中退栈两个运数,相加后进栈st中。
         若ch为“-”,则从数值栈st中退栈两个数,相减后进栈st中。
         若ch为“*”,则从数值栈st中退栈两个数,相乘后进栈st中。
         若ch为“/”,则从数值栈st中退栈两个数,相除后进栈st中
            (若除数为零,则提示相应的错误信息)。}
    若字符串postexp扫描完毕,则数值栈op中的栈顶元素就是表达式的值。
    

    2.队列

    1.定义及特点

    定义:只允许在表的一端进行插入,而在表的另一端进行删除的线性表。
    队尾(rear)——允许插入的一端
    队头(front)——允许删除的一端
    特点:先进先出(FIFO)

    2.队列的顺序存储结构及其基本运算

    顺序队类型SqQueue定义如下:
    typedef struct 
    {     ElemType data[MaxSize]; 
          int front,rear;      //队首和队尾指针
    }   Queue;
    typedef Queue *SqQueue;
    

    队列的基本运算如下:

        InitQueue(&q):初始化队列。构造一个空队列q。
        DestroyQueue(&q):销毁队列。释放队列q占用的存储空间。
        QueueEmpty(q):判断队列是否为空。若队列q为空,则返回真;否则返回假。
        enQueue(&q,e):进队列。将元素e进队作为队尾元素。
        deQueue(&q,&e):出队列。从队列q中出队一个元素,并将其值赋给e。
    


    顺序队的四要素(初始时front=rear=-1):
    队空条件:front = rear
    队满条件:rear=MaxSize-1
    元素e进队:rear++;data[rear]=e;
    元素e出队:front++;e=data[front];

    1. 顺序队中实现队列的基本运算
      (1)初始化队列InitQueue(q)
        构造一个空队列q。将front和rear指针均设置成初始状态即-1值。
    void InitQueue(SqQueue &q)
    {	q=new Queue;
    	q->front=q->rear=-1;
    }
    

    (2)销毁队列DestroyQueue(q)
    释放队列q占用的存储空间。

    void DestroyQueue(SqQueue &q)
    {
      delete q;
    }
    

    3)判断队列是否为空QueueEmpty(q)
    若队列q满足q->front==q->rear条件,则返回true;否则返回false。

    bool QueueEmpty(SqQueue q)
    {
       return(q->front==q->rear);
    }
    

    (4)进队列enQueue(q,e)
    在队列不满的条件下,先将队尾指针rear循环增1,然后将元素添加到该位置。

    bool enQueue(SqQueue &q,ElemType e)
    {  
        if (q->rear+1==MaxSize)	   return false;
                                           //队满上溢出
    	q->rear=q->rear+1;
    	q->data[q->rear]=e;
    	return true;
    }
    

    5)出队列deQueue(q,e)
    在队列q不为空的条件下,将队首指针front循环增1,并将该位置的元素值赋给e。

    bool deQueue(SqQueue &q,ElemType &e)
    {	
             if (q->front==q->rear)  //队空下溢出
    		return false;
    	q->front=q->front+1;
    	e=q->data[q->front];
    	return true;
    }
    

    2、环形队列(或循环队列)中实现队列的基本运算
    把数组的前端和后端连接起来,形成一个环形的顺序表,即把存储队列元素的表从逻辑上看成一个环,称为环形队列或循环队列。

    队空:frontrear
    队满:front
    rear
    front指向队头元素问题,解决方案:
    (1).另外设一个标志以区别队空、队满
    (2).少用一个元素空间,front指队头前一个位置
    队空:frontrear
    队满:(rear+1)%M
    front
    (3).顺序队列没这个问题。
    初始化队列:front=rear=0
    队满条件:(rear+1)%MaxSize=front
    队空条件:front=rear
    入队操作:rear=(rear+1)%MaxSize
    data[rear]=e;
    出队操作:front=(front+1)%MaxSize
    data[front]=e;
    基本运算:
    (1)初始化队列InitQueue(q)
    构造一个空队列q。将front和rear指针均设置成初始状态即0值。

    void InitQueue(SqQueue &q)
    {   q=new Queue;
        q->front=q->rear=0;
    }
    

    (2) 销毁队列

    void DestroyQueue(SqQueue &q)
    {
    	delete q;
    }
    

    (3) 判断队列是否为空

    bool QueueEmpty(SqQueue q)
    {
    	return(q->front==q->rear);
    }
    

    (4) 进环形队列

    bool enQueue(SqQueue &q,ElemType e)
    {	if ((q->rear+1)%MaxSize==q->front)	//队满上溢出
    		return false;
    	q->rear=(q->rear+1)%MaxSize;
    	q->data[q->rear]=e;
    	return true;
    }
    

    (5) 出环形队列

    bool deQueue(SqQueue &q,ElemType &e)
    {	if (q->front==q->rear)		//队空下溢出
    		return false;
    	q->front=(q->front+1)%MaxSize;
    	e=q->data[q->front];
    	return true;
    }
    

    (6) 求循环队列的长度

    int  QueueLength (SqQueue Q)
    {   
         return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;                        
     }
    

    queue容器

    #include<queue>
    q1.push(x): 将x接到队列的末端。
    q1.pop():弹出队列的第一个元素
    注意,并不会返回被弹出元素的值。
    q1.front():即最早被压入队列的元素。
    q1.back():即最后被压入队列的元素。
    q1.empty():当队列空时,返回true。
    q1.size():访问队列中的元素个数
    

    3.链队列

    typedef struct QNode{
       QElemType   data;
       struct Qnode  *next;
    }Qnode, *QueuePtr;
    typedef struct {
       QueuePtr  front;            //队头指针   
       QueuePtr  rear;             //队尾指针
    }LinkQueue;  
    

    队空条件:front=rear
    队满条件:不考虑
    进队e操作:将包含e的节点插入到单链表表尾
    出队操作:删除单链表首数据节点
    空队列:

    元素x入队列:

    元素y入队列:

    元素x出队列:

    基本运算:
    (1) 链队列初始化

    Status InitQueue (LinkQueue &Q){
       Q.front=Q.rear=new QNode; 
        if(!Q.front) exit(OVERFLOW);
        Q.front->next=NULL;
         return OK;
    }
    

    (2) 销毁链队列

    Status DestroyQueue (LinkQueue &Q){
       while(Q.front){
          Q.rear=Q.front->next;
          free(Q.front);
          Q.front=Q.rear;   }    
       return OK;
    }
    

    (3) 判断链队列是否为空

    Status QueueEmpty (LinkQueue Q){
        return (Q.front==Q.rear);                             
     }
    

    (4) 求链队列的队头元素

    Status GetHead (LinkQueue Q, QElemType &e){
       if(Q.front==Q.rear) return ERROR;
       e=Q.front->next->data;
       return OK;
    }
    

    (5) 链队列入队

    Status EnQueue(LinkQueue &Q,QElemType e){
        p=(QueuePtr)malloc(sizeof(QNode));
        if(!p) exit(OVERFLOW);
        p->data=e; p->next=NULL;
        Q.rear->next=p;
        Q.rear=p;
        return OK;
    }
    


    (6) 链队列出队

    Status DeQueue (LinkQueue &Q,QElemType &e){
       if(Q.front==Q.rear) return ERROR;
       p=Q.front->next;
       e=p->data;
       Q.front->next=p->next;
       if(Q.rear==p) Q.rear=Q.front;
       delete p;
       return OK;
    }
    


    4.双端队列
    (1)两端都可以进队和出队操作的队列。
    (2)队列的两端分别称为前端和后端,两端都可以入队和出队。
    (3)其元素的逻辑结构仍是线性结构。

    3.队列应用

    操作系统、售票系统、打印机、手机短信发送
    例子:迷宫问题
    记录走过的方块:

    typedef struct 
    {      int i,j;		//方块的位置
           int pre		//本路径中上一方块在队列中的下标
    }  Box;			//方块类型
    typedef struct
    {     Box data[MaxSize];
           int front,rear;	//队头指针和队尾指针
    }  QuType;		//定义顺序队类型
    

    求一条迷宫路径的算法:

    bool mgpath1(int xi,int yi,int xe,int ye)	//搜索路径为:(xi,yi)->(xe,ye)
    {      Box e;
           int i, j, di, i1, j1;
           QuType *qu;		//定义顺序队指针qu
           InitQueue(qu);		//初始化队列qu
           e.i=xi;  e.j=yi;   e.pre=-1;
           enQueue(qu,e);		//(xi,yi)进队
           mg[xi][yi]=-1;		//将其赋值-1,以避免回过来重复搜索
     while (!QueueEmpty(qu))		//队不空循环
           {	deQueue(qu,e);			//出队方块e
    	i=e.i;   j=e.j;
    	if (i==xe && j==ye)		//找到了出口,输出路径
    	{       print(qu,qu->front);	//调用print函数输出路径
    	        DestroyQueue(qu);		//销毁队列
    	        return true;			//找到一条路径时返回真
    	}
     for (di=0;di<4;di++)		//循环扫描每个方位
            {	switch(di)
    	{
    	case 0:i1=i-1; j1=j;   break;
    	case 1:i1=i;   j1=j+1; break;
    	case 2:i1=i+1; j1=j;   break;
    	case 3:i1=i;   j1=j-1; break;
    	}
    	if (mg[i1][j1]==0)
    	{     e.i=i1;  e.j=j1; 
    	      e.pre=qu->front;	
    	      enQueue(qu,e);	//(i1,j1)方块进队
    	      mg[i1][j1]=-1;	//将其赋值-1
    	}
             }
          }
          DestroyQueue(qu);		//销毁队列
          return false;
    }
    

    队列:解决广度优先搜索算法。
    迷宫路径:最优解

    1.2.谈谈你对栈和队列的认识及学习体会。

    栈和队列各有各的优点,各有各的缺点,在做栈和队列问题时,画图是必不可少的,画图能帮助我们理清做题的思路,方便求解题目。
    栈和队列感觉还有点不懂,应该再反复认真学习!

    2.PTA实验作业

    2.1 jmu-报数游戏

    2.1.1 代码截图


    2.1.2 本题PTA提交列表说明。


    部分正确:题目没看清,少了“!”。
    部分正确:中间多打了一个空格。

    2.2 jmu-ds-舞伴问题

    2.2.1 代码截图


    2.2.2 本题PTA提交列表说明。


    格式错误:少了一个空格。

    3.阅读代码

    3.1 用两个栈实现队列

    题目:
    用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
    解题代码:

    class CQueue {
        Stack<Integer> stack1;
        Stack<Integer> stack2;
        int size;
    
        public CQueue() {
            stack1 = new Stack<Integer>();
            stack2 = new Stack<Integer>();
            size = 0;
        }
        
        public void appendTail(int value) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
            stack1.push(value);
            while (!stack2.isEmpty()) {
                stack1.push(stack2.pop());
            }
            size++;
        }
        
        public int deleteHead() {
            if (size == 0) {
                return -1;
            }
            size--;
            return stack1.pop();
        }
    }
    

    3.1.1 该题的设计思路


    插入元素
    插入元素对应方法 appendTail
    如果 stack1 非空,则将 stack1 内的元素依次弹出并依次压入 stack2,直至 stack1 内的全部元素都被弹出
    将新元素 value 压入 stack1 内
    如果 stack2 非空,则将 stack2 内的元素依次弹出并依次压入 stack1,直至 stack2 内的全部元素都被弹出
    将 size 的值加 1
    时间复杂度:O(n)。
    空间复杂度:O(n)。

    删除元素
    删除元素对应方法 deleteHead
    如果 size 为 0,则队列为空,返回 -1
    如果 size 大于 0,则队列非空,将 size 的值减 1,从 stack1 弹出一个元素并返回
    时间复杂度:O(1)。
    空间复杂度:O(1)。

    3.1.2 该题的伪代码

    class CQueue {
    	Stack<Integer> stack1;//第一个栈
    	Stack<Integer> stack2;//辅助栈
    	int size;//队列元素数
    
    	public CQueue() {
    		初始化 stack1
    		初始化stack2
    		size = 0;//队列元素数开始为0
    	}
    
    	public void appendTail(int value) {
    		while (stack1不为空)
    			将stack1中新插入的元素push进stack2中
    		end while
    		新元素value入栈stack1
    		while (stack2非空)
    			将stack2中的元素再全部返回stack1中
    		end while
    		size++;
    	}
    
    	public int deleteHead() {
    		if 队列为空 
    			return -1;
    		end if
    		队列元素-1
    		return stack1.pop();
    	}
    }
    

    3.1.3 运行结果

    3.1.4分析该题目解题优势及难点。
    优势:
    一个栈存储元素,一个栈辅助操作。新插入的元素在第一个栈的底部,第一个栈内的其余元素的顺序和插入元素之前保持一致。大大节省了时间复杂度。
    难点:
    进行辅助操作和存储操作的两个栈的元素间的调换。

    3.2 根据身高重建队列

    题目:
    假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。

    注意:
    总人数少于1100人。
    解题代码:

    class Solution {
    public:
        vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
            // 先排序
            // [7,0], [7,1], [6,1], [5,0], [5,2], [4,4]
            
            // 再一个一个插入。
            // [7,0]
            // [7,0], [7,1]
            // [7,0], [6,1], [7,1]
            // [5,0], [7,0], [6,1], [7,1]
            // [5,0], [7,0], [5,2], [6,1], [7,1]
            // [5,0], [7,0], [5,2], [6,1], [4,4], [7,1]
            sort(people.begin(), people.end(), [](const vector<int>& a, const vector<int>& b) {
                if (a[0] > b[0]) return true;
                if (a[0] == b[0] && a[1] < b[1]) return true;
                return false;
            });
            
            vector<vector<int>> res;
            for (auto& e : people) {
                res.insert(res.begin() + e[1], e);
            }
            return res;
        }
    };
    

    3.2.1 该题的设计思路

    假设候选队列为 A,已经站好队的队列为 B.
    从 A 里挑身高最高的人 x 出来,插入到 B. 因为 B 中每个人的身高都比 x 要高,因此 x 插入的位置,就是看 x 前面应该有多少人就行了。比如 x 前面有 5 个人,那 x 就插入到队列 B 的第 5 个位置。

    时间复杂度:O(n)
    空间复杂度: O(1)

    3.2.2 该题的伪代码

    class Solution {
    public:
        vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), [](const vector<int>& a, const vector<int>& b) {
        先排序,按身高从高到矮;
        }
        vector<vector<int>> res;
            for (auto& e : people) {
               插入;
            }
    }
    

    3.2.3 运行结果

    3.2.4分析该题目解题优势及难点。

    难点:
    涉及多个c++容器,需要深入去了解这些容器的用法。
    优势:
    容易理清思路,不容易混淆。

  • 相关阅读:
    JQuery+ajax数据加载..........
    JQuery文本框验证
    将SqlDataReader 数据集转化为datatbale ,在将datatable 转化为iList
    DataSet转化为DataTable
    Case 降序升序排列
    Sql case
    sql STUFF 分组
    全/反选
    【面试题034】丑数
    【面试题033】把数组排成最小的数
  • 原文地址:https://www.cnblogs.com/201218zx/p/12548803.html
Copyright © 2020-2023  润新知