當前位置:首頁 » 操作系統 » 逆序對演算法

逆序對演算法

發布時間: 2022-01-19 16:52:22

『壹』 逆序數怎麼求

解答如下:

當n=1時,排列為1 2,逆序數t=0。

當n=2時,排列為內1 3 2 4,逆序容數t=1。

當n=3時,排列為1 3 5 2 4 6,逆序數t=1+2=3。

當n=4時,排列為1 3 5 7 2 4 6 8,逆序數t=1+2+3=6。

當n=5時,排列為1 3 5 7 9 2 4 6 8 10,逆序數t=1+2+3+4=10。

相關內容解釋

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

也就是說,對於n個不同的元素,先規定各元素之間有一個標准次序(例如n個 不同的自然數,可規定從小到大為標准次序),於是在這n個元素的任一排列中,當某兩個元素的先後次序與標准次序不同時,就說有1個逆序。一個排列中所有逆序總數叫做這個排列的逆序數。

『貳』 怎麼算逆序數急~~~!!!

可使用直接計數法,計算一個排列的逆序數的直接方法是逐個枚舉逆序,同時統計個數。

舉個例子:

標准列是1 2 3 4 5,那麼 5 4 3 2 1 的逆序數演算法

看第二個,4之前有一個5,在標准列中5在4的後面,所以記1個。

類似的,第三個 3 之前有 4 5 都是在標准列中3的後面,所以記2個。

同樣的,2 之前有3個,1之前有4個,將這些數加起來就是逆序數=1+2+3+4=10。

(2)逆序對演算法擴展閱讀:

其它演算法:

1、歸並排序

歸並排序是將數列a[l,h]分成兩半a[l,mid]和a[mid+1,h]分別進行歸並排序,然後再將這兩半合並起來。在合並的過程中(設l<=i<=mid,mid+1<=j<=h),當a[i]<=a[j]時,並不產生逆序數;

當a[i]>a[j]時,在前半部分中比a[i]大的數都比a[j]大,將a[j]放在a[i]前面的話,逆序數要加上mid+1-i。因此,可以在歸並排序中的合並過程中計算逆序數。

2、樹狀數組

由於樹狀數組的特性,求和是從當前節點往前求,所以,這里要查詢插入當前數值之時,要統計有多少個小於該數值的數還沒插入,這些沒插入的數,都會在後面插入,也就形成了逆序數。

『叄』 一道編程題:求逆序對的個數

#include<stdio.h>
#define N 105
void main()
{
int n,i,j,k=0,p,m=0;
int a[20];
scanf("%d",&n);
getchar();
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
getchar();
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
{
if(a[i]>a[j])
k++;
}
for(i=0;i<n;i++)/*去掉相同的元素,再進行排序*/
for(j=i+1;j<n;j++)
{
if(a[i]=a[j])
{
for(p=j+1;p<n;p++)
a[p-1]=a[p];
n--;
}
}
for(i=0;i<p;i++)
for(j=i+1;j<p;j++)
{
if(a[i]>a[j])
m++;
}

printf("%d\n%d",k,m);
}//呵呵,我只會用c寫,不過結果是對的。

『肆』 當排列數中出現相同的數時,逆序數怎麼計算,比如145243

一.
預備知識
.
這部分就是網路上一搜一大片的東西,不過還是強調一下。
.
1.
全排列
從n個不同元素中任取m(m≤n)個元素,按照一定的順序排列起來,叫做從n個不同元素中取出m個元素的一個排列。當m=n時所有的排列情況叫n的全排列。[1]對於n的全排列,共有n!種情況。
2.
逆序、逆序數和奇、偶排列
在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。逆序數為偶數的排列稱為偶排列;逆序數為奇數的排列稱為奇排列。[2]
例如,對於n=3的全排列:
全排列
123
231
312
132
213
321
逆序數
0
2
2
1
1
3
奇偶性


