【劍指offer】陣列中的逆序對
轉載請註明出處:http://blog.csdn.net/ns_code/article/details/27520535
- 題目描述:
- 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個陣列,求出這個陣列中的逆序對的總數。
- 輸入:
- 每個測試案例包括兩行:第一行包含一個整數n,表示陣列中的元素個數。其中1 <= n <= 10^5。第二行包含n個整數,每個陣列均為int型別。
- 輸出:
- 對應每個測試案例,輸出一個整數,表示陣列中的逆序對的總數。
- 樣例輸入:
4 7 5 6 4
- 樣例輸出:
5
思路:最簡單的方法是順序陣列,將每個數字與後面的比較,統計逆序對的個數,這種方法的時間複雜度為O(n*n),這種方法寫出的程式碼在九度OJ上測試,會超時。劍指offer給出了歸併排序的思路,這個有點難想到啊,也可能是我太弱了,根本沒往這方面想!理解了思路,就不難了,將陣列劃分成兩個子陣列,再將子陣列分別劃分成兩個子陣列,統計每個子陣列內的逆序對個數,並將其歸併排序,再統計兩個子陣列之間的逆序對個數,並進行歸併排序。這就是歸併排序的變種,在歸併排序程式碼的基礎上稍作改進即可。
合理還要注意一點:全域性變數count不能宣告為int型,必須為long long型。因為題目中說陣列最大為10^5,那麼最大逆序對為(10^5-1)*10^5/2,這個數大約在50億左右,超過了int型的表示範圍。
AC程式碼如下:
#include<stdio.h>
#include<stdlib.h>
/*
統計兩個子陣列之間的逆序對
*/
long long MergePairsBetweenArray(int *arr,int *brr,int start,int mid,int end)
{
int i = mid;
int j = end;
int k = end; //輔助陣列的最後一位
long long count = 0;
//設定兩個指標i,j分別從右往左依次比較,
//將較大的依次放入輔助陣列的右邊
while(i>=start && j>=mid+1)
{
if(arr[i] > arr[j])
{
count += j-mid;
brr[k--] = arr[i--];
}
else
brr[k--] = arr[j--];
}
//將其中一個陣列中還剩下的元素拷貝到輔助陣列中,
//兩個迴圈只會執行其中的一個
while(i>=start)
brr[k--] = arr[i--];
while(j>=mid+1)
brr[k--] = arr[j--];
//從輔助陣列中將元素拷貝到原陣列中,使其有序排列
for(i=end;i>k;i--)
arr[i] = brr[i];
return count;
}
/*
統計陣列中的所有的逆序對
*/
long long CountMergePairs(int *arr,int *brr,int start,int end)
{
long long PairsNum = 0;
if(start<end)
{
int mid = (start+end)>>1;
PairsNum += CountMergePairs(arr,brr,start,mid); //統計左邊子陣列的逆序對
PairsNum += CountMergePairs(arr,brr,mid+1,end); //統計右邊子陣列的逆序對
PairsNum += MergePairsBetweenArray(arr,brr,start,mid,end); //統計左右子陣列間的逆序對
}
return PairsNum;
}
/*
將函式封裝起來
*/
long long CountTotalPairs(int *arr,int len)
{
if(arr==NULL || len<2)
return 0;
int *brr = (int *)malloc(len*sizeof(int));
if(brr == NULL)
exit(EXIT_FAILURE);
long long sum = CountMergePairs(arr,brr,0,len-1);
free(brr);
brr = NULL;
return sum;
}
int main()
{
int n;
while(scanf("%d",&n) != EOF)
{
int *arr = (int *)malloc(n*sizeof(int));
if(arr == NULL)
exit(EXIT_FAILURE);
int i;
for(i=0;i<n;i++)
scanf("%d",arr+i);
printf("%lld\n",CountTotalPairs(arr,n));
free(arr);
arr = NULL;
}
return 0;
}
/**************************************************************
Problem: 1348
User: mmc_maodun
Language: C
Result: Accepted
Time:100 ms
Memory:1696 kb
****************************************************************/
相關文章
- 劍指Offer-37-陣列中逆序對陣列
- 劍指offer——陣列中的逆序對C++(75%)陣列C++
- LeetCode C++ 劍指 Offer 51. 陣列中的逆序對【歸併排序/樹狀陣列/線段樹】LeetCodeC++陣列排序
- 劍指 offer(1) -- 陣列篇陣列
- 【劍指offer】二維陣列中的查詢陣列
- 劍指Offer--陣列中重複的數字陣列
- 【劍指offer】【1】二維陣列中的查詢陣列
- 《劍指offer》:[51]陣列中的重複數字陣列
- 陣列中的逆序對陣列
- 【劍指offer】把陣列排成最小的數陣列
- 二維陣列中的查詢——牛客劍指offer陣列
- 劍指Offer-連續子陣列中的最大和陣列
- 劍指 Offer 04. 二維陣列中的查詢陣列
- 劍指offer之順序列印陣列陣列
- 【劍指offer】調整陣列順序陣列
- 劍指offer:旋轉陣列的最小數字陣列
- 劍指offer 旋轉陣列的最小數字陣列
- 【劍指offer】連續子陣列的最大和陣列
- 【劍指offer】旋轉陣列的最小值陣列
- 劍指 offer 第一題: 二維陣列中的查詢陣列
- 1. 二位陣列中的查詢(劍指offer)陣列
- 《劍指offer》:[52]構建乘積陣列陣列
- 《劍指offer》:[66]矩陣中的路徑矩陣
- 劍指offer 陣列中只出現一次的數字陣列
- 劍指Offer-34-把陣列排成最小的數陣列
- 劍指offer——把陣列排成最小的數C++陣列C++
- 劍指offer-轉陣列的最小數字-php陣列PHP
- 劍指Offer-把陣列中的數排成一個最小的數陣列
- 劍指Offer積累-JZ1-二維陣列中的查詢陣列
- Leetcode 劍指 Offer 03. 陣列中重複的數字LeetCode陣列
- 劍指offer刷題之路--1.陣列中重複的數字陣列
- 劍指 Offer 56 - I. 陣列中數字出現的次數陣列
- 《劍指offer》:[40]陣列中只出現一次的數字陣列
- 【劍指offer】陣列中只出現一次的數字(1)陣列
- 【劍指offer】陣列中只出現一次的數字(2)陣列
- 歸併排序-陣列中的逆序對排序陣列
- 【劍指offer】7.旋轉陣列的最小數字陣列
- 劍指 Offer 42.連續子陣列的最大和陣列