首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >分治-归并系列一>翻转对

分治-归并系列一>翻转对

作者头像
用户11305962
发布2025-04-12 19:12:25
发布2025-04-12 19:12:25
9400
代码可运行
举报
文章被收录于专栏:学习学习
运行总次数:0
代码可运行

题目:

链接: link


这题和逆序对区别点就是,要找到前一个元素是后一个元素的2倍 先找到目标值再,继续堆排序

解析:

策略一:

代码:

代码语言:javascript
代码运行次数:0
运行
复制
class Solution {
    int[] tmp;
    public int reversePairs(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        return mergesort(nums,0,n-1);
    }
    
    private int mergesort(int[] nums, int left, int right){
        int ret = 0;
        if(left >= right) return 0;

        int mid = (right + left) / 2;
        //左右两边找翻转对
        ret += mergesort(nums,left,mid);
        ret += mergesort(nums,mid+1,right);

        //一左一右找翻转对: 降序版本
        //输入数组中的所有数字都在32位整数的表示范围内:改为:2.0*nums[cur2]
        int cur1 = left, cur2 = mid+1, i = 0;
        while(cur1 <= mid && cur2 <= right){
            if(nums[cur1] <= 2.0*nums[cur2]){
                cur2++;
            }else {
                ret += right - cur2 + 1;
                cur1++;
            }
            if(cur2 > right) break;
        }

        //排序:
        cur1 = left; cur2 = mid+1;
        while(cur1 <= mid && cur2 <= right) 
            tmp[i++] = nums[cur1] <= nums[cur2]? nums[cur2++] : nums[cur1++];

        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];
        
        //放回原数组:
        for(int j = left; j <= right; j++){
            nums[j] = tmp[j-left];
        }

        return ret;
    }
}

策略二:

代码:

代码语言:javascript
代码运行次数:0
运行
复制
class Solution {
    int[] tmp;
    public int reversePairs(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        return mergesort(nums,0,n-1);
    }

    一左一右找翻转对: 升序版本:
     private int mergesort(int[] nums, int left, int right){
        int ret = 0;
        if(left >= right) return 0;

        int mid = (right + left) / 2;
        //左右两边找翻转对
        ret += mergesort(nums,left,mid);
        ret += mergesort(nums,mid+1,right);

        //一左一右找翻转对: 升序版本
        //输入数组中的所有数字都在32位整数的表示范围内:改为:2.0*nums[cur2]
        int cur1 = left, cur2 = mid+1, i = 0;
        while(cur1 <= mid && cur2 <= right){
            if(nums[cur1] / 2.0 <= nums[cur2]){
                cur1++;
            }else {
                ret += mid - cur1 + 1;
                cur2++;
            }
            if(cur1 > mid) break;
        }

        //排序:
        cur1 = left; cur2 = mid+1;
        while(cur1 <= mid && cur2 <= right) 
            tmp[i++] = nums[cur1] <= nums[cur2]? nums[cur1++] : nums[cur2++];

        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];
        
        //放回原数组:
        for(int j = left; j <= right; j++){
            nums[j] = tmp[j-left];
        }

        return ret;
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目:
  • 解析:
    • 策略一:
  • 代码:
    • 策略二:
  • 代码:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档