?劍指 Offer 51. 數(shù)組中的逆序對
難度:困難
在數(shù)組中的兩個數(shù)字,如果前面一個數(shù)字大于后面的數(shù)字,則這兩個數(shù)字組成一個逆序對。輸入一個數(shù)組,求出這個數(shù)組中的逆序對的總數(shù)。
示例 1:
輸入: [7,5,6,4]
輸出: 5
限制:
0 <= 數(shù)組長度 <= 50000
??思路:歸并排序
預備知識
「歸并排序」是用分治思想,分治模式在每一層遞歸上有三個步驟:
-
分解(Divide):將
n
個元素分成個含n/2
個元素的子序列。 - 解決(Conquer):用 合并排序法 對兩個子序列遞歸的排序。
- 合并(Combine):合并兩個已排序的子序列已得到排序結果。
具體的我們以一組無序數(shù)列{14,12,15,13,11,16}
為例分解說明,如下圖所示:
在待排序序列長度為 1
的時候,遞歸開始「回升」,因為我們默認長度為 1
的序列是排好序的。
具體思路:
那么求逆序對和歸并排序又有什么關系呢?關鍵就在于「歸并」當中「并」的過程。
合并階段 本質上是 合并兩個排序數(shù)組 的過程:
- 每當遇到
左子數(shù)組當前元素
>
右子數(shù)組當前元素
時,意味著- 「
左子數(shù)組當前元素i 至 末尾元素m
」 與 「右子數(shù)組當前元素
」 構成了若干 「逆序對
」 ; - 逆序對數(shù)
cnts
+=(m - i + 1)
。
- 「
- 考慮在歸并排序的合并階段統(tǒng)計「逆序對」數(shù)量,完成歸并排序時,也隨之完成所有逆序對的統(tǒng)計。
??代碼:(C++、Java)
C++
class Solution {
private:
int cnts = 0;
void mergeSort(vector<int>& nums, vector<int>& tmp, int l, int h){
if(h - l < 1) return;
//分解
int m = l + (h - l) / 2;
mergeSort(nums, tmp, l, m);
mergeSort(nums, tmp, m + 1, h);
//解決 + 合并
int k = l, i = l, j = m + 1;
while(i <= m || j <= h){
if(i > m) tmp[k++] = nums[j++];
else if(j > h || nums[i] <= nums[j]) tmp[k++] = nums[i++];
else{//此時i~m對應數(shù)組中的數(shù)都比nums[j]大
tmp[k++] = nums[j++];
cnts += (m - i + 1);
}
}
for(k = l; k <= h; k++){
nums[k] = tmp[k];
}
}
public:
int reversePairs(vector<int>& nums) {
vector<int> tmp(nums.size());//輔助數(shù)組,臨時記錄中間合并的子數(shù)組
mergeSort(nums, tmp, 0, nums.size() - 1);
return cnts;
}
};
Java
class Solution {
private int cnts = 0;
private void mergeSort(int[] nums, int[] tmp, int l, int h){
if(h - l < 1) return;
//分解
int m = l + (h - l) / 2;
mergeSort(nums, tmp, l, m);
mergeSort(nums, tmp, m + 1, h);
//解決 + 合并
int k = l, i = l, j = m + 1;
while(i <= m || j <= h){
if(i > m) tmp[k++] = nums[j++];
else if(j > h || nums[i] <= nums[j]) tmp[k++] = nums[i++];
else{//此時i~m對應數(shù)組中的數(shù)都比nums[j]大
tmp[k++] = nums[j++];
cnts += (m - i + 1);
}
}
for(k = l; k <= h; k++){
nums[k] = tmp[k];
}
}
public int reversePairs(int[] nums) {
int[] tmp = new int[nums.length];//輔助數(shù)組,臨時記錄中間合并的子數(shù)組
mergeSort(nums, tmp, 0, nums.length - 1);
return cnts;
}
}
?? 運行結果:
?? 復雜度分析:
-
時間復雜度:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),其中
n
為數(shù)組的長度,同歸并排序 O ( n l o g n ) O(nlogn) O(nlogn)。 - 空間復雜度: O ( n ) O(n) O(n),歸并排序需要用到一個臨時數(shù)組。
題目來源:力扣。文章來源:http://www.zghlxwxcb.cn/news/detail-676412.html
放棄一件事很容易,每天能堅持一件事一定很酷,一起每日一題吧!
關注我LeetCode主頁 / CSDN—力扣專欄,每日更新!文章來源地址http://www.zghlxwxcb.cn/news/detail-676412.html
注: 如有不足,歡迎指正!
到了這里,關于(排序) 劍指 Offer 51. 數(shù)組中的逆序對 ——【Leetcode每日一題】的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!