.
二.
相關問題
.
1.
給定一個排列,求它的逆序數。[3]
問題:給定一個排列,求它的逆序數是多少。
分析:設
p1,p2,…,pn
為n的一個全排列,則其逆序數為t=t1+t2+…+tn=
其中
ti為排在pi
前,且比pi
大的數的個數。
這部分代碼比較簡單,此處略去。
.
2.
根據逆序數推排列數。[4]
問題:給定一個n元排列,它的逆序數存在且唯一。那麼反過...

『伍』 n階行列式逆序數怎麼算,有沒有具體公式一步將逆序數

沒有具體公式,演算法如下:

在行列式:

顯然,1,2,...,n也是一個n級排列,這個排列具有自然順序,就是按遞增的順序排起來的;其它的排列都或多或少地破壞自然順序。

逆序

定義2 在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為一個逆序。

註:

1.對於n個不同的元素,先規定個元素之間有一個「標准次序」(例如n個不同的自然數,可規定由小到大為標准次序),於是在這n個元素的任一排列中,當某兩個元素的先後次序與標准次序不同時,就有1個「逆序」。

2.一個排列中所有逆序的總數叫做這個排列的逆序數。

3.逆序數為奇數的排列叫做奇排列,逆序數為偶數的排列叫做偶排列。

『陸』 給定有序表A[1:n],修改合並排序演算法,求出該有序表的逆序對數

逆序對是這么定義的,在數組array中,如果存在下標i,j ,且 i<j ,但是array[i]>array[j]。這里假定array是升序的,如果是降序則相反就行。
比如說 1,5,4,3 則有逆序對 (5,3)(5,4)(4,3)

顯然最笨的求逆序對的方法是,兩層循環查找一遍,復雜度為O(n^2);
目前最好的求逆序對的方法就是用分治法,也就是和歸並排序類似的方法。

我大概說一下這種方法的思想,有什麼不明白的直接用網路hi我。

首先將數組array從中間一分為二,假設前半部分叫left,後半部分叫right
那麼,可以先遞歸地對left和right做歸並排序,同事順便求出它們的逆序對數;(你學歸並排序了,這個應該能懂吧?)
然後,也就是最重要的一步,這時候left和right已經是有序的了,設置下標,l和r分別指向left和right的頭,如果當前的l指向的元素大於r指向的元素,則r++(這時候就構成逆序對了,因為left中的元素在原數組中的下標一定小於right中的元素),一直到left[l]<=right[r]為止,這時候l++,最終到left或right掃描完終止。這其實也是歸並排序的歸並過程。

『柒』 什麼叫逆序

跟標准列相反序數的總和
比如說
標准列是1 2 3 4 5
那麼 5 4 3 2 1 的逆序數演算法:
看第二個,4之前有一個5,在標准列中5在4的後面,所以記1個
類似的,第三個 3 之前有 4 5 都是在標准列中3的後面,所以記2個
同樣的,2 之前有3個,1之前有4個
將這些數加起來就是逆序數=1+2+3+4=10

再舉一個 2 4 3 1 5
4 之前有0個
3 之前有1個
1 之前有3個
5 之前有0個
所以逆序數就是1+3=4

這樣能明白嗎

『捌』 一道ACM題,求逆序對問題

一. 預備知識

.

這部分就是網路上一搜一大片的東西,不過還是強調一下。

.

1. 全排列

從n個不同元素中任取m(m≤n)個元素,按照一定的順序排列起來,叫做從n個不同元素中取出m個元素的一個排列。當m=n時所有的排列情況叫n的全排列。[1]對於n的全排列,共有n!種情況。

2. 逆序、逆序數和奇、偶排列

在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。逆序數為偶數的排列稱為偶排列;逆序數為奇數的排列稱為奇排列。[2]

例如,對於n=3的全排列:

全排列

123

231

312

132

213

321

逆序數

0

2

2

1

1

3

奇偶性





.

二. 相關問題

.

1. 給定一個排列,求它的逆序數。[3]

