題目來自劍指offer
題目:
舉例:
思路:方法(1):
暴力方法:對於陣列中任意兩個數,均做一次判定,判斷是否為逆序對。
時間複雜度:o(n^2)。
方法(2):
類似於歸併排序。
(1)首先把陣列分成兩個長度均等的陣列
(2)分布對這兩個陣列排序(小到大)。
(3)之後再求逆序對,同時對把這兩個陣列合併到乙個陣列
時間複雜度為o(nlogn)
為什麼這麼可以減少時間消耗呢?
計算逆序對時,先算每乙個區間內的逆序對,之後再算區間間的逆序對。
在算區間間的逆序對時,兩個陣列均是有序的,對於有序陣列中的
每乙個元素,可以再o(1)的時間算出其逆序對
舉例:對於陣列:7,5,4,6
先分成兩個陣列 7,5和4,6.
之後對兩個陣列進行排序,得到:
有序陣列(1):5,7
有序陣列(2):4,6
之後逆序歸併,並求逆序
最大數為7,由於7在左邊陣列中,且7>6(右邊陣列的最大數),
則7與第二個陣列6左邊的資料均產生逆序對。同時把7放到臨時陣列中。(本次迴圈找出兩個逆序對)
之後取得最大值為6,由於6在右邊的陣列中,則不會產生逆序對。則直接放入臨時陣列中。
之後取得最大值為5、由於5在左邊陣列中,且5>4(右邊陣列的最大數),
則5與第二個陣列4左邊的資料均產生逆序對。同時把5放到臨時陣列中。(本次迴圈找出乙個逆序對)
。。。**:
#include #include using namespace std;
/*對陣列narr的有序區間[nstart,nmid]和[nmid+1,nend]進行歸併,放到narr中*/
void merge(int narr,int nstart,int nmid,int nend,int* ptmp,int& ncount)
else
}assert(ncur >= nstart && ncur <= nend);
//處理剩餘的陣列,注意,剩餘的肯定是那些比較小的數,此時無論這些小數在左邊還是在右邊都不對逆序對個數產生影響
while (nleftstart <= nleftend)
while (nrightstart <= nrightend)
assert(ncur == nstart - 1);
//把臨時陣列中的資料移動到新陣列中
for (ncur = nend;ncur >= nstart;ncur--)//和下面的函式區別之處 }
/*對narr的區間[nstart,nend]進行排序,並把排序的結果放入narr中*/
void findreverseorder(int narr,int nstart,int nend,int* ptmp,int& ncount)
}int findreverseorder(int narr,int nlen)
int main()
; int narr[100] = ;
cout上述**存在乙個問題:
對於兩個陣列進行歸併時,總是把歸併的結果先放入ptmp中,之後在把排序好的陣列轉存到陣列narr中。
注意,這裡就存在乙個冗餘操作。即資料的來回存放。不過該優化不會改變時間複雜度。
優化**:
思想:當結果歸併到臨時陣列ptmp後,就先不用歸併到narr中,可以直接在陣列ptmp處理,在之後那次的處理中,臨時陣列就為narr了。即臨時陣列不僅僅限定於ptmp,這樣就不用對每次歸併的結果轉來轉去的啦。
#include #include using namespace std;
/*求解陣列narr中的兩個有序區間的逆序對,並把兩個有序區間歸併到ptmp中*/
void merge(int narr,int nstart,int nmid,int nend,int* ptmp,int& ncount)
else
}assert(ncur >= nstart && ncur <= nend);
//處理剩餘的陣列,注意,剩餘的肯定是那些比較小的數,此時無論這些小數在左邊還是在右邊都不對逆序對個數產生影響
while (nleftstart <= nleftend)
while (nrightstart <= nrightend)
assert(ncur == nstart - 1);
}/*對narr的區間[nstart,nend]進行排序,並把排序的結果放入ptmp中*/
void findreverseorder(int narr,int nstart,int nend,int* ptmp,int& ncount)
}int findreverseorder(int narr,int nlen)
{ assert(narr && nlen > 0);
int ncount = 0;
int* ptmp = new int[nlen];
memcpy(ptmp,narr,nlen * sizeof(int));//很重要,別忘了。
findreverseorder(ptmp,0,nlen - 1,narr,ncount);
//此時陣列narr中存放的元素是有序的
//for (int i = 0;i < 7;i++)
//{// cout<
每日一題 數對
本題來自牛客網,為網易2019年校招題之一。點我跳轉 題目描述 牛牛以前在老師那裡得到了乙個正整數數對 x,y 牛牛忘記他們具體是多少了。但是牛牛記得老師告訴過他x和y均不大於n,並且x除以y的餘數大於等於k。牛牛希望你能幫他計算一共有多少個可能的數對。輸入描述 輸入包括兩個正整數n,k 1 n 1...
劍指 45,陣列中的逆序對
題目描述 在陣列中的兩個數字,如果前面乙個數字大於後面的數字,則這兩個數字組成乙個逆序對。輸入乙個陣列,求出這個陣列中的逆序對的總數p。並將p對1000000007取模的結果輸出。即輸出p 1000000007 輸入1,2,3,4,5,6,7,0輸出7 思路 利用歸併排序,從分組的末尾開始比較,如果...
LeetCode 每日一題 陣列中數字出現的次數
陣列中數字出現的最大次數 乙個整型陣列 nums 裡除兩個數字之外,其他數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。要求時間複雜度是o n 空間複雜度是o 1 示例 1 輸入 nums 4,1,4,6 輸出 1,6 或 6,1 示例 2 輸入 nums 1,2,10,4,1,4,3,3 輸...