LeetCode每日一题(493. Reverse Pairs)

Given an integer array nums, return the number of reverse pairs in the array.

A reverse pair is a pair (i, j) where:

0 <= i < j < nums.length and
nums[i] > 2 * nums[j].

Example 1:

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

Explanation: The reverse pairs are:
(1, 4) --> nums[1] = 3, nums[4] = 1, 3 > 2 _ 1
(3, 4) --> nums[3] = 3, nums[4] = 1, 3 > 2 _ 1

Example 2:

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

Explanation: The reverse pairs are:
(1, 4) --> nums[1] = 4, nums[4] = 1, 4 > 2 _ 1
(2, 4) --> nums[2] = 3, nums[4] = 1, 3 > 2 _ 1
(3, 4) --> nums[3] = 5, nums[4] = 1, 5 > 2 * 1

Constraints:

  • 1 <= nums.length <= 5 * 104
  • -231 <= nums[i] <= 231 - 1

个人认为目前看到过的最好的解析, 原文在这里, 基本把这种可以递归拆分成 subproblems 来解决的问题都说透了。 强烈建议看一看

假设 f(i, j)为 nums[i…=j]的 reverse paris 的数量。g(i, m, j)是 nums[i…=m]相对于 nums[m+1…=j]所存在的 reverse pairs 的数量。由此我们可以得出:

f(i, j) = f(i, m) + f(m+1, j) + g(i, m, j)

这里面重点是 g(i, m, j), 因为在 nums[m+1…=j]中的数字一定是在 nums[i…=m]之后的, 所以我们只需要遍历 nums[i…=m], 然后在 nums[m+1…=j]中找到小于它的二分之一的数字即可。因为这里面不存在顺序问题, 所以两个数组都可以按数字值来进行排序, 然后用 merge-sort 的方式来统计 reverse pair 的数量。

最后说一点, 我觉得理解这套解题思路没什么难度, 难的是,我怎么能第一时间认识到这题可以用这个思路来解



impl Solution {
    fn dp(nums: &Vec<i32>) -> i32 {
        match nums.len() {
            1 => return 0,
            2 => {
                if nums[0] as i64 > nums[1] as i64 * 2 {
                    return 1;
                } else {
                    return 0;
                }
            }
            _ => {
                let mut left = nums[..nums.len() / 2].to_vec();
                let mut right = nums[nums.len() / 2..].to_vec();
                let left_count = Solution::dp(&left);
                let right_count = Solution::dp(&right);
                left.sort();
                right.sort();
                let mut li = 0;
                let mut ri = 0;
                let mut count = 0;
                while li < left.len() {
                    while ri < right.len() {
                        if left[li] as i64 <= right[ri] as i64 * 2 {
                            break;
                        }
                        ri += 1;
                    }
                    count += ri as i32;
                    li += 1;
                }
                return left_count + right_count + count;
            }
        }
    }
    pub fn reverse_pairs(nums: Vec<i32>) -> i32 {
        Solution::dp(&nums)
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值