問題:給定一個排列,求它的逆序數是多少。
分析:設 p1,p2,…,pn 為n的一個全排列,則其逆序數為t=t1+t2+…+tn=

其中 ti為排在pi 前,且比pi 大的數的個數。

這部分代碼比較簡單,此處略去。

.

2. 根據逆序數推排列數。[4]

問題:給定一個n元排列,它的逆序數存在且唯一。那麼反過來,已知一個n元排列的逆序數為m,
這樣的n元排列有多少種?
分析:我們用f(n,m)表示逆序數為m的n元排列的個數,則求滿足條件的排列個數問題就轉化為求f(n,m)的值的問題。

為了得到最終結果,我們先研究f(n,m)的性質。可以得到以下幾個命題:

[命題1] 對任意n>=2且0<=m<=C(n,2)時f(n,m)>=1;當m>C(n,2)時,f(n,m)=0

C(a,b)表示從a個元素中選出b個元素的選擇種數

證明:先證命題1的前半部分。

(1)n=2時,m只可能是0或1.有f(2,0)=1,f(2,1)=1

(2)假設n=k時命題成立,即有f(k,m)>=1(0<=m<=C(k,2))

當n=k+1時,排列1,2,3,…,k+1滿足逆序數為0,所以有f(k+1,0)>=1

若m>=1,考慮某一逆序數為m-1的k元排列a1,a2,…,ak(由歸納假設知這個排列存在).現將k+1插入到a(k-1)和ak之間得到一個k+1元排列a1,a2,…,a(k-1),k+1,ak,這個排列的逆序數為m,所以f(k+1,m)>=1

綜上所述,對所有的0<=m<=C(n,2)有f(n,m)>=1

再證命題的後半部分(比較顯然)。

因為對於一n元排列,若要使其逆序數達到最大,那麼排列中任兩個數都構成逆序,其逆序數為C(n,2),所以不可能存在一n元排列使其逆序數大於C(n,2)

[命題2] f(n,m)=f(n,C(n,2)-m)

證明:對於一個逆序數為m的n元排列a1,a2,…,an,n元排列an,a(n-1),…,a2,a1的逆序數為C(n,2)-m.同理,對於一個逆序數為C(n,2)-m的n元排列a1,a2,…,an,n元排列an,a(n-1),…,a2,a1的逆序數為m.

於是,逆序數為m的n元排列的集合 和 逆序數為C(n,2)-m的n元排列的集合 是一一對應關系,所以f(n,m)=f(n,C(n,2)-m)

[命題3] f(n+1,m)=f(n,m)+f(n,m-1)+…+f(n,m-n)

先考慮由1,2,…,n組成的一個排列a1,a2,…,an,由於任一個由1,2,…,n,n+1構成的排列,可以看成將n+1加入的a1左邊,或an的右邊,或ai與a(i+1)之間(1<=i<=n-1)而形成的。又由於在n+1加入任一個位置之後,其前面沒有比n+1大的數,其後面的數都比n+1小,而且加入n+1之後,使得對後面的每一個數而言,其前面比自身大的數的個數增加1,對n+1前面的數而言,其前面比自身大的個數不變。於是當選取n+1加入a1的左邊時,排列a1,a2,…,an的逆序數變為m+n,當n+1加入ai與a(i+1)之間(1<=i<=n-1)時,排列a1,a2,…,an的逆序數變為m+n-i,當加入an的右邊時,排列a1,a2,…,an的逆序數仍為m。

於是,對於任一逆序數為m的n+1元排列,考慮n+1所處的位置。若n+1在第k位,則其餘n個元素構成逆序數為m-n+k-1的n元排列,且對任一逆序數為m-n+k-1的n元排列而言,當n+1放在該排列的某位,使得在新排列中n+1處於第k位,那麼新排列成為一逆序數為m的n+1元排列。

