逆序對問題:
給定乙個陣列,如:[8, 8, 3, 0, 6, 8, 9, 3],前大後小的資料即為乙個逆序對,例如[8,3]、[3,0],求出這一陣列中的所有逆序對。
思路:暴力法:設定雙重迴圈,數量標誌,比較兩兩之間的大小,符合逆序對標準則數量標誌+1,複雜度o(n^2),本例中不考慮這個方法。
合併排序:合併排序是將乙個陣列均分,遞迴呼叫對子陣列進行排序,然後將子陣列合併,主要使用分治思想。在本題中,示例陣列可分為:
[8,8,3,0]
[6,8,9,3]
分別排序之後為
a: [0,3,8,8]
b: [3,6,9,8]
設定i=0,j=0分別標誌a、b陣列,在合併的過程中,比較a[i]、b[j],若a[i]>b[j] 則將b[i]放入原陣列,i++,同理將資料依次放入。
解決逆序對的最關鍵的就是合併這一步,假設a[i]>b[i]了,那麼a[i]之後的所有資料,都是大於b[i]的,此時設定乙個標識,用於記錄資料,返回這個資料,遞迴,最後就可以得到所有逆序對了,這一方法的時間複雜度為o(nlogn),在陣列資料非常多的時候可以明顯感受到它的效率。
以下是它的實現**,其實就是在合併排序的基礎上,記錄一下逆序對個數:
本例中測試了百萬個資料,以下是執行結果:public static void dectest(int a)
private static int mergesort(int a)
int b = new int[n / 2];
system.arraycopy(a, 0, b, 0, n / 2);
int c;
if (n % 2 == 0) else
count += mergesort(b);
count += mergesort(c);
count += merge(b, c, a);
return count;
}private static int merge(int b, int c, int a) else
k++;
}if (i == p)
} else if (j == q)
}return count;
}public static void main(string args)
long t = system.currenttimemillis();
dectest(a);
system.out.print("耗時:");
system.out.println(system.currenttimemillis() - t);
}
百萬個資料119mm執行完畢,速度是十分可觀的。
合併演算法求逆序對
include include include include using namespace std define num 5 int number 0 void mergesort int a,int length void mergepart int a,int b,int l,int r v...
分治演算法 求逆序對
題目 給定乙個序列a1,a2,an,如果存在iaj,那麼我們稱之為逆序對,求逆序對的數目。解析 這道題 只要雙重迴圈就可以解決 但是因為題目要求 所以被迫使用更麻煩的方法 這道題其實就是歸併排序 至於為何 就不說了 歸併排序 就是將乙個陣列 不斷分割 一直分割到只剩乙個為止 乙個的話 必定是有序的 ...
演算法之逆序對
假設a 1.n 是乙個有n個不同數的陣列。若ia j 則對偶 i,j 稱為a的乙個逆序對 inversion 列出陣列的5個逆序對 由集合中的元素構成的什麼陣列具有最多的逆序對?它有多少逆序對?插入排序的執行時間與輸入陣列中的逆序對的數量有什麼關係?給出乙個求在n個元素的任何排列中逆序對數量的演算法...