百度空间 | 百度首页 
 
查看文章
 
《算法导论》课程的题目分析——判定是否存在两数字和为x(P37 2.3-7) 之二
2008-03-27 19:51

算法分析:这个第二个算法是通过归并排序的原理来实现的,首先我们把数组二分成两个部分,我们采用递归判定左右两个部分内部是否有和为x的元素,如果有直接输出就可以了,否则的话我们考虑这样的情况:一个元素在左边,一个元素在右边,他们的和为x!此时就类似一算法的方法了,因为归并他是建立在前面已经操作的计算:分别对左右两个部分排好序,然后进行合并!这样我们类似一算法设置两个指针,一个指向左边的开始,一个指向右边的结尾,我们开始同样的过程:判断两个指针的指点的和,等于x的话表明已经找到了要求,退出;否则如果大于x表示右边数值太大,右指针向左移动;如果小于x表示左边数值太小,左指针向右移动,这样子就能一直执行这样的过程。

复杂度分析:由于执行的归并排序的过程,而且检索的时间复杂度和Merge的过程是一样的,因此综合分析来他的情况和归并排序是一样的!即时间复杂度为O(nlogn),附加空间复杂度为O(n)。

实现代码:

#include<stdio.h>
#include<memory.h>
const int MAXN=5000;
int n,x,y,i,j,a[MAXN],b[MAXN];
bool MergeSort(int f,int t)
{
if (f>=t) return false;
int mid=(f+t)>>1,i,j,l;
if (MergeSort(f,mid)||MergeSort(mid+1,t)) return true;
for (i=f,j=t;i<=mid&&j>mid;)
   if (a[i]+a[j]==x)
   {
    y=a[i];
    return true;
   }
   else if (a[i]+a[j]>x) j--;
   else i++;
for (i=f,j=mid+1,l=0;i<=mid&&j<=t;)
   if (a[i]<a[j]) b[l++]=a[i++];
   else b[l++]=a[j++];
while (i<=mid) b[l++]=a[i++];
while (j<=t) b[l++]=a[j++];
memcpy(a+f,b,(t-f+1)*sizeof(a[0]));
return false;
}
int main()
{
scanf("%d",&n);
scanf("%d",&x);
for (i=0;i<n;i++)
   scanf("%d",&a[i]);
if (MergeSort(0,n-1)) printf("%d %d\n",y,x-y);
else printf("No Answer!\n");
return 0;
}

测试数据:同算法一中,效果还不错

说明:这个算法的时间复杂度不错,可是有附加空间,与经过优化的算法一有一定的差距,但是思想很不错


类别:算法 | 添加到搜藏 | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu