腾讯2019技术岗笔试 消消乐 小Q有n个数字,每次小Q 选择任意两个不相同数字,并同时删去他们,最后问你能不能删完。

第一题:

消消乐
时间限制2s,其他语言:4s

小Q有n个数字,每次小Q 选择任意两个不相同数字,并同时删去他们,最后问你能不能删完。
输入描述:
第一行数字T,表示数据组数,对于每组数据,第一行一个数字,表示数字个数,N一定是偶数,接下来一行N个数AI,表示这些数字,满足2<=N<=1000000,1<=Ai<=N.
输出描述:
对于每一组数据,输出Yes或者No表示是否可以删除所有的数字。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路1:链表,最后链表为空了,就可以消除,链表不是空,就是不可以消除。
下面代码打印了全部的思路:
例:
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

typedef struct link* node;
typedef struct link link;
struct link
{
    int val;
    node next;
    node before;
};

int main()
{
    int num=0;
    scanf("%d",&num);
    int i=0;
    printf("sizeof(LinkList);%d,sizeof(node):%d\n",sizeof(link),sizeof(node));
    node head=(node)malloc(sizeof(link));
    head->val=-1;
    head->before=NULL;
    head->next=NULL;
    node tmp=head;
    for(i=0; i<num; i++)
    {
        int val=0;
        scanf("%d",&val);
        node next=(node)malloc(sizeof(link));
        next->val=val;
        next->next=NULL;
        next->before=tmp;
        printf("tmp:%d next:%d,val:%d,next->before:%d\n",tmp,next,tmp->val,next->before);
        tmp->next=next;
        tmp=next;
    }
    tmp=head->next;
    while(tmp!=NULL)
    {
        printf("%d  ",tmp->val);
        tmp=tmp->next;
    }
    printf("\n");
    tmp=head->next;
    node next=tmp->next;
    int flag=0;
    while(next!=NULL)
    {
        if(tmp->val!=next->val)
        {
            printf("  删除%d和%d  \n",tmp->val,next->val);
            if(next->next!=NULL)
            {
                printf("  修改%d的next为%d  \n",next->before->next->val,next->next->val);
                next->before->next=next->next;
                printf("  修改%d的before%d  \n",next->next->before->val,next->before->val);
                next->next->before=next->before;
                tmp->before->next=tmp->next;
                tmp->next->before=tmp->before;
                tmp=tmp->next;
                next=tmp->next;//next指针从头开始遍历。
            }
            else if(next->next==NULL&&tmp->next==next)//如果最后链表上只剩下了两个,相邻而且不相同。
            {
                printf("YES\n");
                head->next=NULL;
                next=NULL;
                flag=1;
            }
            else if(next->next==NULL&&tmp->next!=next)//链表前面的都相同,只有最后一个和第一个不相同。
            {
                printf("  修改%d的next为NULL  \n",next->before->next->val);
                next->before->next=NULL;
                tmp->before->next=tmp->next;
                tmp->next->before=tmp->before;
                tmp=tmp->next;
                next=tmp->next;//next指针从头开始遍历。
            }
        }
        else
        {
            next=next->next;
        }
    }
    if(flag==0){
        printf("NO\n");
    }

    /**
    打印剩下的链表上的内容来看看
    **/
    tmp=head->next;
    while(tmp!=NULL)
    {
        printf("%d  ",tmp->val);
        tmp=tmp->next;
    }

    return 0;
}


加一个外部循环,修改一下输出格式即可满足题意。

#include <stdio.h>
#include <stdlib.h>

typedef struct link* node;
typedef struct link link;
struct link
{
    int val;
    node next;
    node before;
};

int main()
{
    int group=0;
    scanf("%d",&group);
    int k=0;

    for(k=0; k<group; k++)
    {
        int num=0;
        scanf("%d",&num);
        int i=0;
        //printf("sizeof(LinkList);%d,sizeof(node):%d\n",sizeof(link),sizeof(node));
        node head=(node)malloc(sizeof(link));
        head->val=-1;
        head->before=NULL;
        head->next=NULL;
        node tmp=head;
        for(i=0; i<num; i++)
        {
            int val=0;
            scanf("%d",&val);
            node next=(node)malloc(sizeof(link));
            next->val=val;
            next->next=NULL;
            next->before=tmp;
            //printf("tmp:%d next:%d,val:%d,next->before:%d\n",tmp,next,tmp->val,next->before);
            tmp->next=next;
            tmp=next;
        }
        tmp=head->next;
        while(tmp!=NULL)
        {
            //printf("%d  ",tmp->val);
            tmp=tmp->next;
        }
        //printf("\n");
        tmp=head->next;
        node next=tmp->next;
        int flag=0;
        while(next!=NULL)
        {
            if(tmp->val!=next->val)
            {
                //printf("  删除%d和%d  \n",tmp->val,next->val);
                if(next->next!=NULL)
                {
                    //printf("  修改%d的next为%d  \n",next->before->next->val,next->next->val);
                    next->before->next=next->next;
                    //printf("  修改%d的before%d  \n",next->next->before->val,next->before->val);
                    next->next->before=next->before;
                    tmp->before->next=tmp->next;
                    tmp->next->before=tmp->before;
                    tmp=tmp->next;
                    next=tmp->next;
                }
                else if(next->next==NULL&&tmp->next==next)
                {
                    printf("YES\n");
                    head->next=NULL;
                    next=NULL;
                    flag=1;
                }
                else if(next->next==NULL&&tmp->next!=next)
                {
                    //printf("  修改%d的next为NULL  \n",next->before->next->val);
                    next->before->next=NULL;
                    tmp->before->next=tmp->next;
                    tmp->next->before=tmp->before;
                    tmp=tmp->next;
                    next=tmp->next;
                }
            }
            else
            {
                next=next->next;
            }
        }
        if(flag==0)
        {
            printf("NO\n");
        }

        tmp=head->next;
        while(tmp!=NULL)
        {
            //printf("%d  ",tmp->val);
            tmp=tmp->next;
        }

    }



    return 0;
}

思路2:
只要出现次数最多的那一个数的出现次数小于等于一半就是YES,否则NO

比如:1 1 1 1 1 1 3 3 3 3 4 4

时间复杂度O(1):
扫描数组一次,遇到一个值就计数i=1;如果下一个不是这个值就i减一,如果是这个值就加一;从而有扫描完全组,倘若i>=1说明这个数是主元素。因为如果出现次数大于一半,i的值就一定大于1,请你仔细品品。

** 空间复杂度也是O(1)**完全没用到任何的栈或者链这类复杂数据结构。这样做题最快而且最方便。

发布了140 篇原创文章 · 获赞 114 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qinglingLS/article/details/100252139