剑指offer-数组中的逆序对-Java

138 篇文章 0 订阅
132 篇文章 0 订阅

题目描述:

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

思路解析:

  • 基本的方法是从前到后挨个比较,时间复杂度是O(n^2); 优化方法的时间复杂度是O(nlogn);
  • 优化方法是分治法,把数组一分为二子数组,再分为子数组,直到为一个数字是一个数组的时候,先统计子数组的逆序对的数目,统计的过程中就把顺序按从小到大排序,此时用的归并排序。然后再统计出两个相邻的子数组之间的逆序对的数目。
  • 细节:1.Sort()里面用递归的方法达到一直分为一个数字,条件是left<right。2.计算result的时候注意前面的 array[i ]已经大于后边的array[ j] 了,由于是两边都是排好序的,所以i到mid的值都是比j大的.

图片来自网络。

代码:

public class Solution {
    private int result=0;//存储交换次数
    static int[] temp; //排序所需要的额外的空间
    public int InversePairs(int[] array) {
        //无效的输入
        if(array==null||array.length<=0){
            return 0;
        }
        temp = new int[array.length];
        sort(array,0,array.length-1);
        return result;
    }
    public void sort(int[] array,int left,int right){
         if(left<right){
            int mid = (left+right)/2;
            sort(array,left,mid);
            sort(array,mid+1,right);
            merge(array,left,mid,right);
        }
    }
    public void merge(int[] array,int left,int mid,int right){
        int i=left;
        int j=mid+1;
        int current=0;
        
       while(i<=mid && j<=right){
            if(array[i]>array[j]){
                temp[current++] = array[j++];
                result += mid - i +1;//如果i>j的话,那么从下标i到mid之间的数字都是大于array[j]的
                if(result>1000000007){
                    result%=1000000007;
                }
            }
            else{
                temp[current++]=array[i++];
            }
        }
        while(i<=mid){
            temp[current++]=array[i++];
        }
        while(j<=right){
            temp[current++]=array[j++];
        }
        /*和下面的代码是一个意思
        for(i=0;i<current;i++){
            a[left+i]=temp[i];
        }*/
        current=0;//在原来数组的基础上,继续添加进已排好的数列
        while(left<=right){
            array[left++]=temp[current++];
        }
        
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值