逆序數計數問題

2021-07-23 05:30:19 字數 1350 閱讀 1421

逆序數問題的形化表示

輸入:一組n個不同的數的序列a[n]

輸入:逆序數對數記為 num,如果 i < j 而 a[i] > a[j] ,那麼就是逆序數對

逆序數技術問題是排序演算法的某種變形。

方法一:暴力破解法(類似於氣泡排序)

思路:列舉出所有的陣列對,一共有 n*(n-1)/2 對,判斷這些是否為逆序數對數。

時間複雜度:o(n^2)

方法二:運用divide-and-conquer,借鑑歸併排序或者快排的思想,其時間複雜度為 o(nlogn)

1) 借鑑歸併排序思想

將乙個規模為n的逆序數計數問題分成2個規模為n/2的子問題,遞迴呼叫計算各個子問題產生的逆序數記為 rc_left 和 rc_right ,再將子問題進行合併同時計算此過程中產生的逆序數記為 rc,最後返回的是已經排序好的序列以及a[n]中的逆序數對數 num = rc + rc_left + rc_right 。

如圖,假設左右兩個子串行已經排序好,其逆序數對數分別為 rc_left 和 rc_right

在合併過程中5與4進行比較,可得出一對逆序數對。將4排序好後,就省去了與後續的 6,7,8進行比較,相對於暴力演算法節省了次數。重複此過程完成兩個子問題的合併得到逆序數對數為rc。

演算法**如下

std::vector

v (100000) ;

std::vector

v_temp(100000) ;

int sortandcount ( std::vector

& v , int low , int high )

int mergeandcount ( std::vector

& v , int low , int mid , int high )

}while ( i <= mid ) v_temp[k++] = v[i++] ;

while( j <= high ) v_temp[k++] = v[j++] ;

//將排序後的陣列元素賦值給v

for( int m = low ; m <= high ; m++ )

v[m] = v_temp[m] ;

return rc ;

}

2)運用divide-and-conquer方法,借鑑快排的思想[據大神說,是可以用快排做出來的,以後來更]

逆序對計數問題

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

分而治之 逆序對計數問題

問題 輸入乙個長度長度為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 中的逆序對數目...

計數問題(二)

計數問題 二 在上一講中,我們一起研究 列舉法 乘法原理 加法原理 在計數問題中的應用。但是,在實際的問題中,這些方法並不是單獨使用的。往往需要同時應用這幾種方法,這就需要我們搞清題意,根據已知條件,分別使用正確的方法,得到準確的結果。一 閱讀思考 例1.求720這個數約數的個數。分析與解 從1開始...