1. 程式人生 > >運用BIT處理氣泡排序的交換次數問題

運用BIT處理氣泡排序的交換次數問題

題意:給定一個1~n的排列a0,a1,a2,.....,a(n-1),求對這個數列進行氣泡排序所需要的交換次數。

在資料較大時,用常規的雙重for迴圈來求解交換次數就會因為複雜度太高而存在TLE的情況,所以可以利用樹狀陣列善於查詢兩個數之間的數字和的優勢進行解題。

首相樹狀陣列的基本操作就是BIT的求和以及BIT的值的更新,那麼如何要在沒有if語句比較的情況下進行前後數值大小的比較進而求出交換次數和,首相應該瞭解交換的次數和即為陣列中存在的i<j,array[i]>array[j]的逆序樹對的和,所以對於每個位置的數array[i]只要能夠求出其之前存在的大於這個數的個數即可,而在陣列中兩個數在不滿足i<j&&array[i]<=array[j]的情況就是逆序數對的數量,則可以將其轉變成i-非逆序數對的個數。

以陣列array[9]={1,2,3,4,5,6,7,8,9}為例,用sum(array[i])函式求出在在這次操作之前i位置前有多少個比array[i]要小的數,即非逆序數,再用add(array[i],1)函式在i位置後面說明該位置之前已有多少比這個數要小的數的個數,經過一重for迴圈即可計算出所有的i位置前的逆序樹,相加和即為氣泡排序需要交換的交換次數。每次進行sum和add操作的負複雜度為O(log n),所以該方法的複雜度為O(n*log n)。注意:BIT中的下標表示的是array陣列中的元素值,所以在陣列元素少或者元素的值分別為1~n中的整數,則可以直接進行樹狀陣列BIT的建立,不然需要先將陣列元素值進行離散化來達到符合題目限制條件。

體悟:樹狀陣列利用位置特性做到了不用if語句比較前後數值大小而求出了交換次數,在演算法的複雜度上也較樸素演算法有大的提升。這主要是依賴於樹狀陣列的善於計算區間數值和做到的。樹狀陣列使用的難點主要還是用的次數太少,寫起程式碼來不足夠熟練,還以還是應該通過訓練來解決這一問題。