算法第4章实践报告
1.实践题目
7-1 最优合并问题
2.问题描述
给定k 个排好序的序列, 用 2 路合并算法将这k 个序列合并成一个序列。 假设所采用的 2 路合并算法合并 2 个长度分别为m和n的序列需要m+n-1 次比较。试设 计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。 为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
输入格式:
第一行有 1 个正整数k,表示有 k个待合并序列。 第二行有 k个正整数,表示 k个待合并序列的长度。
输出格式:
输出最多比较次数和最少比较次数。
输入样例:
在这里给出一组输入。例如:
4
5 12 11 2
输出样例:
在这里给出相应的输出。例如:78 52
3.算法描述
最少比较次数类似于哈夫曼编码,最开始找长度最小的2个序列进行合并,合并后的序列与尚未进行合并的序列一起进行比较,从中再次找出长度最小的两个序列进行合并。然后重复上述操作,直到最终合并成一个序列为止。最多比较次数刚好相反。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int k;
cin>>k;
int a[k],b[k];
for(int i=0;i<k;i++)
{
cin>>a[i];
}
sort(a,a+k);
for(int i=k-1,j=0;i>=0;i--,j++)
{
b[j]=a[i];
}
int sum1=0,sum2=0;
for(int i=0;i<k-1;i++)
{
a[i+1]=a[i]+a[i+1];
sum1+=a[i+1];
sort(a+i,a+k);
}
for(int j=0;j<k-1;j++)
{
b[j+1]=b[j]+b[j+1];
sum2+=b[j+1];
}
cout<<sum2-k+1<<" ";
cout<<sum1-k+1<<endl;
return 0;
}
4.时间、空间复杂度分析
时间复杂度:由于每次合并生成的新序列都要和尚未合并的序列进行比较,找出长度最小的两个序列,所以每次都需要排序O(nlogn),重复n次,所以时间复杂度是(n^2logn)。
空间复杂度:开了2个大小为n的数组,所以是O(n)。
5.心得体会
上课时做不出第2题的时候,应该静下心来看一下这一题的,毕竟贪心策略显而易见,代码实现也很简单。以后做题要把心静下来,不要急躁,不要把原来应该解出来的题目都浪费了。