剑指offer——数组的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

算法思路:

将数组分成子数组,使左右数组均有序、如果左数组中一元素大于右数组某一元素,说明左数组其余元素都大于右数组的当前元素,此时产生左数组剩下元素数量的逆序对。

当左数组某一个元素大于右数组某一个元素时,如何统计左数组剩下的元素数量?:mid - p1 + 1

相等时先把左数组元素放入辅助数组,因为逆序对的条件是大于。

public class ReverseCount {
    //暴力法:从第一个元素跟后面元素进行比较,如果大于 计数器加1
    public static void forReverseConut(int[] arr) {
        int count = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                    count++;
                }
            }
        }
        System.out.println("数组中逆序对的数量:" + count);
    }

    //归并排序思想
    public static int mergeReverseCount(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        return process(arr, 0, arr.length - 1);
    }

    public static int process(int[] arr, int L, int R) {
        if (L == R) {
            return 0;
        }
        int mid = L + ((R - L) >> 1);
        return process(arr, L, mid) + process(arr, mid + 1, R) + merge(arr, L, mid, R);
    }

    public static int merge(int[] arr, int l, int mid, int r) {
        int[] help = new int[r - l + 1];
        int i = 0;
        int p1 = l;
        int p2 = mid + 1;
        int count=0;
        while (p1 <=mid && p2 <= r){
            count += arr[p1] > arr[p2] ? (mid - p1 +1) : 0;
            help[i++] = arr[p1] <= arr[p2] ? arr[p1++]:arr[p2++];
        }
        while (p1<=mid){
            help[i++] = arr[p1++];
        }
        while (p2<=r){
            help[i++] = arr[p2++];
        }
        for (i =0;i<help.length;i++){
            arr[l+i] = help[i];
        }
        return count;
    }

    public static int[] getRandomArray(int size, int value) {
        //设置数组长度
        int[] arr = new int[size];
        for (int i = 0; i < arr.length; i++) {
            //为数组生成随机数 范围 [0-value]
            arr[i] = (int) ((Math.random() * (value + 1)));
        }
        return arr;
    }
    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    public static void main(String[] args) {
        int[] randomArray = getRandomArray(50, 50);
        int[] randomArray1 = copyArray(randomArray);
        forReverseConut(randomArray);
        System.out.println(mergeReverseCount(randomArray1));

    }
}

 

使用随即数组调用两种方法产生的结果:

     

posted @ 2020-07-10 16:37  硬盘红了  阅读(114)  评论(0编辑  收藏  举报