统计数组中的逆数对个数

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

输入: [7,5,6,4]
输出: 5

限制:

0 <= 数组长度 <= 50000

方法一、暴力破解,使用冒泡算法思维,遍历数组和每一个元素后面的数字比较,时间复杂段O(n*n),不需要额外开辟数组空间,空间复杂度O(1)。

方法二、使用归并排序的算法思维进行比较统计,采用了二分的迭代方式,复杂度是 logn,每次的迭代,需要对两个有序数组进行合并,这样的动作的时间复杂度是 O(n) ,因此,总的复杂度就是二者的乘积 O(nlogn),每次合并的操作都需要开辟基于数组的临时内存空间,所以空间复杂度为 O(n)。

方法一实现代码:

public int getCountByBubble(int[] arr){
        int bubble_count = 0;
        for(int i = 0; i < arr.length-1;i++) {
            for(int j = i+1; j < arr.length; j++) {
                if(arr[i] > arr[j])
                    bubble_count++;
            }
        }
        return bubble_count;
    }

方法二实现代码:

public class ArrTest {

    public static int count = 0;
 
    /**
     * 统计数组逆数对个数
     * 归并思想统计,计算时间复杂度O(nlogn),空间复杂度O(n)
     * @param arr
     * @return
     */
    public int getCountByMerge(int[] arr){
        int[] tmp = new int[arr.length];
        customMergeSort(arr,tmp,0,arr.length-1);
        return count;
    }

    public void customMergeSort(int[] a,int[] tmp, int start,int end) {
        if(start < end) {
            int mid = (start + end) / 2;
            customMergeSort(a,tmp,start,mid);
            customMergeSort(a,tmp,mid + 1, end);
            customDoubleMerge(a,tmp,start,mid,end);
        }
    }

    public void customDoubleMerge(int[] a,int[] tmp, int left,int mid,int right) {
        int p1 = left, p2 = mid+1, k = left,m = mid;
        while(p1 <= m && p2 <= right) {
            if(a[p1] <= a[p2]) {
                tmp[k++] = a[p1++];
            } else {
                tmp[k++] = a[p2++];
                count = (m - p1 + 1) + count;
            }
        }
        while(p1 <= m){
            tmp[k++] = a[p1++];
        }
        while(p2 <= right) {
            tmp[k++] = a[p2++];
        }

        for(int i = 0; i< k;i++)
            a[i] = tmp[i];
    }
}

 

posted @ 2020-10-15 15:15  loytime  阅读(293)  评论(0编辑  收藏  举报