归并排序图解
将一个序列变为升序序列
#include<iostream>
using namespace std;
int tem[100010],num[100010];
void sort( int l, int r)
{
if (l >= r)return;/终止条件
int mid = (l + r) / 2;//每次取中间
sort(l, mid), sort(mid + 1, r);//logn时间复杂度直到只剩不能在分割的单个子区间
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)//双指针指向当前两个序列头
{
if (num[i] < num[j])tem[k++] = num[i++];//将较小的排在前面
else tem[k++] = num[j++];
}
while (i <= mid)tem[k++] = num[i++];//如果还有剩下的数,接着排
while (j <= r)tem[k++] = num[j++];
for (int i = l, j = 0; i <= r; i++, j++)//复制到答案数组
{
num[i] = tem[j];
}
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> num[i];
sort( 0, n - 1);
for (int i = 0; i < n; i++)
{
cout << num[i] << " ";
}
return 0;
}
总结:
相较于快排可以解决逆序对问题`
给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。
逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。
输入格式
第一行包含整数 n,表示数列的长度。
第二行包含 n 个整数,表示整个数列。
输出格式
输出一个整数,表示逆序对的个数。
数据范围
1≤n≤100000
输入样例:
6
2 3 4 5 6 1
输出样例:
5
#include<iostream>
using namespace std;
int num[100010], tem[100010];
long long sort(int l, int r)
{
if (l >= r) return 0;
int mid = l + r >> 1;
long long res = sort(l, mid) + sort(mid + 1, r);
int i = l, k = 0, j = mid + 1;
while (i <= mid && j <= r)
{
if (num[i] <= num[j])tem[k++] = num[i++];//num[i]为下标较小数组
else
{
tem[k++] = num[j++];
res += mid - i + 1;//前方已经排好序,mid-i+1即为j的个数
}
}
while (i <= mid)tem[k++] = num[i++];
while (j <= r)tem[k++] = num[j++];
for (int i = l, j = 0; i <= r; i++, j++)
num[i] = tem[j];
return res;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
cout << sort(0, n - 1);
}