Sword refers to Offer-32-the reverse pair in the array

Title description

For two numbers in the array, if the first number is greater than the following number, the two numbers form a reverse pair. Enter an array and find the total number P of reverse pairs in this array. And output the result of P modulo 1000000007. That is to output P%1000000007

Enter description:

The title guarantees the same number that does not exist in the input array

data range:

For %50 data, size<=10^4
For %75 data, size<=10^5
For %100 data, size<=2*10^5

Example 1

Input
1, 2, 3, 4, 5, 6, 7, 0
output
7

Problem solving ideas

First of all, I am very entangled with a question, is this tree larger than all the following numbers? Or is it just greater than the next number? Then I thought about it again, I was really stupid. If it was only greater than all the numbers behind, wouldn't it be true that only one can satisfy the condition? Is the last reverse order only one? All must be that the number is greater than the number after it, such two numbers form a reverse pair!

Then, if you want to understand this, just go ahead and do it. Emmm, a thing similar to bubble sorting is here. Sure enough, it timed out, and the time was complicated to O(n^n). . .

error code

public class Solution {
    
    
    public int InversePairs(int [] array) {
    
    
        int P = 0;
        for(int i = 0;i<array.length;i++){
    
    
            for(int j = i; j< array.length;j++){
    
    
                if(array[i]>array[j]){
    
    
                    P++;
                }
            }
        }
         int result = P%1000000007;
        return result;
    }
}

Rearrange ideas

Since this method is feasible, it means that only the "sort" method needs to be improved. So try to merge and seek.
Review the portal of merge sort: interview essentials-eight sorting algorithms

Merge sort algorithm

//归并排序
	public static void mergeSort(int[] arr,int low,int high) {
    
    
		int middle=(high+low)/2;
		if(low<high) {
    
    
			//处理左边
			mergeSort(arr, low, middle);
			//处理右边
			mergeSort(arr, middle+1, high);
			//归并
			merge(arr,low,middle,high);
		}
	}
	
	public static void merge(int[] arr,int low,int middle, int high) {
    
    
		//用于存储归并后的临时数组
		int[] temp = new int[high-low+1];
		//记录第一个数组中需要遍历的下标
		int i=low;
		//记录第二个数组中需要遍历的下标
		int j=middle+1;
		//用于记录在临时数组中存放的下标
		int index=0;
		//遍历两个数组取出小的数字,放入临时数组中
		while(i<=middle&&j<=high) {
    
    
			//第一个数组的数据更小
			if(arr[i]<=arr[j]) {
    
    
				//把小的数据放入临时数组中
				temp[index]=arr[i];
				//让下标向后移一位;
				i++;
			}else {
    
    
				temp[index]=arr[j];
				j++;
			}
			index++;
		}
		//处理多余的数据
		while(j<=high) {
    
    
			temp[index]=arr[j];
			j++;
			index++;
		}
		while(i<=middle) {
    
    
			temp[index]=arr[i];
			i++;
			index++;
		}
		//把临时数组中的数据重新存入原数组
		for(int k=0;k<temp.length;k++) {
    
    
			arr[k+low]=temp[k];
		}
	}

Correct code

I admit that this code is someone else's. Because I don't understand why, but in the recursion, the size of the result is calculated cnt = (cnt + (mid-i+1))%1000000007; instead of finding the reverse number in the modulo operation. . . Doesn't recursion affect the result? Oh. . . It turns out that the modulus and addition of each result is also unchanged. .


public class Solution {
    
    
    private int cnt;
    private void MergeSort(int[] array, int start, int end){
    
    
        if(start>=end)return;
        int mid = (start+end)/2;
        MergeSort(array, start, mid);
        MergeSort(array, mid+1, end);
        MergeOne(array, start, mid, end);
    }
    private void MergeOne(int[] array, int start, int mid, int end){
    
    
        int[] temp = new int[end-start+1];
        int k=0,i=start,j=mid+1;
        while(i<=mid && j<= end){
    
    
//如果前面的元素小于后面的不能构成逆序对
            if(array[i] <= array[j])
                temp[k++] = array[i++];
            else{
    
    
//如果前面的元素大于后面的,那么在前面元素之后的元素都能和后面的元素构成逆序对
                temp[k++] = array[j++];
                cnt = (cnt + (mid-i+1))%1000000007;
            }
        }
        while(i<= mid)
            temp[k++] = array[i++];
        while(j<=end)
            temp[k++] = array[j++];
        for(int l=0; l<k; l++){
    
    
            array[start+l] = temp[l];
        }
    }
    public int InversePairs(int [] array) {
    
    
        MergeSort(array, 0, array.length-1);
        return cnt;
    }
}

Guess you like

Origin blog.csdn.net/H1517043456/article/details/107418592