zoukankan      html  css  js  c++  java
  • 493. Reverse Pairs

    问题:

    给定一个数组nums,若 i < j, nums[i] > 2*nums[j],则称这一对 i,j为important reverse pair

    求给定数组中,有多少组important reverse pair。

    Example1:
    Input: [1,3,2,3,1]
    Output: 2
    
    Example2:
    Input: [2,4,3,5,1]
    Output: 3
    
    Note:
    The length of the given array will not exceed 50,000.
    All the numbers in the input array are in the range of 32-bit integer.
    

      

    解法:

    解法一:FenwickTree

    方针:遍历数组,对每一个新遍历到的数nums[j],看已经遍历过的数里面,是否存在满足要求的nums[i](nums[i] > 2*nums[j])

    我们使用FenwickTree来记录到目前为止,满足要求的nums[i]总共有多少个。

    每遍历一个数,update到FenwickTree中。

    presum来得到满足要求的nums[i]的个数。

    这里,我们需要使用辅助数组,sortnums来存放经过排序后的nums

    使用FenwickTree来对应sortnums的计数。(相同index下)

    具体做法:

    每遍历一个nums[j]

    在sortnums中找到<=2*nums[j]的index

    那么在FenwickTree中,到目前为止所有个数 0~index的个数 = >2*nums[j]的个数

    在sortnums中找到nums[j]的index

    更新到FenwickTree.update(index,1)

    ⚠️ 注意:这里对于重复相同的元素,index可能会重复,但是没关系,我们要求的是计数个数,(不需要index一一对应)直接使用update方法更新增加delta=1即可。

    代码参考:

     1 class FenwickTree {
     2 public:
     3     FenwickTree(int n):preSum(n+1, 0){}
     4     void update(int i, int delta){
     5         while(i<preSum.size()){
     6             preSum[i]+=delta;
     7             i+=lowbit(i);
     8         }
     9     }
    10     int getPreSum(int i){
    11         int sum=0;
    12         while(i>0){
    13             sum+=preSum[i];
    14             i-=lowbit(i);
    15         }
    16         return sum;
    17     }
    18 private:
    19     vector<int> preSum;
    20     int lowbit(int x){
    21         return x&(-x);
    22     }
    23 };
    24 
    25 class Solution {
    26 public:
    27     int reversePairs(vector<int>& nums) {
    28         FenwickTree tree(nums.size());
    29         vector<int> sortnums(nums);
    30         sort(sortnums.begin(), sortnums.end());
    31         int res=0;
    32         for(int i=0; i<nums.size(); i++){
    33             //对每一个j,前面遍历过的每个i,是否有满足条件nums[i] > 2*nums[j]的
    34             //找大于2*nums[j]的位置
    35             //sort从小到大,先找<=2*nums[j]的位置
    36             int dislower=distance(sortnums.begin(), upper_bound(sortnums.begin(),sortnums.end(),(long long)2*nums[i]));
    37             res+=(tree.getPreSum(nums.size())-tree.getPreSum(dislower));
    38             //将遍历过的元素更新到tree
    39             int pos_sorted_i=distance(sortnums.begin(), lower_bound(sortnums.begin(),sortnums.end(),nums[i]))+1;
    40             tree.update(pos_sorted_i, 1);
    41         }
    42         return res;
    43     }
    44 };

    解法二:

    归并排序 merge Sort

    在归并排序的合并两个有序数列过程中,追加一个判断,

    • if 左边的数>=2倍的右边的数:res+=左边剩下的数。
    • 左边下一个数

    代码参考:

     1 class Solution {
     2 public:
     3     int reversePairs(vector<int>& nums) {
     4         int res=0;
     5         if(nums.size()==0) return 0;
     6         res = mergeSort(nums, 0, nums.size()-1);
     7         return res;
     8     }
     9     int mergeSort(vector<int>& nums, int start, int end) {
    10         int res=0;
    11         if (start==end) {
    12             return 0;
    13         }
    14         int mid = start + (end - start) / 2;
    15         res+=mergeSort(nums, start, mid);
    16         res+=mergeSort(nums, mid+1, end);
    17         res+=merge(nums, start, mid, end);
    18         return res;
    19     }
    20     int merge(vector<int>& nums, int start, int mid, int end) {
    21         int p = start, q = mid+1;
    22         int res=0;
    23         while(p<=mid && q<=end) {
    24             if(nums[p] > (long long)2*nums[q]){
    25                 res+=(mid-p+1);
    26                 q++;
    27             }else{
    28                 p++;
    29             }
    30         }
    31         
    32         vector<int> a(end-start+1, 0);
    33         p = start, q = mid+1;
    34         int ai=0;
    35         while(p<=mid && q<=end) {
    36             if(nums[p] < nums[q]){
    37                 a[ai]=nums[p];
    38                 p++,ai++;
    39             }else{
    40                 a[ai]=nums[q];
    41                 q++,ai++;                
    42             }
    43         }
    44         while(p<=mid){
    45             a[ai++]=nums[p++];
    46         }
    47         while(q<=end){
    48             a[ai++]=nums[q++];
    49         }
    50         copy(a.begin(), a.end(), nums.begin()+start);
    51         return res;
    52     }
    53 };
  • 相关阅读:
    【WPF/WAF】使用System.Windows.Interactivity交互事件
    【Linux/CentOS】Boolean ftp_home_dir is not defined
    【笔记】使用Token做验证
    【笔记】什么是跨域请求/访问?
    MongoDB优化与一些需要注意的细节
    MongoDB中聚合工具Aggregate等的介绍与使用
    MongoDB中MapReduce介绍与使用
    Centos下MongoDB的安装与配置
    PHP使用header方式实现文件下载
    关于redis中SDS简单动态字符串
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/13419857.html
Copyright © 2011-2022 走看看