首页 > 试题广场 >

数组中的逆序对

[编程题]数组中的逆序对
  • 热度指数:828708 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007

数据范围:  对于 的数据,
对于 的数据,
数组中所有数字的值满足 0 \le val \le 10^9

要求:空间复杂度 ,时间复杂度

输入描述:
题目保证输入的数组中没有的相同的数字

示例1

输入

[1,2,3,4,5,6,7,0]

输出

7
示例2

输入

[1,2,3]

输出

0
//这里用的是官方题解,我做了一些更详细的注释,希望可以帮到一些朋友



import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型一维数组
     * @return int整型
     */
     int mod = 1000000007;
    public int mergeSort(int left, int right,int[] data,int[] temp) {
        //将数组分开
        if(left >= right) {
            return 0;
        }
        int mid = (left + right) / 2;
        int res = mergeSort(left,mid,data,temp) + mergeSort(mid + 1,right,data,temp);
        //下面的代码本质上是将数组合并,并且排序,顺便给逆序对进行计数
        res %= mod;
        //两端数组
        int i = left;//左边数组第一个元素
        int j = mid + 1;//右边数组第一个元素
        //将两段数组添加到一个临时数组中
        for(int k = left; k <= right; k++) {
            temp[k] = data[k];
        }
        for(int k = left; k <= right; k++) {
            if(i == mid + 1) {//左边数组已经遍历完
                data[k] = temp[j++];
            }else if(j == right + 1 || temp[i] <= temp[j]) {//右边数组已经遍历完或者左边元素小于右边元素
                data[k] = temp[i++];
            }else {
                data[k] = temp[j++];//左边元素大于右边元素,此时出现逆序对,进行计数
                res += mid - i + 1;//res是下一层数组逆序对的结果,由于两边数组都是有序的,左边的某一个元素大于右边的某一个元素,那么左边后面的所有元素都比右边的哪一个元素大,因此要加上mid - i + 1
            }
        }
        return res % mod;
    }

    public int InversePairs (int[] nums) {
        // write code here
        int left = 0;
        int right = nums.length - 1;
        int[] res = new int[right + 1];
        return mergeSort(left,right,nums,res);
    }
}
发表于 2024-03-20 22:09:52 回复(0)
终于过了,最后一个用例也太逆天了
public class Solution {
    public int InversePairs(int[] nums) {
        int left = 0, right = nums.length - 1;
        return (int)(mergeSort(nums, left, right) % 1000000007);
    }

    private long mergeSort(int[] nums, int left, int right) {
        if (left == right) {
            return 0;
        }
        int mid = left + ((right - left) >> 1);
        long x1 = mergeSort(nums, left, mid);
        long x2 = mergeSort(nums, mid + 1, right);
        long x3 = merge(nums, left, mid, mid + 1, right);
        return x1 + x2 + x3;
    }

    private long merge(int[] nums, int l1, int l2, int r1, int r2) {
        int[] temp = new int[r2 - l1 + 1];
        int i = 0;
        int l = l1;
        long count = 0;  
        while (l1 <= l2 && r1 <= r2) {
            if (nums[l1] > nums[r1]) {
                count = count + r2 - r1 + 1;
                temp[i++] = nums[l1++];
            } else {
                temp[i++] = nums[r1++];
            }
        }
        while (l1 <= l2) {
            temp[i++] = nums[l1++];
        }
        while (r1 <= r2) {
            temp[i++] = nums[r1++];
        }

        // 放回原来的数组
        i = 0;
        for (int i1 = l; i1 <= r2; i1++) {
            nums[i1] = temp[i++];
        }
        return count;
    }
}


发表于 2024-01-20 19:29:41 回复(1)

归并排序

public class Solution {
    public static final int MOD = 1000000007;

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

