1. 程式人生 > 實用技巧 >【C++】逆序對計數問題

【C++】逆序對計數問題

還是分治的思想,解決方法利用了歸併排序。具體可以看一下這篇部落格。

第三章:分治II - 不妨不妨,來日方長 - 部落格園 (cnblogs.com)

C++程式碼如下,可以在VS直接執行。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int sort_merge_recursive(vector<int>& data, int left, int right);
int sort_crossing_merge_recursive(vector<int
>& data, int left, int mid, int right); void merge(vector<int>& data, int left, int mid, int right); int main() { /* 使用歸併排序的思路來解決逆序數對計數的問題:還是分治的思想,分解成小問題、解決小問題、合併問題解。 陣列的分解跟歸併排序裡頭的分解是一樣的,都是二分,最後分到只剩單獨一個元素。不同的是,歸併排序直接 比較分解之後子陣列的大小,在合併的時候按照從小到大或者從大到小的順序往新的容器裡放就行了。 逆序對問題,分解的步驟跟歸併排序是一模一樣的,在合併的過程中,兩個子陣列之間比較大小進行排序時, 恰好可以判斷子陣列逆序對,條件在程式碼中後面註釋了,就加了那一句程式碼;跟陣列的最大子陣列和不同的是,那個 是求的左子陣列、右子陣列、跨中心陣列中最大的一個,而求子陣列逆序對,是把這三者相加。
*/ vector<int> data = { 7,5,6,4}; //獲取序列元素個數 int length = data.size(); int left = 0; int right = 3; int number=0; vector<int> result; number = sort_merge_recursive(data, left, right); cout << "逆序對的個數是:"<< number << endl; for (int i = 0
; i < length; i++) { cout << data.at(i) << " "; } } int sort_merge_recursive(vector<int>& data, int left, int right) { if (left >= right) return 0; else { int mid = (left + right) >> 1; int s1, s2, s3, s_end; s1 = sort_merge_recursive(data, left, mid);//左子陣列 s2 = sort_merge_recursive(data, mid + 1, right);//右子陣列 s3 = sort_crossing_merge_recursive(data, left, mid, right);//跨中心陣列 s_end = s1 + s2 + s3;//求三個的和 return s_end; } } int sort_crossing_merge_recursive(vector<int>& data, int left, int mid, int right) { int i = left; int j = mid + 1; int number=0; vector<int> temp; temp.resize(right - left + 1); int k = 0; while (i <= mid && j <= right) { if (data.at(i) > data.at(j)) { temp.at(k++) = data.at(j++); number += mid-i+1;//這裡是相比于歸並排序增加的部分 } else { temp.at(k++) = data.at(i++); } } while (i <= mid) { temp.at(k++) = data.at(i++); } while (j <= right) { temp.at(k++) = data.at(j++); } for (int n = 0; n < k; n++) { data.at(left++) = temp.at(n); } return number; }