每日一題 45 陣列中的逆序對

2021-06-16 16:27:23 字數 2795 閱讀 4132

題目來自劍指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 輸...