逆序对问题(Java实现)归并

题目
对于给定的一段正整数序列,逆序对就是序列中ai>aj,且i<j的有序对;注意序列中可能有重复数字,并分析算法的时间性能。
例如:有6个数字,分别是5,4,2,6,3,1,则逆序对数目是11。

思想

  1. 一个乱序的数组,使用归并排序的方法对其进行拆分拆分,最后剩余两个已经排好序的数组(如图1)

     图1
    

在这里插入图片描述

  1. 然后对两个数组再进行归并排序,排序的同时统计逆序对,比如2与1对比可以产生逆序对,则4与1、5与1也能产生逆序对,按照此思路即可统计出所有的逆序对。

  2. 代码

package com.itwyc;

import java.util.*;

public class Main {
    public static long count = 0;   // 逆序对个数
    public static void getCount(int[] nums) {
        if (nums.length > 1) {
            int[] left_temp = getLeftTemp(nums, 0); // 得到左边数组           
            int[] right_temp = getLeftTemp(nums, 1);// 得到右边数组              
            getCount(left_temp); // 将得到的数组继续拆分                                   
            getCount(right_temp);
            merge(nums, left_temp, right_temp);// 归并排序,归并的同时统计逆序对                     
        }
    }

    public static int[] getLeftTemp(int[] temp, int a) {
        int[] current;
        if (a == 0) {
            current = new int[temp.length / 2];
            for (int i = 0; i < temp.length / 2; i++) {
                current[i] = temp[i];
            }
        } else {
            current = new int[temp.length - temp.length / 2];
            for (int i = 0; i < temp.length - temp.length / 2; i++) {
                current[i] = temp[temp.length / 2 + i];
            }
        }
        return current;
    }

    public static void merge(int[] nums, int[] left_temp, int[] right_temp) {
        int index = 0;
        int left = 0;
        int right = 0;
        int left_len = left_temp.length;
        int right_len = right_temp.length;
        while (left < left_len && right < right_len) {// 如果左边的数大于右边的数,则为逆序对                   
            if (left_temp[left] > right_temp[right]) {
                count += (left_len - left);// 如果此数为逆序对,则此数右边的数也为逆序对,因为两个数组内已经排好序                              
                nums[index++] = right_temp[right++];
            } else {
                nums[index++] = left_temp[left++];
            }
        }
        while (left < left_len) {
            nums[index++] = left_temp[left++];
        }
        while (right < right_len) {
            nums[index++] = right_temp[right++];
        }
    }

    public static void main(String[] args) {

        /**
         *  逆序对问题
         */
        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
        getCount(nums);
        System.out.println("逆序对有" + count + "个.");
    }
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java归并排序求逆序对是一种常见的排序算法,它通过将数组分成两个子数组,分别对子数组进行排序,然后将两个已排序的子数组合并成一个有序的数组。在归并的过程中,可以统计逆序对的数量。 下面是Java归并排序求逆序对实现步骤: 1. 首先,定义一个全局变量count,用于记录逆序对的数量。 2. 创建一个辅助数组temp,用于存储归并过程中的临时结果。 3. 编写一个merge方法,用于将两个已排序的子数组合并成一个有序的数组,并在合并过程中统计逆序对的数量。 - 在merge方法中,首先定义三个指针:left、right和index,分别指向左子数组、右子数组和辅助数组temp的起始位置。 - 然后,比较left指针和right指针所指向的元素大小: - 如果左子数组的元素小于等于右子数组的元素,则将左子数组的元素复制到temp数组,并将left指针向右移动一位。 - 如果左子数组的元素大于右子数组的元素,则将右子数组的元素复制到temp数组,并将right指针向右移动一位。同时,count需要加上left指针到左子数组末尾的长度,因为左子数组剩余的元素都大于当前的右子数组元素。 - 继续上述比较和复制的过程,直到左子数组或右子数组的元素全部复制到temp数组。 - 最后,将temp数组中的元素复制回原数组的相应位置。 4. 编写一个mergeSort方法,用于递归地对数组进行归并排序。 - 在mergeSort方法中,首先判断数组的长度是否大于1,如果不大于1,则直接返回。 - 如果数组的长度大于1,则将数组分成两个子数组,并分别调用mergeSort方法对子数组进行排序。 - 最后,调用merge方法将两个已排序的子数组合并成一个有序的数组,并统计逆序对的数量。 5. 在主函数中调用mergeSort方法对数组进行排序,并输出逆序对的数量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值