    public int mergeSort(int[] nums, int l, int r) {
        if (l == r) {
            return 0;
        } 
        int mid = (l + r) >> 1;
        int lres = mergeSort(nums, l, mid);
        int rres = mergeSort(nums, mid + 1, r);

        int left = l, right = mid + 1, ans = (lres + rres) % MOD;
        int[] tmp = new int[r - l + 1];
        int idx = 0;
        while (left <= mid && right <= r) {
            if (nums[left] <= nums[right]) {
                tmp[idx++] = nums[left++];
            } else {
                tmp[idx++] = nums[right++];
                ans = (ans + mid - left + 1) % MOD;
            }
        } 
        while (left <= mid) tmp[idx++] = nums[left++];
        while (right <= r) tmp[idx++] = nums[right++];
        for (int i = 0; i < idx; i++) {
            nums[l + i] = tmp[i];
        }

        return ans;
    }
}
发表于 2023-11-11 15:11:11 回复(0)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型一维数组
     * @return int整型
     */
    public int InversePairs (int[] nums) {
        long total=0;
        for (int i = 0; i < nums.length; i++) {
            for (int j = i+1; j <nums.length; j++) {
                if (nums[i]>nums[j]){
                    total++;
                }
            }
        }
        return (int) (total%1000000007);
    }
}

发表于 2023-10-20 20:05:53 回复(2)
// 归并排序,计算左边到右边的逆序对
public class Solution {
    long n;
    public int InversePairs (int[] nums) {
        int[] tmp = new int[nums.length];
        mergeSort(nums, tmp, 0, nums.length - 1);
        return (int)(n % 1000000007);
    }
    public void mergeSort(int[] nums, int[] tmp, int l, int r) {
        if (l < r) {
            int c = (l + r) / 2;
            mergeSort(nums, tmp, l, c);
            mergeSort(nums, tmp, c + 1, r);          
            mergeAscend(nums, tmp, l, c, r);
        }

    }

    private void mergeAscend(int[] nums, int[] tmp, int l, int c, int r) {
        int l1 = l, r1 = c, l2 = c + 1, r2 = r;
        int i = l1;
        while (l1 <= r1 && l2 <= r2 ) {
            if (nums[l1] <= nums[l2]) {
                tmp[i++] = nums[l1++];
            } else {
                n += (r1 -l1 + 1);
                tmp[i++] = nums[l2++];
            }
        }
        while (l1 <= r1) {
            tmp[i++] = nums[l1++];
        }
        while (l2 <= r2) {
            tmp[i++] = nums[l2++];
        }
        for (i = l; i <= r; i++) {
            nums[i] = tmp[i];
        }
    }
}
发表于 2023-09-16 21:39:41 回复(0)
import java.util.*;

public class Solution {
    public int InversePairs(int [] array) {
        long sum = 0;
        for (int i = 1; i < array.length; i++) {
            int values = array[i];
            int[] ints = Arrays.copyOfRange(array, 0, i + 1);
            Arrays.sort(ints);
            int index = Arrays.binarySearch(ints, values);
            sum += (i - index);
        }
        return (int)(sum % 1000000007);

    }
}
发表于 2023-03-23 17:08:33 回复(1)
通过率83.3%,不足是运行超时,代码没毛病。
public class Solution {
    public int InversePairs(int [] array) {
        if (array == null || array.length == 0) return -1;
        int count = 0;
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = i; j < array.length - 1; j++) {
                if (array[i] > array[j + 1])  count++;
            }
        }
        return count % 1000000007;
    }
}


