分而治之 逆序對計數問題

2021-10-10 01:09:57 字數 2855 閱讀 8849

問題:

輸入乙個長度長度為n的陣列a[n],求出陣列a[n]逆序對的總數。

輸入:

長度為n的陣列a[n]

輸出:

陣列a[n]逆序對的總數

把陣列a二分為兩個子陣列a[1…n/2],a[n/2 + 1…n]

遞迴求解子問題

求解s1∶僅在a[1…n/2]中的逆序對數目

求解s2∶僅在a[n/2+1…n]中的逆序對數目

合併a[1…n/2]和a[n/2 +1…n]的解

求解s3∶跨越子陣列的逆序對數目

s = s1+s2+s3

與最大子陣列的問題一樣,執行效率的瓶頸值也在合併方面,也就是s3跨越子陣列的逆序對數目的求解問題。

s3的求解:

1. 策略一:直接求解2. 策略二:排序求解排序求解s的分而治之提高了演算法執行時間,但仍然還有優化的可能;

3. 策略三:歸併求解

(1)從左到右掃瞄有序子陣列:a[i]∈a[1…m],a[j] ∈ a[m+1…n]

···如果a[i] > a[j],統計逆序對,j向右移

···如果a[i] ≤ a[j],i向右移

(2)利用歸併排序框架保證合併後陣列的有序性

(3)s時間複雜度降至o(n)

//歸併排序的合併部分

}while

(i <= mid)

//左半部分排序

b[k++

]= a[i++];

while

(j <= r)

//右半部分排序

b[k++

]= a[j++];

for(

int i = l; i <= r; i++

)//從輔助空間複製回 a 陣列

a[i]

= b[i];}

void

mergesort

(int a,

int l,

int r)

//歸併排序

}int

main()

題目描述在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。

現在,給你乙個n個元素的序列,請你判斷出它的逆序數是多少。

比如 1 3 2 的逆序數就是1。

輸入

第一行輸入乙個整數t表示測試資料的組數(1<=t<=5)

每組測試資料的每一行是乙個整數n表示數列中共有n個元素(2〈=n〈=1000000)

隨後的一行共有n個整數ai(0<=ai<1000000000),表示數列中的所有元素。

資料保證在多組測試資料中,多於10萬個數的測試資料最多只有一組。

輸出

輸出該數列的逆序數

樣例輸入22

1 13

1 3 2

樣例輸出01

**:

#include

#include

using

namespace std;

#define max 1000001

long

long a[max]

,b[max]

;long

long count;

void

merge

(long

long a,

int l,

int mid ,

int r)

//歸併排序的合併部分

}while

(i <= mid)

//左半部分排序

b[k++

]= a[i++];

while

(j <= r)

//右半部分排序

b[k++

]= a[j++];

for(

int i = l; i <= r; i++

)//從輔助空間複製回 a 陣列

a[i]

= b[i];}

void

mergesort

(long

long a,

int l,

int r)

//歸併排序

}int

main()

return0;

}

逆序對計數問題

問題描述 統計乙個陣列中共有多少個逆序對 輸入 第一行乙個整數n,第二行n個整數 輸出 這n個數構成的陣列中逆序對的總數 解題思路 如果用蠻力列舉法,則對每個a i 列舉j j i 並統計逆序對數目 參考如下 int countinver int a int n 平均時間複雜度為o n 2 採用分而...

逆序數計數問題

逆序數問題的形化表示 輸入 一組n個不同的數的序列a n 輸入 逆序數對數記為 num,如果 i j 而 a i a j 那麼就是逆序數對 逆序數技術問題是排序演算法的某種變形。方法一 暴力破解法 類似於氣泡排序 思路 列舉出所有的陣列對,一共有 n n 1 2 對,判斷這些是否為逆序數對數。時間複...

逆序對計數

逆序對計數 問題描述 對於給定的陣列a,計算其逆序對的總數。即 image.png 輸入形式 輸入包含1組測試用例。乙個測試用例佔一行,第乙個整數表示陣列的長度,後面緊跟者陣列中的各個整數元素,中間都用乙個空格分開。陣列的長度範圍 每個數字a i 的範圍為 輸出形式 輸出乙個整數,表示逆序對的個數。...