数组中的逆序对

题目
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如:在数组{7,5,6,4}中,一共存在5对逆序对,分别是{7,5},{7,4},{7,6},{5,4},{6,4}。
解题思路
(1)暴力法
顺序扫描整个数组,然后每扫到一个数字,就拿后面的数字与它比较,如果后面的数字比它小,则这两个数字就组成了一个逆序对。假设数组中含有n个数,由于每个数字都要和O(n)个数字进行比较,因此这种算法的时间复杂度是O(n^2)。
源代码

package Arithmetic;

public class InversePairs {
    public static int inversePairs(int[] data) {
        int nums = 0;
        for (int i = 0; i < data.length; i++) {
            for (int j = i; j < data.length; j++)
                if (data[i] > data[j])
                    nums++;
        }
        return nums;
    }

    public static void main(String[] args) {
        System.out.println(inversePairs(new int[]{7, 5, 6, 4 }));
    }
}

(2)归并排序
如下图所示,先把数组分解成两个长度为2的子数组,再把这两个子数组分别拆分成两个长度为1的子数组。接下来一边合并相邻的子数组,以便统计逆序对的数目。在第一对长度为1的子数组{7}、{5}中,7大于5,因此(7,5)也是一个逆序对。同样的,在第二对长度为1的子数组{6}、{4}中,也有逆序对(6,4)。由于已经统计了这两对子数组内部的逆序对了,因此需要把这两对子数组排序,以免在以后的统计过程中再避免重复。
在这里插入图片描述
源代码

package Arithmetic;

public class InversePairs {
    public static int iPairs(int[] array) {
        if (array == null)
            throw new IllegalArgumentException();
        // 创建辅助数组
        int length = array.length;
        int[] copy = new int[length];
        System.arraycopy(array, 0, copy, 0, length);
        int numberOfInversePairs = iPairs(array, copy, 0, length - 1);
        return numberOfInversePairs;
    }

    /**
     * @param array 未归并数组
     * @param copy  用于存储归并后数据的数组
     * @param begin 起始位置
     * @param end   结束位置
     * @return 逆序数
     * @author Thanos
     */
    public static int iPairs(int[] array, int[] copy, int begin, int end) {
        if (begin == end)
            return 0;
        int mid = (begin + end) / 2;//中间位置
        // 递归调用
        int left = iPairs(copy, array, begin, mid);
        int right = iPairs(copy, array, mid + 1, end);
        // 归并
        int i = mid, j = end, pos = end;
        int count = 0; // 记录相邻子数组间逆序数

        while (i >= begin && j >= mid + 1) {
            if (array[i] > array[j]) {
                copy[pos--] = array[i--];
                count += j - mid;
            } else
                copy[pos--] = array[j--];
        }

        while (i >= begin)
            copy[pos--] = array[i--];
        while (j >= mid + 1)
            copy[pos--] = array[j--];

        return left + right + count;
    }

    public static void main(String[] args) {
        System.out.println(iPairs(new int[]{7, 5, 6, 4, 3}));
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值