532. 逆序对

2018-03-12  本文已影响19人  6默默Welsh

描述

在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。给你一个数组,求出这个数组中逆序对的总数。
概括:如果a[i] > a[j] 且 i < j, a[i] 和 a[j] 构成一个逆序对。

样例

序列 [2, 4, 1, 3, 5] 中,有 3 个逆序对 (2, 1), (4, 1), (4, 3),则返回 3 。

代码

  1. 暴力法
public class Solution {
    /**
     * @param A: an array
     * @return: total of reverse pairs
     */
    public long reversePairs(int[] A) {
        if (A == null || A.length == 0) {
            return 0;
        }
        
        int result = 0;
        for (int i = 0; i < A.length - 1; i++) {
            for (int j = i+1; j < A.length; j++) {
                if (A[i] > A[j]) {
                    result++;
                }
            }
        }
        
        return result;
    }
}
  1. 归并排序
public class Solution {
    /**
     * @param A an array
     * @return total of reverse pairs
     */
    public long reversePairs(int[] A) {
        return mergeSort(A, 0, A.length - 1);
    }
    
    private int mergeSort(int[] A, int start, int end) {
        if (start >= end) {
            return 0;
        }
        
        int mid = start + (end - start) / 2;
        int sum = 0;
        sum += mergeSort(A, start, mid);
        sum += mergeSort(A, mid+1, end);
        sum += merge(A, start, mid, end);
        return sum;
    }
    
    private int merge(int[] A, int start, int mid, int end) {
        // 此处如果写成 int[] temp = new int[A.length] 就比较耗费时间和空间
        int[] temp = new int[end - start + 1];
        int leftIndex = start;
        int rightIndex = mid + 1;
        // temp 数组的 index 要从 0 开始,如果写成等于 start,
        // 当 start 不等于 0 就会出现越界错误
        int index = 0;
        int sum = 0;
        
        while (leftIndex <= mid && rightIndex <= end) {
            // 左指针指向的值小于等于右指针指向的值则不构成逆序对
            if (A[leftIndex] <= A[rightIndex]) {
                temp[index++] = A[leftIndex++];
            } else {
                temp[index++] = A[rightIndex++];
                // 右指针指向的值小于左指针指向的值时,对于当前右指针指向的值
                // 从当前左指针开始到 mid位置所有数都可以和右指针指向值构成逆序对
                sum += mid - leftIndex + 1;
            }
        }
        while (leftIndex <= mid) {
            temp[index++] = A[leftIndex++];
        }
        while (rightIndex <= end) {
            temp[index++] = A[rightIndex++];
        }
        
        for (int i = 0; i < temp.length; i++) {
            // 此处是 i+start
            A[i + start] = temp[i];
        }
        
        return sum;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读