我是靠谱客的博主 淡淡犀牛,这篇文章主要介绍leetcode493- 翻转对(一边归并排序,一边获取翻转对)介绍解题思路分治法的效率展示代码,现在分享给大家,希望可以做个参考。

leetcode493- 翻转对(一边归并排序,一边获取翻转对)

  • 介绍
    • 题目
  • 解题思路
    • 心路历程
  • 分治法的效率展示
  • 代码

介绍

我的LeetCode主页,一题一题解

标签:排序、树状数组、线段树、二分查找、分治法

493. 翻转对
难度 困难

493. 翻转对
https://leetcode-cn.com/problems/reverse-pairs/

题目

给定一个数组 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位整数的表示范围内。

解题思路

大佬写的题解太好了
看官方那个:这啥,让我来仔细瞅瞅
看笨猪爆破组大佬的题解:原来是这样,懂了懂了

心路历程

最开始的想法是直接双重循环,时间复杂度O(n^2),很明显慢多了
然后一看相关标签,排序、分治,好像想起了些什么(什么?树状数组和线段树?在学了在学了,别骂了)

首先从分治的角度思考,即将数组分为两个部分
令 i 在前一个数组里面,j 在后一个数组
在这种情况下,只要两个数组都是分别排序好的

借用大佬的图展示下:
image.png

那么可以直接通过双指针,分别遍历两个数组
从而获取翻转对的数量
最后再将两个合并,顺便排序
最后再返回在当前层时全部的翻转对

分治法的效率展示

都不怎么快
image.png

代码

class Solution {

    private int count;    

    public int reversePairs(int[] nums) {
        if (nums == null || nums.length < 2) {
            return 0;
        }        
        count = 0;  
        mergeSort(nums, 0, nums.length - 1);      
        return count;
    }

    //分治的方法
    private void mergeSort(int[] nums, int start, int end) {
        //出口
        if (start == end) {
            return 0;
        }
        int mid = start + (end - start) / 2;
        //二分递归
        mergeSort(nums, start, mid);
        mergeSort(nums, mid + 1, end);

        //关键的部分
        //双指针获取翻转对的数量
        int i = start;
        int j = mid + 1;
        while (i <= mid && j <= end) {
            //条件成立,当前的i一直到mid都可以与当前的j构成翻转对
            //用long是因为数据顶到了int的顶
            if ((long) nums[i] > 2 * (long) nums[j]) {
                count += mid - i + 1;
                j++;
            }
            //条件不在满足了,i++,看下一个i是否再次满足
            else {
                i++;
            }
        }

        // 获取完之后合并,新建一个数组转存
        int[] tempArr = new int[end - start + 1];
        i = start;
        j = mid + 1;
        int idx = 0;
        while (i <= mid && j <= end) {
            tempArr[idx++] = nums[i] < nums[j] ? nums[i++] : nums[j++];
        }
        while (i <= mid) {
            tempArr[idx++] = nums[i++];
        } 
        while (j <= end) {
            tempArr[idx++] = nums[j++];
        }
        for (i = 0, j = start; j <= end; i++, j++) {
            nums[j] = tempArr[i];
        }
    }
}

最后

以上就是淡淡犀牛最近收集整理的关于leetcode493- 翻转对(一边归并排序,一边获取翻转对)介绍解题思路分治法的效率展示代码的全部内容,更多相关leetcode493-内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(135)

评论列表共有 0 条评论

立即
投稿
返回
顶部