发表于 2023-03-19 20:57:05 回复(2)
public class Solution {
    int flag = 0;
    public int InversePairs(int [] array) {
            process(array,0,array.length-1);
            return flag ;
        }
        public void process(int[] arr, int l, int r) {
            if (l == r) {
                return;
            }
            int m = l + ((r - l) >> 1);
            process(arr, l, m);
            process(arr, m + 1, r);
            merge(arr, l, r);
        }
        public void merge(int[] arr, int left, int right) {
            int mid = left + ((right - left) >> 1);
            int[] temp = new int[right - left + 1];
            int i = left;
            int j = mid + 1;
            int k = 0;
            while (i <= mid && j <= right) {
                if (arr[i] > arr[j]) {
                    temp[k++] = arr[j++];  //右边的小,小的加入辅助数组
                flag+=mid-i+1;  //右边的小说明有逆序对,因为每次两个部分都是排好序的所以arr[i]以及以后都比arr[j]大
                flag %=1000000007;
            }else {
                temp[k++] = arr[i++];
            }
        }
        if (i<=mid) {
            int x = i;
            while (i <= mid) {
                temp[k++] = arr[i++];
            }
            flag += (mid-i+1)*(right-mid);  //左边的多了说明在arr[i]以及以后都比右部分大所以这里乘了(right-mid)
            flag %=1000000007;
            }
            while (j <= right) {
                temp[k++] = arr[j++];
            }
            for (int i1 = 0; i1 < temp.length; i1++) {
                arr[i1 + left] = temp[i1];
            }
        }
}

发表于 2023-03-16 22:13:36 回复(0)
public class Solution {
    public int InversePairs(int [] array) {
        if(array.length == 0) return 0;
        long P =0L;
        for(int i =0; i < array.length - 1; i++)
            for(int j = i + 1; j < array.length; j++){
                if(array[i] > array[j]) P++;
            }
        return (int)(P % 1000000007);
    }
}
这个代码是不是时间复杂度是O(n^2)?虽然通过了,冒泡排序再怎么优化都是n^2吗?
发表于 2023-03-08 16:57:38 回复(1)
参考高赞@rs勿忘初心 的思路,使用Java语言实现。
这里count的取模放到最后会抛出异常,需要放到每次计算的过程中
public class Solution {
    public int InversePairs(int [] array) {
        if(null == array || array.length <= 1){
            return 0;
        }

        return getCount(array,0,array.length-1,new int[array.length]);

    }

    private int getCount(int[] array,int start,int end,int[] copy){
        if(start >= end) {
            copy[start] = array[start];
            return 0;
        }

        int count = 0;
        int mid = start + (end - start) / 2;
        count += getCount(array,start,mid,copy);
        count += getCount(array,mid + 1,end,copy);

        int i = mid;
        int j = end;
        int copyIndex = end;
        while (i >= start && j > mid){
            if(array[i] > array[j]){
                copy[copyIndex--] = array[i--];
                count += j - mid;
                count = count % 1000000007;
            }
            else{
                copy[copyIndex--] = array[j--];
            }
        }
        while (i >= start){
            copy[copyIndex--] = array[i--];
        }
        while (j > mid){
            copy[copyIndex--] = array[j--];
        }

        for(int k = start;k <= end;k++){
            array[k] = copy[k];
        }

        return count;
    }
}


发表于 2023-03-03 11:49:35 回复(1)
//归并排序Java版
public class Solution {
    int count=0;
    public int InversePairs(int [] array) {
        mergeSort(array,0,array.length-1);
        return count;
    }

    public void mergeSort(int [] array, int left, int right){
        if(left >= right) return;
        int mid = (left+right)/2;
        mergeSort(array, left, mid);
        mergeSort(array, mid+1, right);
        merge(array, left, mid, right);
    }

    public void merge(int [] array, int left, int mid, int right){
        int[] temp=new int[right-left+1];
        int i=left, j=mid+1;
        int t=0;

        while(i<=mid && j<=right){
            if(array[i]<=array[j]){
                temp[t++]=array[i++];
            }else{
                count=count+(mid-i+1);
                count%=1000000007; //在这里取模
                temp[t++]=array[j++];
            }
        }

        while(i<=mid){
            temp[t++]=array[i++];
        }
        while(j<=right){
            temp[t++]=array[j++];
        }

        for(int k=0;k<temp.length;k++){
            array[left+k]=temp[k];
        }
        
    }
}

