题目描述
给定一个数组 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位整数的表示范围内。
算法1
归并排序解决逆序对的模板问题
只不过判断从判断大小该为判断 n[i]>2*n[j]
C++ 代码
class Solution {
public:
int tmp[50010];
int ans =0;
void merge_sort(vector<int>& q, int l, int r)
{
if (l >= r) return;
int mid =( l + r) >> 1;
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
int i=l; int j =mid+1;
while(i<=mid && j<=r){
if((long long)q[i] > (long long )2*q[j]){
ans += mid-i+1;
j++;
}else{
i++;
}
}
int k = 0;
i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
int reversePairs(vector<int>& nums) {
merge_sort(nums, 0, nums.size()-1);
return ans;
}
};
同样的题目 还有
Leetcode 面试题51. 数组中的逆序对
地址 https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。
输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
使用归并排序计算逆序对的裸题
代码
class Solution {
public:
int tmp[50010];
int ans =0;
void merge_sort(vector<int>& q, int l, int r)
{
if (l >= r) return;
int mid =( l + r) >> 1;
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
int i=l; int j =mid+1;
while(i<=mid && j<=r){
if(q[i] > q[j]){
ans += mid-i+1;
j++;
}else{
i++;
}
}
int k = 0;
i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
int reversePairs(vector<int>& nums) {
merge_sort(nums, 0, nums.size()-1);
return ans;
}
};
为啥第一种解法要分开写啊,不能像y总写求逆序对的一样,归并与统计ans写一起吗。。纠结一上午啦hh
遇到题目的时候可以参考Y总的模板。可以看做是多种方式多个思路吧
我后来发现了,应该是不能同时做,同时做的化当第一个数组的某元素不大于第二个数组的某元素的两倍但是大于了一倍是右移动,但是这样第一个数组的后一个元素可能大于它,因此大于2倍与大于不同合在一起。。感谢大佬回复0.0
共同学习进步, 我也没回答啥.hh