分治演算法 求陣列逆序數
阿新 • • 發佈:2019-02-15
題目:在陣列中的兩個數字如果前面一個數字大於後面一個數字 則這兩個數字組成一個逆序對 輸入一個數組 求這個陣列中逆序對的個數
先把陣列分割成子陣列 先統計出子陣列內部的逆序對的數目 然後再統計出兩個相鄰子陣列之間的逆序對的數目 統計逆序對的過程中 還需要對陣列進行排序 這類似與歸併排序 演算法的時間複雜度為O(nlogn) 空間複雜度為O(n)
歸併排序
求逆序對數~~~#include<iostream> using namespace std; void merge(int *A, int *temp, int start, int mid, int end) { int a = start; int b = mid+1; int c = end; int d = start; while (a <= mid && b <=end ) { if (A[a] < A[b]) temp[d++] = A[a++]; else temp[d++] = A[b++]; } while (a != mid + 1) temp[d++] = A[a++]; while (b != end + 1) temp[d++] = A[b++]; for (int i = start;i <= end;i++) A[i] = temp[i]; } void sortg(int *A,int *temp ,int a,int b) { if (a < b) { int mid = a + (b - a) / 2; sortg(A, temp, a, mid); sortg(A, temp, mid + 1, b); merge(A, temp, a, mid, b); } } int main() { int A[] = { 7,4,10,6,9,9,2,3 }; int n = 8; int *t = new int[n]; memset(t, 0, sizeof(int)*n); sortg(A, t, 0, n - 1); for (int i = 0;i < n;i++) cout << A[i] << ' '; delete[]t; return 0; }
#include<iostream> using namespace std; int merge(int *A, int *temp, int start, int mid, int end) { int a = end; int b = mid; int c = end; int t = 0; while (b >= start && a >= mid + 1) { if (A[b] > A[a]) { temp[c--] = A[b--]; t += a - mid; } else temp[c--] = A[a--]; } while (a >= mid + 1) temp[c--] = A[a--]; while (b >= start) temp[c--] = A[b--]; for (int i = start;i <= end;i++) A[i] = temp[i]; return t; } int Nimum(int *A, int *temp, int a, int b) { if (a==b) return 0; else { int mid = a + (b - a) / 2; int left=Nimum(A, temp, a, mid); int right=Nimum(A, temp, mid + 1, b); int num=merge(A, temp, a, mid, b); return left + right + num; } } int main() { int A[] = { 7,4,5,3,8,2}; int n =6; int *t = new int[n]; memset(t, 0, sizeof(int)*n); int num=Nimum(A, t, 0, n - 1); for (int i = 0;i < n;i++) cout << A[i] << ' '; cout << endl<< num << endl; delete[]t; return 0; }