FOJ 1664 Top K different numbers

本文通过解决一个具体的在线评测题目,详细介绍了合并排序(MergeSort)与快速排序(QuickSort)的实现方法及其应用。同时对比了两种排序算法的时间复杂度,并分享了在实际编程中遇到的问题及解决过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2010-11-21  22:46:04

题目地址:http://acm.fzu.edu.cn/problem.php?pid=1664

       通过这道题目学会了使用 合并排序(MergeSort) 与 快速排序(QuickSort),可是关于一个算法的最坏时间复杂度与平均时间复杂度仍然是+_++_+的,MergeSort最坏复杂度与平均复杂度为O(nlogn),QuickSort最坏复杂度为O(n^3),平均复杂度为O(nlogn)。。。

       我的MergeSort错误代码:


#include<stdio.h>
int Merge(int *p1,int *p2,int n,int mid)
{
    int i,j,k;
    k=i=0; j=mid;
    while(i<mid&&j<n)
    { if(*(p1+i)>*(p2 +j))    ///  p2应该为 p1
       { *(p2+k)=*(p1+j); j++;}
      else {*(p2+k)=*(p1+i);i++;}
      k++;
    }
    if(i==mid)
       for(;j<n;j++,k++) *(p2+k)=*(p1+j);
    else
       for(;i<mid;i++,k++) *(p2+k)=*(p1+i);
    return 0;
}
int MergeSort(int *p1,int *p2,int n)
{
    int mid=n/2;
    if(n>1)
    {
           MergeSort(p2,p1,mid);
           MergeSort(p2+mid,p1+mid,n-mid);
           Merge(p1,p2,n,mid);
    }
    return 0;
}
int main()
{
    int n,k,flag,i,a[10001]={0},b[10001]={0};
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i=1;i<n+1;i++)
           {scanf("%d",&a[i]); b[i]=a[i];}
        if(n%2) MergeSort(a,b,n+1);
        else    MergeSort(a+1,b+1,n);
   ////  其实不必考虑到序列个数n是偶数还是奇数
        flag=1;
        for(i=n-1;i>0;i--)
           if(a[i]!=a[i+1])
           {
              flag++;
              if(flag>=k) break;
           }
                                               /////   该程序段应该在k>1的情况下才执行的,否则k=1时,执行完该程序段后flag=2
        if(flag>=k)
        {
          printf("%d",a[i]);
          for(i++;i<n+1;i++)
            if(a[i]!=a[i-1])
              printf(" %d",a[i]);
       //// 由上面可知,应分k=1与k>1两种情况,k=1输出a[n],k>1时,执行该程序段
        }
        else printf("-1");
        printf("/n");
    }
    return 0;

}


尽管改了上述错误后,似乎仍是不能AC,不知道哪里还有错,最后不考虑序列个数n的奇偶性,然后经过相关调整后,终于是AC 了


#include<stdio.h>
int Merge(int *p1,int *p2,int n,int mid)
{
    int i,j,k;
    k=i=0; j=mid;
    while(i<mid&&j<n)
    { if(*(p1+i)>*(p1+j))
       { *(p2+k)=*(p1+j); j++;}
      else {*(p2+k)=*(p1+i);i++;}
      k++;
    }
    if(i==mid)
       for(;j<n;j++,k++) *(p2+k)=*(p1+j);
    else
       for(;i<mid;i++,k++) *(p2+k)=*(p1+i);
    return 0;
}
int MergeSort(int *p1,int *p2,int n)
{
    int mid=n/2;
    if(n>1)
    {
           MergeSort(p2,p1,mid);
           MergeSort(p2+mid,p1+mid,n-mid);
           Merge(p1,p2,n,mid);
    }
    return 0;
}
int main()
{
    int n,k,flag,i,a[10000],b[10000];
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i=0;i<n;i++)
           {scanf("%d",&a[i]); b[i]=a[i];}
        MergeSort(a,b,n);
        flag=1; i=n-1;
        while(flag<k&&i>0)           /////+_+刚开始是i>=0又得到了个WA  +_+
        {
           i--;
           if(b[i]!=b[i+1]) flag++;

        }
        if(flag>=k)
        {
           printf("%d",b[i]);
           for(i++;i<n;i++)
             if(b[i]!=b[i-1])
               printf(" %d",b[i]);
        }
        else printf("-1");
        printf("/n");
   }
    return 0;

}


下面是用了QSort 的AC代码:


#include<stdio.h>
void swap(int *p1,int *p2)
{
     int temp;
     temp=*p1;*p1=*p2;*p2=temp;
}
int FindPivot(int *p,int n)
{
    int i;
    for(i=1;i<n;i++)
      {  if(*p>*(p+i)) return 0;
         if(*p<*(p+i)) return i;
      }
      return -1;
}
int Partition(int *p,int n,int Pivot)
{
    int left=0,right=n-1;
    do
    {
        swap(p+left,p+right);
        while(*(p+left)<Pivot) left++;
        while(*(p+right)>=Pivot) right--;
    } while(left<right);
    return left;
}
void QSort(int *p,int n)
{
     int PivotIndex,k;
     if(n>1)
     {
            PivotIndex=FindPivot(p,n);
            if(PivotIndex>-1)
            {
               k=Partition(p,n,*(p+PivotIndex));
               QSort(p,k);
               QSort(p+k,n-k);
            }
     }
}


int main()
{
    int n,k,flag,i,a[10000];
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i=0;i<n;i++)
           scanf("%d",&a[i]);
        QSort(a,n);
        flag=1;
        if(n>1&&k>1)
        {
          for(i=n-2;i>=0;i--)
            if(a[i]!=a[i+1])
            {
              flag++;
              if(flag>=k) break;
            }
          }
        if(flag>=k)
        {
          if(k==1) printf("%d",a[n-1]);
          else
          {
           printf("%d",a[i]);
           for(i++;i<n;i++)
             if(a[i]!=a[i-1])
               printf(" %d",a[i]);
          }
        }
        else printf("-1");
        printf("/n");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值