於是,逆序數為m的n+1元排列的集合 和 逆序數為m的n元排列的集合 是一一對應關系。這樣,對於一個n+1元排列,f(n,m)表示n+1排在最後的排列個數,f(n,m-1)表示n+1排在倒數第二位的排列的個數……,f(n,m-n)表示n+1排在首位的排列個數,且f(n+1,m)為這些排列之和。

所以f(n+1,m)=f(n,m)+f(n,m-1)+…+f(n,m-n)(注:記b<0時,f(a,b)=0)

[命題4] f(n,0)=f(n,C(n,2))=1

[命題5] f(n,1)=f(n,C(n,2)-1)=n-1(n>1)

證明:由命題3和命題4有

f(n,1)=f(n-1,1)+f(n-1,0)=f(n-1,1)+1

反復應用上式,根據f(2,1)=1,得到命題5成立

[命題6] f(n,2)=f(n,C(n,2)-2)=C(n,2)-1(n>2)

證明:由命題3,4,5有

f(n,2)=f(n-1,2)+f(n-1,1)+f(n-1,0)=f(n-1,2)+n-1

反復應用上式,根據f(2,2)=0,得到命題6成立

同理,可證明

f(n,3)=C(n,3)-C(n,2)-C(n,1) (n>3)

f(n,4)=C(n,4)+2C(n,3)-C(n,1) (n>4)

f(n,5)=C(n,5)+3C(n,4)+2C(n,3)-C(n,2)+1 (n>5)



我們可以無限遞推下去,計算f(n,k)的時候要用到前面所推導出的f(n,1)~f(n,k-1)。但是卻很難得到一個通項公式。這個問題就類似於用∑(k^t-(k-1)^t) 來求∑(k^(t-1)),每作下一項都要用到前面所有的結果。

由於在命題3中我們得出了一個關於f(n,m)的遞推公式,而且又知道了一些初始值。因此可以設計一個程序,輸入n,m,輸出f(n,m)。[5]

.

參考代碼:

+ View Code
.
3. 根據每個數的逆序數,然後求出原排列。[6]

復制代碼
問題:對於一個集合S={1,2,3,...N}的任一排列a1、a2、a3、... aN,我們定義ai的逆序數為
∑(aj>ai | j<i),即排在ai前的所有比ai大的數的個數。我們把每個數的逆序數按下標排出就構
成排列a1、a2、a3、... aN的一個逆序排列。比如排列 3 1 2 的逆序排列為 1 1 0(從左往右
依次是1的逆序數、2的逆序數、3的逆序數)。現在我們給出一個排列的逆序排列,請求出原排列。[7]
復制代碼
分析:<developing…一種題解請參閱引用7>

.

4. 給定逆序數,求滿足此逆序數的最小排列。[8]

問題:對於n的全排列,給定一個正整數m,找到滿足逆序數是m的最小的排列。例如,n=5,m=4,此
時滿足逆序數為4最小的排列是1 3 5 4 2。
分析:解決此問題,要先了解以下幾個命題和定理。(注意,在證明中排列的大於、小於指兩排列在全排列中位置的前後關系,小於即在前,大於反之)

[定理1]對於n的全排列,在它完全倒序的時候(也就是n,n-1,…,2,1的時候)逆序數最多。

證明:此處省略,可用反證法簡單證明。

[命題1]對於一個形如1,2,3,…,i-1,i,n,…i+1的排列q(如n=5時的1,2,5,4,3),即在數n前保證首項為1且嚴格以公差為1遞增而數n之後排列任意的數列,

(1)當數n之後是遞減的時候q的逆序數最多,為t=C(n-i,2)。

(2)排列q是出現逆序數為t的最小排列。

證明:首先證明(1)。

這個證明很容易。因為數列的前i+1項已經確定,所以整個數列的逆序數只和i+2項到n項有關。顯然,由定理1,當第i+2項到第n項完全倒序的時候逆序數最大。比如說排列1,2,5,4,3就比1,2,5,3,4構成的逆序對多。

