標籤:style class blog code http color
題目:在數組中的兩個數字如果前面一個數字大於後面一個數字,則這兩個數字組成一個逆序對
題解分析:
首先應該想到很簡單的一種解法,順序遍曆數組,對每個數,逐個比較該數字和其以後的數字,T(n) = O(n^2)
(1)總體的意思就是將數組分成兩段,首先求段內的逆序對數量,比如下面兩段代碼就是求左右兩端數組段內的逆序對數量
count += Merge(data, temp, first, mid);//找左半段的逆序對數目count += Merge(data, temp, mid + 1, end);//找右半段的逆序對數目
(2)然後求相鄰兩個有序段間的逆序對數量
首先兩個相鄰段都是各自有序的,範圍分別是:[first, mid] [mid + 1, last]
我們設兩個遊標 i 和 j 分別指示兩個有序段的最末位置: i = mid j = last
注意:我們求兩段之間的逆序對的同時需要將這兩段最終保持有序
這裡需要有一個temp數組,先將結果暫存於temp中,最後將temp複製到data中
暫存temp時,我們從最末位置last開始向前移動
我們不斷比較data[i] 和 data[j]:
如果data[i] > data[j] ,因為 後一段是有序的,所以data[i]大於後一段中 [mid + 1, j]中的每個值, 此時需要暫存temp,並且增加逆序數
如果data[i] <= data[j], 此時只需要暫存temp即可
int Merge(std::vector<int>& data, std::vector<int>& temp, int first, int last){ if (first == last) { temp.at(first) = data.at(first); return 0; } int mid = first + (last - first) / 2; int left = Merge(data, temp, first, mid); int right = Merge(data, temp, mid + 1, last); int i = mid; int j = last; int tempIndex = last; int count = 0; while (i >= first && j >= mid + 1) { if (data.at(i) > data.at(j)) { temp.at(tempIndex--) = data.at(i--); count += (j - (mid + 1) + 1); } else { temp.at(tempIndex--) = data.at(j--); } } while (i >= first) { temp.at(tempIndex--) = data.at(i--); } while (j >= mid + 1) { temp.at(tempIndex--) = data.at(j--); }
std::copy(temp.begin() + first, temp.begin() + last + 1, data.begin() + first); return left + right + count;}int InvertPairs(std::vector<int>& data, std::vector<int>& temp){ if (data.size() == 0) { return 0; } int count = Merge(data, temp, 0, data.size() - 1); return count;}