答:
a.
插入排序的最坏时间复杂度为,对一个长度为的子表进行排序需要最坏需要时间,那么排序个子表需要的时间。
b.
归并排序先对数组进行对半拆分,需要拆分次,现在当拆分到数组的长度为时,停止拆分,然后使用插入排序对这个子数组进行排序,然后归并排序开始合并,所以拆分的次数从减少至 - = ,合并的时间复杂度为,所以总时间复杂度为。
c.
若要使修改后具有相同的运行时间,需要,得到,所以,当时,修改后的算法运行时间为,也就是只要引入插入排序,其运行时间总要大于标准的归并排序(这里是忽略了常数因子还有机器的影响)。但如果借助记号,那么只要是常数,那么跟的渐进性是相同的。
d.
在实践中,该数的大小跟被记号隐藏的常数因子的大小与机器的影响有关,而且该数应该是个常数,所以可以尝试各种的数值,然后对比其运行时间,通过足够多的尝试来决定的数值。
答:
a.
我们需要证明。
b.
第2 ~ 4行代码的作用是把小的元素与上一个元素交换,直到循环终止,最小的元素在的位置上。
- 初始化:在未进行迭代之前,最小元素最多位于上,该结论为真。
- 保持:在每次迭代,如果当前元素比上一个元素小,便交换其位置,如果大,便什么都不做。所以在第次迭代之后,都可以确定最小元素的位置至多在。
- 终止:在循环结束时,也就是时,此时,最小元素在的位置上。
c.
- 初始化:在迭代之前,子数组为,此时子数组包含0个元素。
- 保持:在第次迭代后,根据b的结论,第小的元素会在的位置上,所以在第次迭代之前,子数组是有序的,然后此次迭代之后,子数组是有序的。
- 终止: 当时,循环终止,此时子数组是有序的,且比小,所以该数组有序。
d.
冒泡排序中,2 ~ 4行代码无论如何都需要进行次循环,所以时间复杂度为,而且必需进行次循环,所以他的时间复杂度为。冒泡排序是稳定性的排序,其最坏时间复杂度与最好时间复杂度都为。而插入排序的最好时间复杂度为。
答:
a.
实现以上代码片段的运行时间为。
b.
循环内部需要对取次方,也就是每次循环需要次乘法跟一次加法,一共要进行次循环,所以其运行时间为。与霍纳规则相比,朴素算法的每次迭代都要比霍纳规则多次乘法,因为朴素算法要求,所以其性能要比霍纳算法差得多。
c.
**初始化:**当时,,所以。
**保持:**在本次的循环开始,有:
当本次循环结束时:
当下次循环开始时,有,有
所以在下次循环开始时,也有:
**终止:**当循环终止时,有,此时
d.
从c中的结论可以看出该代码片段是正确的。
a.
b.
当数组是一个递减的数组时具有最多的逆序对,具有。
c.
从插入排序的伪代码中可以看出,插入排序的运行时间取决于5~7行代码的循环次数,在每次进行while循环时,只要前面有多少个数比当前的key大,便要进行多少次循环,所以每次循环的次数是子数组的逆序对的个数。所以while循环总的运行时间为为逆序对的个数,那么总插入排序总的运行时间为。
d.
private static int getPairCountEachPart(int[] a, int p, int q, int r, int count) {
int[] left = new int[q - p + 1];
int[] right = new int[r - q];
for (int i = 0; i < left.length; i++) {
left[i] = a[p + i];
}
for (int j = 0; j < right.length; j++) {
right[j] = a[q + j + 1];
}
int i = 0, j = 0;
while (p <= r) {
if (left[i] <= right[j]) {
a[p++] = left[i++];
if (i == left.length) {
for (;j < right.length; j++) {
a[p++] = right[j];
}
break;
}
} else {
a[p++] = right[j++];
count += left.length - i;
if (j == right.length) {
for (;i < left.length; i++) {
a[p++] = left[i];
}
break;
}
}
}
return count;
}
public static int getSequencePairCount(int[] a) {
return getSequencePairCount(a, 0, a.length - 1);
}
public static int getSequencePairCount(int[] a, int p, int r) {
int left = 0, right = 0;
if (p < r) {
int q = (p + r) / 2;
left = getSequencePairCount(a, p, q);
right = getSequencePairCount(a, q + 1, r);
if (a[q] <= a[q + 1]) {
return left + right;
}
return getPairCountEachPart(a, p, q, r, left + right);
}
return 0;
}