数组中的逆序对

数组中的逆序对

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

输入一个数组,求出这个数组中的逆序对的总数。

样例
输入:[1,2,3,4,5,6,0]

输出:6

思路:
如果用双层循环暴力做,算法复杂度是o(n^2) 肯定是不对的
我们想到用排序算法做,既能遍历到逆序对,又能不改变原数组逆序对的前后位置,所以用归并排序做

假如[1,2,3,4,5,6,0]
归并排序:切分 也许不严谨但是得到了[1,2,3,4] , [0,5,6] 这两个数组,正常的归并就是将他们合并为一个数组,小的在前大的不动,由于0是后面那个数组的最小值,如果前面的第一个数1都要比0大,代表2,3,4不用比较了,肯定比0大,返回 前面第一次比第二个数组数大的index到第一个数组的边界(mid)的容量,就是这个部分的逆序对个数,利用二分递归如此反复,由于归并用了分治与归并,没有重复的子问题,所以这个逆序对不可能重复

public class Solution {
    int res = 0;

    public int inversePairs(int[] nums) {
        mergeSort(nums, 0, nums.length - 1);
        return res;
    }

    public void merge(int num[], int l, int r) {//归并

        int temp[] = new int[r + 1];
        int m = (l + r) / 2;
        int i = l, j = m + 1, k = l;
        while (i <= m && j <= r) {
            if (num[i] < num[j]) {
                temp[k++] = num[i];
                i++;
            } else {
                res = res + m - i + 1;
                temp[k++] = num[j];
                j++;

            }

        }
        while (i <= m) {
            temp[k++] = num[i];
            i++;
        }
        while (j <= r) {
            temp[k++] = num[j];
            j++;
        }
        for (int o = l; o <= r; o++) {
            num[o] = temp[o];
        }
    }

    public void mergeSort(int num[], int start, int end) {//分治
        if (start == end) {//递归出口
            return;
        }
        int mid = (start + end) / 2;
        mergeSort(num, start, mid);
        mergeSort(num, mid + 1, end);
        merge(num, start, end);

    }

    public static void main(String[] args) {
        int a[] = {1, 2, 3, 4, 5, 6, 0};
        System.out.println(new D1().inversePairs(a));

    }
}

6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值