-9 逆序输出一个整数的各位数字_逆序对个数(归并排序)
題目描述
輸入 N 組數據,對每組數據輸出逆序對個數。
輸入
對于每組測試用例,第一行輸入此組數據元素個數 x,接下來 x 行,每行一個數,表示元素。(1≤x≤500000)(1≤x≤500000)
當讀入的元素個數 x 為零時,程序結束。
輸出
對于每組測試用例,輸出一個數,表示逆序對個數。
樣例輸入
5 9 1 0 5 4 3 1 2 3 0樣例輸出
6 0數據規模與約定
時間限制:1 s
內存限制:256 M
100% 的數據保證 1≤x≤500000
解答:
逆序對定義:設 A 為一個有 n 個數字的有序集 (n>1),其中所有數字各不相同。如果存在正整數 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],則 <A[i], A[j]> 這個有序對稱為 A 的一個逆序對,也稱作逆序數。
根據逆序對定義可知,如果尋找一個序列中逆序對的數量相當于尋找一個序列中每個數后面有多少個小于自己的數,將這些數加起來就是最后的答案。
所以一種暴力的算法就直接出來了,兩層for循環,每次取一個數依次和他后面的數進行比較,如果小于這個數,逆序對數加1否則繼續向后比較。這也是最暴力的算法,時間復雜度O(n)。
上述算法只是為了找到每一個數后面有多少個數小于他自己,,其實可以對其進行排序,然后看每一個數進行了多少次交換。對交換的次數進行統計即可得到最后的結果。排序有好多算法,最好的排序算法是快速排序,但他是不穩定的,并不適合這道題,所以我們選擇一種穩定,并且相對效率較高的歸并排序。下面附上代碼。
#include<iostream> #include<algorithm> using namespace std; #define MAX_N 500000 int n, a[MAX_N +5], temp[MAX_N + 5]; long long num;void merge(int begin, int mid, int end) {int i = begin;int j = mid + 1;int k = begin;while (i <= mid && j <= end){if (a[i] > a[j]) {temp[k] = a[j];k++;j++;num += mid - i + 1; //對交換的次數進行統計} else {temp[k] = a[i];k++;i++;}}while (i <= mid) {temp[k] = a[i];k++;i++;}while (j <= end) {temp[k] = a[j];k++;j++;}for (int p = begin; p <= end; p++)a[p] = temp[p]; }void mergesort(int begin, int end) { //歸并排序if (begin >= end)return;int mid = (begin + end) / 2;mergesort(begin, mid);mergesort(mid + 1, end);merge(begin, mid, end); }int main() {while (1) {cin >> n;if (n == 0) break;for (int i = 0; i < n; i++) cin >> a[i];num = 0;mergesort(0, n - 1);cout << num << endl;} ?return 0; }以上就是本題的代碼,有什么問題歡迎隨時提問。
總結
以上是生活随笔為你收集整理的-9 逆序输出一个整数的各位数字_逆序对个数(归并排序)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言文件实现通信录程序,学C三个月了,
- 下一篇: 输入快捷键显示未知命令_「干货」华为VR