【归并排序】归并排序/逆序对的数量

简介: 【归并排序】归并排序/逆序对的数量

目录

算法思想

例题

题目:acwing.787. 归并排序

题目:acwing.787.


image.gif


算法思想

归并排序———分治(合二为一)

1.确定分界点(mid=(l+r)/2)

image.gif

2.递归排序左边和右边

image.gif

3.归并将左边和右边合二为一

image.gif


例题

题目:acwing.787. 归并排序

给定你一个长度为 n 的整数数列。

请你使用归并排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n个整数(所有整数均在 1∼1091∼109 范围内),表示整个数列。

输出格式

输出共一行,包含 n个整数,表示排好序的数列。

数据范围

1≤n≤100000

输入样例:

5
3 1 2 4 5
image.gif

输出样例:

1 2 3 4 5
image.gif

原题链接 :AcWing 787. 归并排序

#include<iostream>
using namespace std;
const int N = 1e6 + 10;//数据范围1≤n≤100000
int n;
int q[N], tmp[N];//tmp临时数组
void merge_sort(int q[], int l, int r)
{
  if (l >= r)
    return;
  int mid = l + r >> 1;//确定分界点(mid=(l+r)/2)
  merge_sort(q, l, mid);//递归排序左边
  merge_sort(q, mid + 1, r);//递归排序右边
  /*归并*/
  int k = 0, i = l, j = mid + 1;//i指向左边的起点,j指向右边的起点
  while (i <= mid && j <= r)
    if (q[i] <= q[j])   //左右比大小,小的存在临时数组中
      tmp[k++] = q[i++];
    else 
      tmp[k++] = q[j++];
  while(i<=mid) tmp[k++] = q[i++];
  while(j<=r)   tmp[k++] = q[j++];
  for (i = l, j = 0; i <= r; i++, j++)//将临时数组赋回有序数组
    q[i] = tmp[j];
}
int main()
{
   scanf("%d", &n);//输入n个数
  for (int i = 0; i < n; i++)
    scanf("%d", &q[i]);
  merge_sort(q, 0, n - 1);
  for (int i = 0; i < n; i++)
    printf("%d ", q[i]);
  return 0;
}

image.gif

题目:acwing.787.逆序对的数量

给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量逆序对的定义如下: 对于数列的第i个和第 j个元素,如果满足i< i且a [i]>a[j],则其为一个逆序对;否则不是。

输入格式

第一行包含整数n,表示数列的长度

第二行包含n 个整数,表示整个数列。

输出格式

输出一个整数,表示逆序对的个数。

数据范围

1 < n < 100000

数列中的元素的取值范围[1,10^9]

输入样例:

6
2 3 4 5 6 1
image.gif

输出样例:

5
image.gif

原题链接 :AcWing 788. 逆序对的数量

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1e6+10;//1 < n < 100000
int a[N], tmp[N];
LL merge_sort(int q[], int l, int r)
{
    if (l >= r) return 0;
    int mid = (l + r) >> 1; // 确定分界点
    LL res = merge_sort(q, l, mid) + merge_sort(q, mid + 1, r);
    /*归并*/
    int k = 0,i = l, j = mid + 1 ;
    while (i <= mid && j <= r)
    {
        if (q[i] <= q[j]) tmp[k++] = q[i++]; 
        else
        {
            res += mid - i + 1;
            tmp[k++] = q[j++];
        }
    }
    while (i <= mid) tmp[k++] = q[i++];
    while (j <= r) tmp[k++] = q[j++];
    for (int i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j];
    return res;
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &a[i]);
    LL res = merge_sort(a, 0, n - 1);
    cout << res << endl;
    return 0;
}

image.gif


image.gif

好了,本篇学习笔记就到此为止了,如有问题欢迎指正,感谢各位佬的支持!

相关文章
|
4天前
|
人工智能 算法
图解:求逆序对数量(归并排序的应用)
图解:求逆序对数量(归并排序的应用)
|
5月前
|
算法 搜索推荐 大数据
【算法】排序——归并排序和计数排序
上两篇文章讲解了插入排序、选择排序以及交换排序,每种类型的排序大类下都有一到两种排序,今天给大家带来的是归并排序,和前面几种排序一样都属于比较排序中的一种,是通过比较数组中的元素来实现排序的,还给大家带来一种非比较排序计数排序,让我们开始今天的排序之吧!!!
|
10月前
|
算法
【快速排序】快速排序/第k个数
【快速排序】快速排序/第k个数
|
存储 人工智能
归并排序例题——逆序对的数量
做道简单一点的题巩固一下
(归并排序)AcWing 788. 逆序对的数量
(归并排序)AcWing 788. 逆序对的数量
59 0
已知数据序列为(12,5,9,20,6,31,24),对该数据序列进行排序,写出插入排序、冒泡排序、快速排序、简单选择排序、堆排序以及二路归并排序每趟的结果。
已知数据序列为(12,5,9,20,6,31,24),对该数据序列进行排序,写出插入排序、冒泡排序、快速排序、简单选择排序、堆排序以及二路归并排序每趟的结果。
177 0
|
机器学习/深度学习 算法 API
算法排序5——归并排序&分治思想
算法排序5——归并排序&分治思想
90 0
算法排序5——归并排序&分治思想
|
算法 API 索引
算法排序6——快速排序(分治思想)
对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理
101 0
算法排序6——快速排序(分治思想)
|
搜索推荐 算法
7-273 插入排序还是归并排序 (25 分)
7-273 插入排序还是归并排序 (25 分)
101 0