求逆序數(shù)

求一個(gè)數(shù)列的逆序數(shù)

逆序?qū)Γ簲?shù)列a[1],a[2],a[3]…中的任意兩個(gè)數(shù)a[i],a[j] (i<j),如果a[i]>a[j],那么我們就說(shuō)這兩個(gè)數(shù)構(gòu)成了一個(gè)逆序?qū)?/p>

逆序數(shù):一個(gè)數(shù)列中逆序?qū)Φ目倲?shù)

如:數(shù)列[3 5 4 8 2 6 9] (3,2),(5,2),(4,2),(5,4)等等都是一個(gè)逆序?qū)?設(shè)計(jì)一個(gè)程序求得一個(gè)數(shù)列的逆序數(shù)。(要求時(shí)間復(fù)雜度為O(nlogn)

主要思路

1、想到時(shí)間復(fù)雜度為O(nlogn),因此不能按照傳統(tǒng)方法“一對(duì)一”進(jìn)行查找
2、O(nlogn)的時(shí)間復(fù)雜度可以采用歸并排序進(jìn)行協(xié)助查找
3、對(duì)于序列a1中的某個(gè)數(shù)a1[i],序列a2中的某個(gè)數(shù)a2[j],如果a1[i]<a2[j],沒有逆序數(shù),如果a1[i]>a2[j],那么逆序數(shù)為a1中a1[i]后邊元素的個(gè)數(shù)(包括a1[i]),即length1-i+1(下面代碼中l(wèi)ength1的值等于mid)
4、累加遞歸過(guò)程中的所有逆序數(shù)

主要代碼

void Merge( int *a, int *b, int left, int right)
 //合并 a[ left:(left+right)/2 ] 和 a[ (left+right)/2+1:right ] 到 b[ left:right ]
 {
int i = left,  m = (left+right)/2, k = left, j = m + 1;
while( (i <= m) && (j <= right) )
    if( a[ i ] <= a[ j ]) b[ k++ ] = a[ i++ ];
    else {
        b[ k++ ] = a[ j++ ];
        count+=m-i+1; //關(guān)鍵代碼,歸并算法加此代碼可求逆序數(shù)。
    } 
if ( i>m ) 
    for( int q=j; q<=right; q++ )   b[ k++ ] = a[ q ];
else 
    for( int q=i; q<=m; q++)   b[ k++ ] = a[ q ];
}//將元素進(jìn)行排序并將排序后的元素合并到數(shù)組b中,其中求出逆序數(shù)

//分治法解決問(wèn)題
void MS (int *a, int left, int right) {
    int b[99];
    if (left == right) return ;
    int mid = (left + right)/2;
    MS (a, left, mid);//對(duì)左邊進(jìn)行排序(分)
    MS (a, mid+1, right);//對(duì)右邊進(jìn)行排序(分)
    Merge (a, b, left, right);//(治, 并)
    copy (a, b, left, right);//將數(shù)組b的元素復(fù)制到數(shù)組a中
}

ps:count+=m-i+1; //關(guān)鍵代碼,歸并算法加此代碼可求逆序數(shù)。

完整代碼

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

int count = 0;
/*
void MG (int *a, int *b, int left, int right) {
int i, j, m, k = left;
i = left;
m = (left+right)/2;
j = m + 1;
while ((i<=m)&& (j<=right)) {
    if (a[i] <= a[j]) {
        b[k] = a[i]; 
        i++; k++;
    }
    else {
        b[k] = a[j]; 
        j++; k++;
    } 
}
if (i>m) {
    while (j<=right) {
        b[k] = a[j];
        k++; j++;
    }
}
else {
    while (i<=m) {
        b[k] = a[i];
        k++; i++;
    }
}
}
*/

void Merge( int *a, int *b, int left, int right)
 //合并 a[ left:(left+right)/2 ] 和 a[ (left+right)/2+1:right ] 到 b[ left:right ]
 {
int i = left,  m = (left+right)/2, k = left, j = m + 1;
while( (i <= m) && (j <= right) )
    if( a[ i ] <= a[ j ]) b[ k++ ] = a[ i++ ];
    else {
        b[ k++ ] = a[ j++ ];
        count+=m-i+1; //關(guān)鍵代碼,歸并算法加此代碼可求逆序數(shù)。
    } 
if ( i>m ) 
    for( int q=j; q<=right; q++ )   b[ k++ ] = a[ q ];
else 
    for( int q=i; q<=m; q++)   b[ k++ ] = a[ q ];
}

void copy (int *a, int *b, int left, int right) {
    while (left <= right) {
        a[left] = b[left];
        left ++;
    }
}

void MS (int *a, int left, int right) {
    int b[99];
    if (left == right) return ;
    int mid = (left + right)/2;
    MS (a, left, mid);
    MS (a, mid+1, right);
    //MG (a, b, left, right);
    Merge (a, b, left, right);
    copy (a, b, left, right);
}

int main(int argc, char const *argv[])
{
    int n, left, right;
    int a[99];
    cin >> n;
    for (int i=0; i<n; i++) 
        cin >> a[i];
    left = 0; right = n-1;
    MS (a, left, right);
    cout << count;
    return 0;
}

Example

4
4 3 2 1 enter

輸出結(jié)果:
6

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,559評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,581評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,922評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,096評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,639評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,374評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,591評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,789評(píng)論 3 349
  • 開封第一講書人閱讀 35,196評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,322評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,554評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容