发表于 2023-02-05 11:31:45 回复(2)
public int InversePairs(int[] array) {
if (array == null || array.length == 1) {
return 0;
}
return mergeSort(array, 0, array.length - 1);
}

private int mergeSort(int[] array, int left, int right) {
if (left == right) {
return 0;
}
int mid = left + ((right-left)>>1);
int result = mergeSort(array, left, mid)
+ mergeSort(array, mid + 1, right)
+ merge(array, left, mid, right);
return (result%1000000007);
}

private int merge(int[] array, int left, int mid, int right) {
int[] help = new int[right - left + 1];
int p1 = mid;
int p2 = right;
int reverseNum = 0;
int i = help.length - 1;
while (p1 >= left && p2 > mid) {
if (array[p1] > array[p2]) {
reverseNum += (p2 - mid);
help[i--] = array[p1--];
} else {
help[i--] = array[p2--];
}
}
while (p1 >= left) {
help[i--] = array[p1--];
}
while (p2 > mid) {
help[i--] = array[p2--];
}
for (int j = 0; j < help.length; j++) {
array[left + j] = help[j];
}
return reverseNum%1000000007;
}
发表于 2022-11-23 20:07:24 回复(0)
我这个算不算暴力解法呀
public class Solution {
    public int InversePairs(int [] array) {
        if(array.length==0 || array.length==1)return 0;
        int fast = 1;
        int slow = 0;
        long count = 0;
        while(slow<array.length-1){
            if(array[slow]>array[fast]){
                count++;
            }
            fast++;
            if(fast==array.length){
                slow++;
                fast=slow+1;
            } 
        }
        return (int)(count % 1000000007);
    }
}
发表于 2022-11-12 14:01:48 回复(3)
public class Solution {
    public int InversePairs(int [] array) {
        if (array == null || array.length <= 0 ) {
            return 0;
        }
        int[] temp = new int[array.length];
        return sort(array, 0, array.length-1, temp) % 1000000007;

    }
    private int sort(int[] array, int left, int right, int[] temp) {
        if (left == right) {
            return 0;
        }
        int mid = (right - left) / 2 + left;
        int leftPairCount = sort(array, left, mid, temp);
        int rightPairCount = sort(array, mid + 1, right, temp);
        int tmpPairCount = merge(array, left, mid, right, temp);
        return leftPairCount + rightPairCount + tmpPairCount;

    }

    private int merge(int[] array, int left, int mid, int right, int[] temp) {
        int start1 = left;
        int start2 = mid + 1;
        int index = 0;
        int computeReversePairs = 0;
        while (start1 <= mid && start2 <= right) {

            if (array[start1] <= array[start2]) {
                temp[left + index] = array[start1];
                start1++;

            } else {
                temp[left + index] = array[start2];
                start2++;
                computeReversePairs = (computeReversePairs+(mid-start1+1))%1000000007;
            }
            index++;
        }

        while (start1 <= mid) {
            temp[left + index] = array[start1];
            start1++;
            index++;
        }
        while (start2 <= right) {
            temp[left + index] = array[start2];
            start2++;
            index++;
        }
        //将temp覆盖原来的数组中的顺序
        while (left <= right) {
            array[left] = temp[left];
            left++;
        }
        return computeReversePairs;
    }
}

发表于 2022-11-01 13:38:12 回复(0)
其实就是归并排序,在左边比右边绝对大的时候  再进行计count += 左边当前共有的多少数
public class Solution {
    public int mod = 1000000007;
    public int InversePairs(int [] arr) {
        if(arr == null || arr.length <= 1){
            return 0;
        }
        int[] temp = new int[arr.length];
        return InversePairs(arr, 0, arr.length - 1, temp);
    }

