LeetCode 题解(291): Reverse Pairs

该博客主要解析LeetCode第291题,介绍如何找出数组中的重要反转对。通过使用归并排序的策略,当数组分解到只剩两个元素时,判断左边元素是否大于右边元素的两倍,如果是则累加计数。接着进行归并排序,逐层比较并返回结果。博客提供了C++和Java两种语言的实现方案。
摘要由CSDN通过智能技术生成

题目:

Given an array nums, we call (i, j) an important reverse pair ifi < 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.

题解:

merge sort递归至最底层,divide至左右各一个元素时,比较左元素是否大于右元素的两倍,如是,global count 加1,然后merge sort,返回至上层,继续比较,继续merge sort,以此类推。

C++版:

class Solution {
public:
    int reversePairs(vector<int>& nums) {
        return reversePairsSub(nums, 0, nums.size() - 1);
    }
    
    int reversePairsSub(vector<int>& nums, int low, int high) {
        if (low >= high) {
            return 0;
        } 
        int mid = (low + high) / 2;
        int count = reversePairsSub(nums, low, mid) + reversePairsSub(nums, mid + 1, high);
        int local_count = 0;
        //比较左右两半元素大小
        for (int i = low, j = mid + 1; i <= mid; i++) {
            while (j <= high && nums[i] / 2.0 > nums[j]) {
                local_count++;
                j++;
            }
            count += local_count;
        }
        mergeSort(nums, low, mid, high);
        return count;
    }
    // Merge Sort
    void mergeSort(vector<int>& nums, int low, int mid, int high) {
        vector<int> temp(nums.begin() + low, nums.begin() + high + 1);
        int i = low, j = mid + 1;
        int k = low;
        while (k <= high) {
            if (i > mid || (j <= high && temp[i - low] > temp[j - low])) {
                nums[k++] = temp[j - low];
                j++;
            } else {
                nums[k++] = temp[i - low];
                i++;
            }
        }
    }
};

Java版:

public class Solution {
    public int reversePairs(int[] nums) {
        return reversePairsSub(nums, 0, nums.length - 1);
    }
    
    public int reversePairsSub(int[] nums, int low, int high) {
        if (low >= high) {
            return 0;
        }
        int mid = (low + high) / 2;
        int count = reversePairsSub(nums, low, mid) + reversePairsSub(nums, mid + 1, high);
        int local_count = 0;
        for (int i = low, j = mid + 1; i <= mid; i++) {
            while (j <= high && nums[i] / 2.0 > nums[j]) {
                local_count++;
                j++;
            }
            count += local_count;
        }
        mergeSort(nums, low, mid, high); 
        return count;
    }
    
    public void mergeSort(int[] nums, int low, int mid, int high) {
        int[] temp = new int[high - low + 1];
        for (int i = low; i <= high; i++) {
            temp[i - low] = nums[i];
        }
        int i = low, j = mid + 1, k = low;
        while (k <= high) {
            if (i > mid || (j <= high && temp[i - low] > temp[j - low])) {
                nums[k] = temp[j - low];
                k += 1;
                j += 1;
            } else {
                nums[k] = temp[i - low];
                k += 1;
                i += 1;
            }
        }
    }
}

Python版:

class Solution(object):
    def reversePairs(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        return self.reversePairsSub(nums, 0, len(nums)-1)
        
    def reversePairsSub(self, nums, low, high):
        if low >= high:
            return 0
        mid = (low + high) / 2
        count = self.reversePairsSub(nums, low, mid) + self.reversePairsSub(nums, mid+1, high)
        count_local = 0
        j = mid + 1
        for i in range(low, mid + 1):
            while j <= high and nums[i] / 2.0 > nums[j]:
                count_local += 1
                j += 1
            count += count_local
        
        nums[low:high+1] = sorted(nums[low:high+1])
        return count


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值