对于一个序列(a1.a2,....an),如果某个下标对(i,j)满足 1<=i<j<=n,且ai>aj,则称其为该序列的一个逆序对。例如,序列(8,6,7)共有两个逆序对:(1,2).(1,3)。输入一个正整数序列(a1.a2、…an),请设计一个复杂度为 O(n*log n)的算法,输出该序列中逆序对的总个数。要求写出算法思想和伪代码(c语言),并说明该算法的正确性。
时间: 2023-02-28 13:34:11 浏览: 356
对于统计一个数列中逆序对的问题,可以使用归并排序来实现。该算法的思想是,先递归地将数列划分为两个子数列,再归并两个子数列,同时统计逆序对的数量。
以下是伪代码:
int count = 0;
void merge_sort(int arr[], int l, int r)
{
if (l >= r) return;
int mid = (l + r) / 2;
merge_sort(arr, l, mid);
merge_sort(arr, mid + 1, r);
int i = l, j = mid + 1;
while (i <= mid && j <= r)
{
if (arr[i] <= arr[j])
{
i++;
}
else
{
count += mid - i + 1;
j++;
}
}
}
该算法的正确性在于,归并排序的过程比较两个数的大小,并将较小的数放入新数组中,这也是统计逆序对的前提。因此,在归并过程中,如果出现了arr[i] > arr[j]
的情况,说明从i
到mid
的所有数都大于arr[j]
,因此逆序对的个数为mid - i + 1
。
相关问题
写一个C语言程序实现给定标识符集(a1, a2, …an),这些字符的下标从1开始按自然序编号,pi是对ai成功检索的概率, qi是不成功检索的概率, 且∑(1<=i<=n)pi +∑(0<=i<=n)qi =1,问:它的最优二分检索树是怎样的? 输入格式: 第1行是n,表示字符个数; 第2行是这n个字符的成功检索概率pi, 0<pi<1; 第3行是失败检索概率qi,0<qi<1,且∑(1<=i<=n)pi +∑(0<=i<=n)qi =1。 输出格式: 最优二分检索树先根遍历时得到的字符编号序列。 输入样例1: 4 0.1875 0.1875 0.0625 0.0625 0.125 0.1875 0.0625 0.0625 0.0625 输出样例1: 2 1 3 4
这是一个经典的动态规划问题,可以使用动态规划求解最优二分检索树。
具体的思路是,首先对于每一个子树,我们计算出其所有节点的概率之和,然后根据这个概率之和来计算其对应的最小代价。由于最终的二分检索树的根节点可能是任何一个节点,我们需要对于每一个可能的根节点都进行一次计算,并选取其中代价最小的一颗子树作为最终的答案。
具体的实现可以参考下面的 C 语言代码:
用C语言完成如下题目的代码:1 最优二分检索树问题 分数 100 作者 李丽娜 单位 吉林大学 给定标识符集(a1, a2, …an),这些字符的下标从1开始按自然序编号,pi是对ai成功检索的概率, qi是不成功检索的概率, 且∑(1<=i<=n)pi +∑(0<=i<=n)qi =1,问:它的最优二分检索树是怎样的? 输入格式: 第1行是n,表示字符个数; 第2行是这n个字符的成功检索概率pi, 0<pi<1; 第3行是失败检索概率qi,0<qi<1,且∑(1<=i<=n)pi +∑(0<=i<=n)qi =1。 输出格式: 最优二分检索树先根遍历时得到的字符编号序列。 输入样例1: 4 0.1875 0.1875 0.0625 0.0625 0.125 0.1875 0.0625 0.0625 0.0625 输出样例1: 2 1 3 4 输入样例2: 5 0.1524 0.1369 0.0179 0.0007 0.3081 0.1567 0.1022 0.0682 0.0476 0.0084 0.0009 输出样例2: 2 1 5 3 4
以下是最优二分检索树问题的C语言代码实现,使用了动态规划算法:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_N 100
int n;
double p[MAX_N + 1];
double q[MAX_N + 1];
double w[MAX_N + 1][MAX_N + 1];
double e[MAX_N + 1][MAX_N + 1];
int root[MAX_N + 1][MAX_N + 1];
void optimal_bst() {
int i, j, r, k;
for (i = 1; i <= n + 1; i++) {
w[i][i - 1] = q[i - 1];
e[i][i - 1] = q[i - 1];
}
for (r = 0; r <= n; r++) {
for (i = 1; i <= n - r + 1; i++) {
j = i + r - 1;
w[i][j] = w[i][j - 1] + p[j] + q[j];
e[i][j] = INT_MAX;
for (k = i; k <= j; k++) {
double t = e[i][k - 1] + e[k + 1][j] + w[i][j];
if (t < e[i][j]) {
e[i][j] = t;
root[i][j] = k;
}
}
}
}
}
void print_optimal_bst(int i, int j) {
if (i <= j) {
int r = root[i][j];
printf("%d ", r);
print_optimal_bst(i, r - 1);
print_optimal_bst(r + 1, j);
}
}
int main() {
int i;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%lf", &p[i]);
}
for (i = 0; i <= n; i++) {
scanf("%lf", &q[i]);
}
optimal_bst();
print_optimal_bst(1, n);
printf("\n");
return 0;
}
运行程序,输入样例即可得到输出结果。
相关推荐












