首页 > 学院 > 开发设计 > 正文

Reverse Pairs (第二周:分治法)

2019-11-06 07:41:00
字体:
来源:转载
供稿:网友

Reverse Pairs (第二周:分治法)

问题描述

Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j]. You need to return the number of important reverse pairs in the given array.

Example:

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

Output: 2

Example:

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

Output: 3

算法思路

主要是使用了分治的思想: 1. 其实就是传统的逆序数问题,基于归并排序算法来做即可,只不过稍微复杂了点,该题还要使用到二分查找。 2. 对于一个序列a,其长度为n,我们将其分为左右两部分,分别是序列b与序列c。a的逆序数又3分别组成:b的逆序数数目+c的逆序数数目+b中的数大于c中的数的2倍的数对。 3. 前两个结果我们可以根据分治得到,关键在于第三个。我每次得到b与c序列后,对其进行归并排序,对于第二个序列,即序列c中的每一个元素cj,在归并的时候,在b中查找到最小的大于cj的元素bi的位置pos,既然在b中,大于2倍cj的数有n2−pos个。 4. 至于如何查到pos,如果用线性搜索,则会超时,我们使用了二分查找。与传统二分搜索不同的是,我们不是要找目标值的位置,当查找值等于目标值的时候,下界要加一。 5. 要注意的是,样例使用的数字比较大,在进行数字判断的时候,要把数字从int类型转成double类型或者long类型。

算法代码

class Solution {public: int reversePairs(vector<int>& nums) { int n = nums.size(); if(n <= 1) return 0; int cnt = 0; vector<int> b(nums.begin(), nums.begin() + n / 2); vector<int> c(nums.begin() + n / 2, nums.end()); cnt += reversePairs(b); cnt += reversePairs(c); int ai = 0, bi = 0, ci = 0; while(ai < n){ if(bi < b.size() && (ci == c.size() || b[bi] <= c[ci])) nums[ai++] = b[bi++]; else{ long tmp2 = (long)c[ci]*2; int low = 0,high = b.size() - 1,pos = bi; while(low <= high){ pos = (low + high)/2; if((long)b[pos] == tmp2) low++; else if((long)b[pos] > tmp2) high = pos - 1; else low = pos + 1; } if(low < b.size() && low >= 0 && (long)b[low] > tmp2){ cnt += n/2 - low; } nums[ai++] = c[ci++]; } } return cnt; }};
上一篇:Spark2.1.0官方文档

下一篇:146. LRU Cache

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表