493. 翻转对
个人思路
思路
与逆序对的分之思想类似,都是使用归并排序
一开始的思路是完全照搬逆序对的思路,在比较两个元素大小时判断是否存在二倍的关系。
不能按照逆序对求解的原因:
两元素比较大小的过程中,i,j指针不断后移,会出现还没有找到合适的i时,j已经后移并跳过了满足条件的j。正是由于指针后移会影响到指针的求解,因此要把问题求解过程在比较大小之前完成
个人思路代码
错误代码
void merge(vector<int>& nums, int L1, int R1, int L2, int R2){
int i = L1, j = L2;
int temp[maxn], index = 0;
while(i <= R1 && j <= R2){
if(nums[i] <= nums[j]){
temp[index++] = nums[i++];
}
else{
//!!!!!!!!!!
if(nums[i] > 2 * nums[j]){//判断重要翻转对
printf("%d %d\n", i, j);
printf("%d %d\n", nums[i], nums[j]);
ans += R1 - i + 1;
}
//!!!!!!!
temp[index++] = nums[j++];
}
}
while(i <= R1){
temp[index++] = nums[i++];
}
while(j <= R2){
temp[index++] = nums[j++];
}
for(int i = 0; i < index; ++i){
nums[L1 + i] = temp[i];
}
}
正确代码(归并排序)
class Solution {
public:
int maxn = 50005;
int ans = 0;
void merge(vector<int>& nums, int L1, int R1, int L2, int R2){
int i = L1, j = L2;
while(i <= R1 && j <= R2)
{
if((long)nums[i] > 2*long(nums[j]))
{
ans += R1 - i + 1;
j++;
}
else
i++;
}//先处理问题
i = L1, j = L2;//重新初始化i,j
int temp[maxn], index = 0;
while(i <= R1 && j <= R2){
if(nums[i] <= nums[j]){
temp[index++] = nums[i++];
}
else{
temp[index++] = nums[j++];
}
}
while(i <= R1){
temp[index++] = nums[i++];
}
while(j <= R2){
temp[index++] = nums[j++];
}
for(int i = 0; i < index; ++i){
nums[L1 + i] = temp[i];
}
}
void mergeSort(vector<int>& nums, int left, int right){
if(left < right){
int mid = (left + right) / 2;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
merge(nums, left, mid, mid + 1, right);
}
}
int reversePairs(vector<int>& nums) {
int n = nums.size() - 1;
mergeSort(nums, 0, n);
return ans;
}
};