問題:
輸入乙個長度長度為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 的範圍為 輸出形式 輸出乙個整數,表示逆序對的個數。...