首页 > 其他分享 >获取数组中逆序对的对数

获取数组中逆序对的对数

时间:2022-11-08 22:46:00浏览次数:69  
标签:p2 arr p1 help int -- 数组 对数 逆序

package class04;

import java.util.Arrays;

/**
 * 获取数组中逆序对的对数
 * <p>
 * 在一个数组中,
 * 任何一个前面的数a,和任何一个后面的数b,
 * 如果(a,b)是降序的,就称为逆序对。
 * 返回数组中所有的逆序对的对数。
 */
public class Code03_reversePairNumber {
    public static int reversePairNumber(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        return process(arr, 0, arr.length - 1);
    }

    private static int process(int[] arr, int L, int R) {
        if (L == R) {
            return 0;
        }
        int M = L + ((R - L) >> 1);
        return process(arr, L, M) + process(arr, M + 1, R) + merge(arr, L, M, R);
    }

    private static int merge(int[] arr, int L, int M, int R) {
        int[] help = new int[R - L + 1];
        int ans = 0;//用于记录逆序对的对数
        int p1 = M;//定义p1先在左组的最右位置
        int p2 = R;//定义p2先在右组的最右位置
        int i = help.length - 1;//辅助数组help,从后往前逆序填值。
        while (p1 >= L && p2 >= M + 1) {
            //如果arr[p1]大于arr[p2],那么右组中p2(不含)左侧的所有数,都是大于arr[p1]的,给ans累加上这个个数。
            ans += arr[p1] > arr[p2] ? p2 - (M + 1) + 1 : 0;
            //如果左组中的arr[p1],大于右组中的arr[p2],就给help[i]赋值arr[p1],p1--,i--。
            //如果左组中的arr[p1],小于等于右组中的arr[p2],就给help[i]赋值arr[p2],p2--,i--。
            //注意,如果是等于,一定是给help[i]赋值右组的arr[p2],而不是左组的arr[p1]。否则,对于左组的arr[p1],我们不知道右组中一共有几个数是小于arr[p1]的。
            help[i--] = arr[p1] > arr[p2] ? arr[p1--] : arr[p2--];
        }
        while (p1 >= L) {//只要p1大于等于左组的0位置
            help[i--] = arr[p1--];//就将arr[p1]赋值给help[i],p1--,i--。
        }
        while (p2 >= M + 1) {//只要p2大于等于右组的0位置
            help[i--] = arr[p2--];//就将arr[p2]赋值给help[i],p2--,i--。
        }
        for (i = 0; i < help.length; i++) {//将辅助数组help中的值,全部倒给原数组arr。仅仅是当前一个小组。
            arr[L + i] = help[i];
        }
        return ans;
    }

    //获取逆序对的对数,用于测试。
    public static int reversePairNumberForTest(int[] arr) {
        int ans = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < i; j++) {
                if (arr[j] > arr[i]) {//数组中,当任意一个数大于它左侧的任意一个数时,ans就累加一。
                    ans++;
                }
            }
        }
        return ans;
    }

    public static int[] generatorRandomArray(int maxSize, int maxValue) {
        int[] arr = new int[(int) (Math.random() * maxSize) + 2];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * maxValue);
        }
        return arr;
    }

    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    public static void main(String[] args) {
        int maxSize = 100;
        int maxValue = 100;
        int testTimes = 100000;
        System.out.println("test start!");
        for (int i = 0; i < testTimes; i++) {
            int[] arr0 = generatorRandomArray(maxSize, maxValue);
            int[] arr1 = copyArray(arr0);
            int[] arr2 = copyArray(arr0);
            int num1 = reversePairNumber(arr1);
            int num2 = reversePairNumberForTest(arr2);
            if (num1 != num2) {
                System.out.println("oops!");
                System.out.println("arr0 = " + Arrays.toString(arr0));
                System.out.println("num1 = " + num1);
                System.out.println("num2 = " + num2);
                break;
            }
        }
        System.out.println("test end!");
    }

}

 

标签:p2,arr,p1,help,int,--,数组,对数,逆序
From: https://www.cnblogs.com/TheFloorIsNotTooHot/p/16871496.html

相关文章

  • 数组扩容
    importjava.util.Scanner;publicclassEext{ publicstaticvoidmain(String[]args){ //数组扩容 int[]arr={1,2,3}; int[]arr2=newint[arr.length+1]......
  • 在有序数组中找一个数
    #include<stdio.h>intmain(){ intarr[]={1,2,3,4,5,6,7,8,9,10}; inti=1; intse=sizeof(arr)/sizeof(arr[0]); intk=7; for(i=0;i<se;i++) { if(arr[i]==k)......
  • 实验4 类与数组、指针
    实验任务5:#include<iostream>#include"vectorInt.h"usingnamespacestd;voidtest(){usingnamespacestd;intn;cin>>n;vectorIntx1(n);......
  • 实验四 类与数组、指针
    实验五:task5.cpp#include<iostream>#include"vectorInt.hpp"voidtest(){usingnamespacestd;intn;cin>>n;vectorIntx1(n);for(autoi......
  • 数组
    数组介绍数组是一种容器,可以用来存储同种数据类型的多个值数组在存储数据的时候,需要结合隐式转换考虑数组的定义与初始化数组的定义格式一:int[] array格式二......
  • 数组翻转
    importjava.util.Scanner;publicclassEext{ publicstaticvoidmain(String[]args){ int[]array={1,2,3,4,5,6}; //把array[0]和array[5]进行交换{5,2,3,......
  • 实验4 类与数组、指针
    实验五vectorint.h#pragmaonce#include<iostream>usingnamespacestd;classvectorInt{public: ints,*p; vectorInt(intm) { p=newint[m]; s......
  • 实验4 类与数组、指针
    Task1~4浅复制:inta=10;intb=a;可用于静态内存的复制。对于简单的类,默认的复制构造函数已经够用了,但当类持有其他资源,如动态分配的内存、指针等,就需要用到深复制......
  • 软件工程最大连续子数组和(最大子段和)
     题目一:最大连续子数组和(最大子段和)背景 问题:给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整......
  • 实验四类和对象数组及指针
    11#pragmaonce22#include<iostream>3344usingstd::cout;55usingstd::endl;6677classvectorInt{88public:99//构造......