現在證明(2)。

假設存在一個排列p的逆序數為m且p小於q。我們知道,q的前i位已經是數n在當前位置的最小排列。也就是說,在q中無論是n還是n之後的任意一個數,將它與q中的1到i位的任意一個數更換位置後得到的排列一定大於q。比如,對於排列q:1,2,5,4,3,前兩個數1、2的位置是不能變的,否則會大於q,比如1,3,5,4,2。

所以我們只能從q的第i+1位到n位入手。由(1)可知,當n在第i+1位時,無論後面的數怎麼排列,逆序數都無法超過m。所以p的數n一定在第i+2到第n位的任一位上。

好的,我們假設數n在第i+2位上。在這種情況下不難發現,我們把原來n後面最大的數填補到第i+1位,這時的逆序數最多。比如對於1,2,5,4,3,我們把5移動到第4位,然後將4填補到第3位,排列就變成了1,2,4,5,3,顯然這要比1,2,3,5,4優。

我們分析一下這時p的逆序數。因為數n到了第i+2位,則由它構成的逆序數為n-i-2。同樣,由第i+1位(也就是例子中的4,即n-1)構成的逆序數也是n-i-2。顯然,由於保持了遞減的特徵,剩下的第i+3到第n位的逆序數為C(n-i-2,2)。(這里姑且認為C(1,2)=1)這時總的逆序數為

t1 =C(n-i-2,2)+2*(n-i-2)

=(n-i-2)(n-i-3)/2+2*(n-i-2)

=(n-i-2)(n-i+1)/2.

而q的逆序數

t2=C(n-i,2)

=(n-i)(n-i-1)/2.

用t2-t1,得到定值1。也就是說,無論n取何值,t2總是大於t1。

如果再將數n向右移動一位,這時我們只有保持前1到i+1位(即例子中的1,2,3,4)不變才能夠保證之後的變換能夠使逆序數最大(這個很顯然,不特別證明)。然而,當前面的i+1位確定了以後,怎麼變換後面的數字才能夠使總逆序數最大呢?還是要原來n後面最大的數填補到第i+1位。我們已經證明,這樣做是不如不換優的。所以,不存在一個小於q的排列p使p的逆序數為m。證畢。

[命題2]在命題1所設定的排列q的基礎上,我們將數n後面的第k小數與數n的前一個數(即i)交換,然後使數n後面保持逆序。這樣得到的新排列所含的逆序數為t=C(n-i,2)+k,且這個排列是逆序數為t的最小排列。

證明:首先,在此強調一下排列q的結構,如圖一:

由於操作以後數n之後仍然保持逆序,所以從第i+1到第n位的逆序數仍為C(n-i,2)。對於x來說,交換之前後面有k-1個比它小的數,交換之後又加上了一個,所以x所擁有的逆序數(即以x為左的逆序數)為k-1+1=k,此時總的逆序數為C(n-i,2)+k。

對於新排列逆序數為t=C(n-i,2)+k的最小排列的證明與命題1的證明相似,在此處不加以詳細證明。

到此我們可以得出,命題2也是真命題。

有了這兩個命題作基礎,我們很容易就能夠得到這道題的演算法。首先利用命題1,二分查找找到數n的位置,我們可以得到數n在這個位置的時候形如q的排列的逆序數t。然後計算t與m的差值,得出k,然後根據命題2進行變換,最後得出要求的排列。

.

參考代碼:

+ View Code

『玖』 c語言 請問逆序數的優化編程演算法怎麼做到

int getRevange(int n);

int getRevange(int n)
{
int t = 0;

for(; n; n /= 10)

t = t*10 + n%10;

return t;

}