    public int InversePairs(int [] arr, int left, int right,int[] temp) {
        if(left >= right){
            return 0;
        }
        int mid = left + (right - left ) / 2;

        int val1 = (InversePairs(arr, left, mid, temp) + InversePairs(arr, mid + 1, right, temp)) % mod;


        if(arr[mid] <= arr[mid + 1]){
            return val1;
        }

        int l = left, r = mid + 1 ,count = 0,
        tempI = 0;
        while (l <= mid && r <= right){
            if(arr[l] > arr[r]){
                temp[tempI] = arr[r];
                r++;
                // 左边比右边绝对大时 count+= 左边当前共有多少数的数量
                count +=  mid + 1 - l;
            }else{
                temp[tempI] = arr[l];
                l++;
            }
            tempI++;
        }

        while (l <= mid){
            temp[tempI] = arr[l];
            l++; tempI++;
        }
        while (r <= right){
            temp[tempI] = arr[r];
            r++; tempI++;
        }

        tempI = 0;
        for (int i = left; i <= right; i++,tempI++) {
            arr[i] = temp[tempI];
        }
        return (val1 + count)  % mod;
    }
}   


发表于 2022-10-31 01:36:05 回复(0)
为什么要 % 
1000000007
发表于 2022-10-11 21:37:18 回复(1)
public class Solution {
    int ans = 0;
    public int InversePairs(int [] nums) {
        if(nums.length < 1) return 0;
        mergeSort(nums, 0, nums.length - 1);
        return ans;
    }
    
    void mergeSort(int[] nums, int left, int right){
        if(left >= right) return;
        
        int mid = left + (right - left) / 2;
        
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);
        merge(nums, left, mid , right);
    }
    
    void merge(int[] nums, int left, int mid, int right) {
        int[] copy = new int[right - left + 1];
        
        int l1 = left, l2 = mid + 1, idx = 0;
        while(l1 <= mid && l2 <= right) {
            if(nums[l1] < nums[l2]) {
                copy[idx++] = nums[l1++];
            }else{
                copy[idx++] = nums[l2++];
                ans += mid - l1 + 1;
                ans %= 1000000007;
            }
        }
        while(l1 <= mid) copy[idx++] = nums[l1++];
        while(l2 <= right) copy[idx++] = nums[l2++];
        
        for(int i = 0; i < copy.length; ++i) {
            nums[left + i] = copy[i];
        }
    }
}

发表于 2022-09-03 14:13:29 回复(0)
/*2的n次位进行比较,改变归并的情况 不分割只合并*/
public class Solution {
    public int InversePairs(int [] array) {
        int i=1,count=0; //比较的位数
        while(i <= array.length){
            count+=compare(array,i);
            i=2*i;
        }
        return count%1000000007;
    }
    //排序数组 数组的比较位数 零时数组的长度
    public int compare(int [] arr, int number){
        //数组指针
        int p = 0;
        int count=0;

        //开始循环比较
        while (p+number <= arr.length-1){ //存在比较

            //零时存储的数组
            int [] temp=new int[2*number>arr.length ? arr.length -p : 2*number];

            //左右的比较指针
            int l = p;
            int r = p + number;

            //存入数组下标
            int i = 0;
            while(l<p+number && r<arr.length){
                //开始比较赋值
                if(arr[l] > arr[r]) { //前大于后
                    temp[i++] = arr[r++];
                    count += p+number-l;
                    count %= 1000000007; 
                }
                else
                    temp[i++] = arr[l++];
                //一段比较结束
                if(l == p+number || r == p+number*2) break;
            }

            //比较未完成的
            while(l< p+number)
                temp[i++] =  arr[l++];
            while(r<arr.length && i<temp.length )
                temp[i++] = arr[r++];

            //覆盖原数组
            for(int j=0;j < temp.length && p+j < arr.length;j++){
                arr[p+j] = temp[j];
            }

            p=p+2*number;
        }
        return count;
    }
}
发表于 2022-08-28 10:35:07 回复(0)

问题信息

难度:
169条回答 171595浏览

热门推荐

通过挑战的用户

查看代码