数组中的逆序对

本文介绍了一种使用归并排序思想来高效计算数组中逆序数目的方法。通过递归将数组分为两半,分别计算每半部分的逆序数,并在归并过程中计算跨半部分的逆序数,最终得到整个数组的逆序总数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


思路:利用归并排序的思想,先求前面一半数组的逆序数,再求后面一半数组的逆序数,然后求前面一半数组比后面一半数组中大的数的个数(也就是逆序数),这三个过程加起来就是整体的逆序数目了。

易错点:第二个方法在归并时,需要array的左右子数组是已排好序的数组,归并的结果是得到排好序的数组copy。因此在递归调用iPairs时,方法的前2个参数是颠倒的,这样得到的array才是排好序的。

比如第一次时用copy当辅助数组对array排序,第二次就正好反过来。

package algorithm;

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;
    }

    /**
     * @author Thanos
     * @param array 未归并数组 
     * @param copy 用于存储归并后数据的数组
     * @param begin 起始位置
     * @param end 结束位置
     * @return 逆序数
     */
    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) {
        int test[] = { 7, 5, 1, 6, 4 };
        int count = iPairs(test);
        System.out.println(count + " ");
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值