解釋一個這段程序:
假設n為12345
n%10 => 5 t = t*10 * n%10; t=> 0*10+5 => 5 n /= 10; n => 1234
n%10 => 4 t = t*10 * n%10; t=> 5*10+4 => 54 n /= 10; n => 123
n%10 => 3 t = t*10 * n%10; t=> 54*10+3 => 543 n /= 10; n => 12
n%10 => 2 t = t*10 * n%10; t=> 543*10+2 => 5432 n /= 10; n => 1
n%10 => 1 t = t*10 * n%10; t=> 5432*10+1 => 54321 n /= 10; n => 0
循環結束,t的值正好是n的逆序數。

『拾』 設有數組A[n],n>1,試設計一個演算法,求數組A[n]的逆序

方法一:最原始的方法,利用兩重循環進行枚舉。該演算法的時間復雜度為O(n^2)。 C++代碼如下: int count_inversion(int *a,int N) { int count = 0; int i,j; for (i = 0 ;i < N ;i ++) for(j = i + 1; j < N ;j++) if (a[i] > a[j]) count ++; return count; } Pascal代碼如下: vari,j,k,n:longint; a:array[1..1000000]of longint; begin readln(n); for i:=1 to n do read(a[i]); k:=0; for i:=1 to n-1 do for j:=i+1 to n do if a[i]>a[j] then inc(k); writeln(k); end. 方法二:利用歸並排序的思想求解逆序對的個數,這是目前解決該問題的一種較為高效的演算法。該演算法的時間復雜度為O(nlogn)。 C++代碼如下: void merge_inversion(int *a,int l,int m,int r) { int i,j,k; int n1 = m - l + 1; int n2 = r - m; int *L = (int *)calloc(n1,sizeof(int)); int *R = (int *)calloc(n2,sizeof(int)); for(i = l; i <=m ;i ++) L[i-l]=a; for(j = m +1 ;j <= r ;j ++) R[j -m-1] = a[j]; i = 0 ; j = 0 ; for(k = l ;k <= r ;k ++) { if ( i < n1 && j < n2 ) { if( L < R[j]) { a[k]=L[i++]; globa_count += n2-1-j+1; } else a[k]=R[j++]; } else break; } // process if one part terminately early if (i == n1 && j < n2) while(j < n2) a[k++]=R[j++]; if (i < n1 && j == n2) while(i < n1) a[k++]=L[i++]; free(L); free(R); } Pascal代碼如下: type arr=array[1..1000000]of longint; vari,n,k:longint; a:arr; procere merge(var a:arr; l,x,r:integer); vari,j,p:integer; b:arr; begin i:=l; j:=x+1; p:=l; while p<=r do begin if (i<=x)and((j>r)or(a[i]<=a[j])) then begin b[p]:=a[i]; inc(i); end else begin b[p]:=a[j]; inc(j); k:=k+x-i+1; end; inc(p); end; for i:=l to r do a[i]:=b[i]; end; procere msort(var a:arr; l,r:integer); var x:integer; begin if l<>r then begin x:=(l+r) div 2; msort(a,l,x); msort(a,x+1,r); merge(a,l,x,r); end; end; begin readln(n); for i:=1 to n do read(a[i]); k:=0; msort(a,1,n); writeln(k); end.

熱點內容
單片機android 發布:2024-09-20 09:07:24 瀏覽:765
如何提高三星a7安卓版本 發布:2024-09-20 08:42:35 瀏覽:664
如何更換伺服器網站 發布:2024-09-20 08:42:34 瀏覽:311
子彈演算法 發布:2024-09-20 08:41:55 瀏覽:289
手機版網易我的世界伺服器推薦 發布:2024-09-20 08:41:52 瀏覽:817
安卓x7怎麼邊打游戲邊看視頻 發布:2024-09-20 08:41:52 瀏覽:162
sql資料庫安全 發布:2024-09-20 08:31:32 瀏覽:94
蘋果連接id伺服器出錯是怎麼回事 發布:2024-09-20 08:01:07 瀏覽:507
編程鍵是什麼 發布:2024-09-20 07:52:47 瀏覽:658
學考密碼重置要求的證件是什麼 發布:2024-09-20 07:19:46 瀏覽:481