第一题:
消消乐
时间限制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)**完全没用到任何的栈或者链这类复杂数据结构。这样做题最快而且最方便。