劍指offer---數組中的逆序對

題目描述

在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007

輸入描述:

題目保證輸入的數組中沒有的相同的數字

數據範圍:

	對於%50的數據,size<=10^4

	對於%75的數據,size<=10^5

	對於%100的數據,size<=2*10^5

示例:

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

解題思路:
該題數組的size<=2*10^5,那麼使用兩層for循環就會出現超時的情況
那麼可以使用歸併排序思想來實現:
因爲每次歸併的時候,左邊和右邊的數組都是有序數組,
若左邊的數組中的數字大於右邊的數字,那麼左邊從當前位置起,到左邊數組結束的長度,都可以與右邊的數字組成逆序對。

如:

左邊爲4,6     右邊爲3,7
那麼當43比較時,(4,3),(6,3)都可以組成逆序對

下面的代碼就是在歸併排序的基礎上加了一行統計逆序對的代碼。

//數組中的逆序對 
static long sum = 0;//這裏需要注意爲 long 類型
void mergeArray(vector<int> &v,int left,int mid,int right){
	int i = left;//左邊數組的左指針
	int j = mid+1;//右邊數組的左指針
	int k = 0;//臨時數組的下標
	vector<int> temp(right-left+1);
	while(i <= mid && j <= right){
		if(v[i] > v[j]){
			//此時左邊數組的數字大於右邊數組的數字
			//可以組成逆序對
			sum += mid - i + 1; //統計逆序對
			temp[k++] = v[j++];
		}else{
			temp[k++] = v[i++];
		}
	} 
	while(i <= mid){
		temp[k++] = v[i++];
	}
	while(j <= right){
		temp[k++] = v[j++];
	}
	for(int m = 0;m < temp.size();m++){
		v[left+m] = temp[m];
	}
}
void divide(vector<int> &v,int left,int right){
	if(left < right){
		int mid = left + (right-left) >> 1;
		divide(v,left,mid);
		divide(v,mid+1,right);
		mergeArray(v,left,mid,right);
	}
}
int InversePairs(vector<int> data){
	if(data.empty()){
		return 0;
	}
	divide(data,0,data.size()-1);
	return sum % 1000000007;
} 

其他的排序算法代碼實現:

排序算法彙總—C++實現各個排序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章