前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >leetcode493. Reverse Pairs

leetcode493. Reverse Pairs

作者头像
眯眯眼的猫头鹰
发布2019-10-29 17:39:17
4200
发布2019-10-29 17:39:17
举报
文章被收录于专栏:眯眯眼猫头鹰的小树杈

题目要求

Given an array nums , we call(i, j)an important reverse pair if i < j andnums[i] > 2*nums[j].

You need to return the number of important reverse pairs in the given array.

Example1:

Input: [1,3,2,3,1] Output: 2

Example2:

Input: [2,4,3,5,1] Output: 3

Note:

  1. The length of the given array will not exceed 50,000.
  2. All the numbers in the input array are in the range of 32-bit integer.

思路和代码

这题可以结合归并排序的思路,将问题拆分为两个子问题,在分别计算出两个子数组含有的重要反序组之后,再对跨两个子数组的重要反序组进行排序。假设两个子数组此时均为有序,则只需要用二分法的思路,找到满足条件的最远下标即可。代码如下:

代码语言:javascript
复制
    public int reversePairs(int[] nums) {
        if (nums == null) {
            return 0;
        }
        long[] numsInLong = Arrays.stream(nums).asLongStream().toArray();
        return reversePairs(numsInLong, 0, nums.length-1);
    }

    public int reversePairs(long[] nums, int left, int right) {
        if (left >= right) {
            return 0;
        }
        int mid = (left + right) / 2;
        int leftReversePairs = reversePairs(nums, left, mid);
        int rightReversePairs = reversePairs(nums, mid+1, right);
        int count = 0;
        int cur = mid;
        while(cur >= left) {
            int index =  findRightMostIndex(nums, nums[cur], mid+1, right);
            int tmpCount = index - mid - 1;
            if (tmpCount == 0) {
                break;
            }
            count += tmpCount;
            cur--;
        }

        mergeSort(nums, left, right);
        return count + leftReversePairs + rightReversePairs;
    }

    public void mergeSort(long[] nums, int left, int right) {
        long[] copy = Arrays.copyOfRange(nums, left, right+1);
        int mid = (left + right) / 2 - left;
        int leftIndex = 0;
        int rightIndex = mid + 1;
        int index = left;
        while (index <= right) {
            if (rightIndex > right - left) {
                nums[index++] = copy[leftIndex++];
            } else if (leftIndex > mid) {
                nums[index++] = copy[rightIndex++];
            } else if (copy[leftIndex] <= copy[rightIndex]) {
                nums[index++] = copy[leftIndex++];
            } else {
                nums[index++] = copy[rightIndex++];
            }
        }
    }
    public int findRightMostIndex(long[] nums, long num, int left, int right) {
        while (left <= right) {
            int mid = (left + right) / 2;
            if (num > nums[mid] * 2) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }

这里的一个优化点在于只复制一次完整的数组,减少不断初始化子数组备份的过程。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目要求
  • 思路和代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档