每日OJ题_分治归并④_力扣493. 翻转对

目录

力扣493. 翻转对

解析代码


力扣493. 翻转对

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

注意:

  1. 给定数组的长度不会超过50000
  2. 输入数组中的所有数字都在32位整数的表示范围内。
class Solution {
public:
    int reversePairs(vector<int>& nums) {

    }
};

解析代码

        大思路与求逆序对的思路一样,就是利用归并排序的思想,将求整个数组的翻转对的数量,转换成三部分:

  • 左半区间翻转对的数量。
  • 右半区间翻转对的数量。
  • 一左一右选择时翻转对的数量。

        重点就是在合并区间过程中,如何计算出翻转对的数量。 与上个问题不同的是,上一道题我们可以一边合并一遍计算,但是这道题要求的是左边元素大于右边元素的两倍,如果我们直接合并的话,是无法快速计算出翻转对的数量的。

        例如 left = [4, 5, 6] right = [3, 4, 5] 时,如果是归并排序的话,需要计算 left 数组中有多少个 能与 3 组成翻转对。但是我们要遍历到最后一个元素 6 才能确定,时间复杂度较高。 因此需要在归并排序之前完成翻转对的统计。因为左右区间是有序的,所以使用双指针统计。

这里用升序(也可以用降序):

class Solution {
    vector<int> tmp;
public:
    int reversePairs(vector<int>& nums) {
        tmp.resize(nums.size());
        return mergeSortCnt(nums, 0, nums.size() - 1);
    }

    int mergeSortCnt(vector<int>& nums, int left, int right)
    {
        if(left >= right)
            return 0;
        int ret = 0, mid = (left + right) >> 1;
        // 先计算左右两侧翻转对数量
        ret += mergeSortCnt(nums, left, mid);
        ret += mergeSortCnt(nums, mid + 1, right);

        // 计算翻转对数量
        int cur1 = left, cur2 = mid + 1, i = left;
        while(cur2 <= right) // 升序的情况
        {
            while(cur1 <= mid && nums[cur2] >= nums[cur1] / 2.0)
            {
                cur1++;
            }
            if(cur1 > mid)
                break;
            ret += mid - cur1 + 1;
            cur2++;
        }

        // 合并两个有序数组
        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];
        
        return ret;
    }
};

http://www.niftyadmin.cn/n/5401941.html

相关文章

Docker 使用原理流程

# docker 是如何来的&#xff1f; a. linux 内核本身支持容器技术&#xff0c;LXC (市面上有很多基于 LXC 开发的容器管理软件&#xff0c;如创建容器&#xff0c;查看容器&#xff0c;管理容器&#xff0c; docker 作为管理容器的一款代表工具软件) b. 容器的作用&#xff0c;…

K8s Pod 进阶

目录 资源限制 Pod 和容器的资源请求和限制 CPU 资源单位 内存资源单位 示例1 示例2 重启策略&#xff08;restartPolicy&#xff09; 示例 健康检查 探针的三种规则 Probe支持三种检查方法 示例1&#xff1a;exec方式 示例2&#xff1a;httpGet方式 示例3&…

【Django】执行查询—跨关系查询中的跨多值关联问题

跨多值查询 跨越 ManyToManyField 或反查 ForeignKey &#xff08;例如从 Blog 到 Entry &#xff09;时&#xff0c;对多个属性进行过滤会产生这样的问题&#xff1a;是否要求每个属性都在同一个相关对象中重合。 filter() 先看filter()&#xff0c;通过一个例子看&#xf…

C语言--修饰符(auto、extern、static)与变量(局部变量+全局变量)和函数的关系

其中extern功能和用法上&#xff0c;比较特殊。先了解extern修饰全局变量&#xff0c;我总结为以下几点 为了方便描述&#xff0c;我创建了一个工程&#xff0c;工程包含了两个源文件&#xff0c;main.c和database.c **1&#xff09;&#xff1a;database.c中使用extern时用来…

文本多分类

还在用BERT做文本分类&#xff1f;分享一套基于预训练模型ERNIR3.0的文本多分类全流程实例【文本分类】_ernir 文本分类-CSDN博客 /usr/bin/python3 -m pip install --upgrade pip python3-c"import platform;print(platform.architecture()[0]);print(platform.machine…

解决Unable to load class ‘org.gradle.api.attributes.VerificationType‘

在使用AdnroidStudio开发过程中难免会遇到Unable to load class org.gradle.api.attributes.VerificationType报错&#xff0c;可以尝试清理缓存重启解决 打开 File-》Invalidate Caches... 重启AndroidStudio后&#xff0c;重新加载即可&#xff0c;但也不是百分百解决。

【已连接kafka成功】Kafka生产者初始化

Properties producerProps new Properties();producerProps.put("bootstrap.servers", "你的集群地址");producerProps.put("sasl.jaas.config", "org.apache.kafka.common.security.scram.ScramLoginModule required username\"用户…

python给企微发消息

方法一&#xff1a;webhook方式。使用群机器人给企微群发消息 import requestsdef qwxsendmessage(msg):urlhttps://qyapi.weixin.qq.com/cgi-bin/webhook/send?key6c598840-804a-4eb5-a999-a023313 #url换成自己群机器人的webhookurldata{msgtype:text,text:{content:msg}}…