剑指offer 数组中的逆序对

题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。

        输入一个数组,并求出这个数组中的逆序对的总数P,并将P对1000000007取模输出、

输入描述:保证数组中没有相同的数字,size <= 2*10^5

输入:1,2,3,4,5,6,7,0   输出:7


思路: 1. 显然全部遍历一遍是可以求出来,时间复杂度为O(n^2)

           2. 实际上就是个归并排序,加了个变量count来计算,拆完合并时,因为归并的是两个有序的,那么前半部分某个大于后半部分某个,那么前半部分的某个后面的所有和后半部分都构成逆序对。就加一句count = mid - i + 1;

注意:这里由于题目明确说了结果取模,就是考虑到结果是int的话可能会出现越界情况,所以一帮自己做题目要注意可以使用long类型~

public class Solution {
        public int InversePairs(int [] array) {
             return revered(array);   
        }
    	
	public static int revered(int[] arr){
		return mergeSort(arr, 0, arr.length-1)%1000000007;
	}
	
	
	private static int mergeSort(int[] arr, int l, int r) {
		int cnt = 0;
		if(l < r){
			int mid = (l+r)/2;
			cnt += mergeSort(arr, l, mid);   //左边逆序数量
	        if(cnt>=1000000007)//数值过大求余
                {
                    cnt%=1000000007;
                }
            cnt += mergeSort(arr, mid+1, r); //右边逆序数量
			if(cnt>=1000000007)//数值过大求余
                {
                    cnt%=1000000007;
                }
            cnt += merge(arr, l, mid, r);	 //合并两部分,并计算数量
		    if(cnt>=1000000007)//数值过大求余
                {
                    cnt%=1000000007;
                }
        }
		return cnt;
	}

	private static int merge(int[] arr, int l, int mid, int r) {
		
		int[] aux = new int[r - l + 1];
		
		for(int i=l; i <= r; i++){
			aux[i-l] = arr[i];
		}
		
		int i = l, j = mid + 1;
		int cnt = 0;
		for(int k = l; k <= r; k ++){

			//判断索引的合法性
			if(i > mid){
				arr[k] = aux[j-l];
				j ++;
			}else if(j > r){
				arr[k] = aux[i - l];
				i ++;
			}else if(aux[i - l] < aux[j - l]){
				arr[k] = aux[i - l];
				i ++;
			}else{
				cnt += mid - i + 1;
                if(cnt>=1000000007)//数值过大求余
                {
                    cnt%=1000000007;
                }
				arr[k] = aux[j - l];
				j ++;
			}
		}
		return cnt;
	}

	//暴力
	public static int rever(int[] arr){
		int len = arr.length;
		int count = 0;
		for(int i = 0; i < len; i ++){
			for(int j = i; j < len; j++){
				if(arr[i] > arr[j]){
					count++;
				}
			}
		}
		return count;
	}
}
对归并排序的本质理解清楚~~

猜你喜欢

转载自blog.csdn.net/jae_wang/article/details/80511993