算法设计与分析——4
第四章实验报告
4-3 最优合并问题
给定k个排好序的序列,用2路合并算法将这k个序列合并成一个序列。假设所采用的2路合并算法合并 2 个长度分别为m和n的序列需要m+n-1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。 为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
输入格式:第一行有 1 个正整数k,表示有 k个待合并序列。 第二行有 k个正整数,表示 k个待合并序列的长度。
输出格式:输出最多比较次数和最少比较次数。
输入样例:4 // 5 12 11 2
输出样例:78 52
2. 算法描述
主要思路:合并k个序列,需要合并k-1次,每次合并的比较次数取决于俩序列长度和。贪心策略为,比较次数最多,即每次尽可能选择长度最大两序列进行合并,比较次数最少,即每次尽可能选择长度最小两序列进行合并。使用替换法证明,若合并时选择的非长度最大/最小,则总是存在更优的选择方法是比较次数更多/更少,因此该贪心策略成立。
int MinSum(int a[], int n) {
int min_sum = 0; //存放比较总次数
for (int i = 0; i < n-1; i++) {
sort(a, a + n); //排序
a[i+1] = a[i] + a[i+1]; //总选择最小两个(非最前两个需要除去前方的0)相加赋给其中一个
a[i] = 0; //另外一个置为零
min_sum += a[i+1] - 1; //更新比较次数
}
return min_sum;
}
int MaxSum(int b[], int n) {
int max_sum = 0; //存放比较总次数
for (int i = 0; i < n-1; i++) {
sort(b, b + n); //排序
b[n-2] = b[n-2] + b[n-1]; //总选择最大两个(最后两个)相加赋给其中一个
b[n-1] = 0; //另外一个置为零
max_sum += b[n-2] - 1; //更新比较次数
}
return max_sum;
}
3. 时间复杂度分析
需要合并n-1次,每次都需要进行排序,更新序列长度以及比较次数,整个问题的时间复杂度为O(n^2*logn)。
4. 心得体会
此类问题最重要的、难点就在于贪心算法的选择,我们在选择贪心算法时,需要多个方面兼顾考虑,不能全靠感觉和常识,需要进一步的考虑。区分贪心算法问题和动态规划问题之间的不同,选择合适的策略解决问题。