归并排序

115 阅读1分钟

模板

  • C++
void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int mid = l + r >> 1;
    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 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];
}
  • Java
public static void merge_sort(int q[], int l, int r) {
    if (l >= r) {
        return;
    }
    
    int mid = l + r >> 1;
    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 {
            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];
    }
    
}

练习

01 归并排序

  • 题目

Snipaste_2023-01-14_20-31-41.png

  • 题解
import java.io.*;

public class Main {
    public static final int N = 100010;
    public static int[] q = new int[N];
    public static int[] tmp = new int[N];

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] strs = br.readLine().split(" ");
        for (int i = 0; i < n; i++) {
            q[i] = Integer.parseInt(strs[i]);
        }
        br.close();
        merge_sort(q, 0, n - 1);
        for (int i = 0; i < n; i++) {
            System.out.print(q[i] + " ");
        }
    }

    public static void merge_sort(int[] q, int l, int r) {
        if (l >= r) {
            return;
        }

        int mid = l + r >> 1;
        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 {
                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];
        }
    }
}

02 逆序对的数量

  • 题目

Snipaste_2023-01-14_21-22-10.png

  • 题解

思路讲解:AcWing 788. 逆序对的数量 - AcWing

import java.io.*;

public class Main {
    public static final int N = 100010;
    public static int[] q = new int[N];
    public static int[] tmp = new int[N];

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] strs = br.readLine().split(" ");
        for (int i = 0; i < n; i++) {
            q[i] = Integer.parseInt(strs[i]);
        }
        br.close();
        System.out.print(merge_sort(q, 0, n - 1));

    }

    public static long merge_sort(int[] q, int l, int r) {
        if (l >= r) {
            return 0;
        }

        int mid = l + r >> 1;
        long 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 {
                tmp[k++] = q[j++];
                res += mid - i + 1;
            }
        }

        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];
        }

        return res;
    }
}