题目:493. 翻转对
题目描述:
给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] ,
我们就将 (i, j) 称作一个重要翻转对。
你需要返回给定数组中的重要翻转对的数量。
示例 1:
输入: [1,3,2,3,1]
输出: 2
示例 2:
输入: [2,4,3,5,1]
输出: 3
注意:
给定数组的长度不会超过50000。
输入数组中的所有数字都在32位整数的表示范围内。
网址:https://leetcode-cn.com/problems/reverse-pairs/
解题思路:
采用的是归并的思想;
下图是分解的全过程:
例如: [2,4,3,5,1]的求解过程
class Solution {
public:
int reversePairs(vector<int>& nums) {
return mergeSort(nums, 0, nums.size() - 1);
}
int mergeSort(vector<int>& nums, int left, int right) {
if (left >= right) return 0;
int mid = left + (right - left) / 2;
int res = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);
for (int i = left, j = mid + 1; i <= mid; ++i) {
while (j <= right && nums[i] / 2.0 > nums[j]) ++j;
res += j - (mid + 1);
}
sort(nums.begin() + left, nums.begin() + right + 1);
return res;
}
};
解题思路2:
利用其他的思路,第二层for 二分法出现超时;
class Solution {
public:
int returnInt(vector<int>& nums , int position)
{
int len = nums.size() - 1 ;
int startN = position + 1 , endN = len ;
int mid = (startN + endN) >> 1 , target = nums[position] ;
while (startN <= endN)
{
mid = (startN + endN) / 2 ;
if (nums[mid] >= target) endN -- ;
else startN ++ ;
}
if (nums[mid] < target)
mid ++ ;
nums.insert(nums.begin() + mid , target) ;
nums.erase(nums.begin() + position) ;
if (target == 0)
return mid - position - 1 ;
else if (target > 0)
{
startN = position ;
endN = mid - 1 ;
}
else
{
startN = mid + 1 ;
endN = len ;
}
if (target == INT_MAX)
target = (target >> 1) + 1 ;
else target = (target + 1) >> 1 ;
while (startN <= endN)
{
mid = (startN + endN) / 2 ;
if (nums[mid] >= target) endN -- ;
else startN ++ ;
}
if (nums[mid] < target)
mid ++ ;
if (target < 0)
return mid - position - 1 ;
else
return mid - position ;
}
int reversePairs(vector<int>& nums) {
if (nums.size() < 2)
return 0 ;
int c_i = nums.size() - 2 ;
int ret = 0 ;
while (c_i > -1)
{
ret += returnInt(nums , c_i) ;
c_i -- ;
}
return ret ;
}
};