You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].

Example 1:

Input: nums = [5,2,6,1]
Output: [2,1,1,0]
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.

Constraints:

  • 0 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4
 
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
vector<int> res(nums.size(),0);
//从右向左,将数组有序插入tmp.利用二分查找确定当前数右边比它小的数的个数
vector<int> tmp;
for(int i=nums.size()-1;i>=0;i--){
int left = 0,right=tmp.size()-1;
//找第一个大于等于当前数的位置。插入其中
while(left <= right){
int mid = left+(right-left)/2;
if(tmp[mid] < nums[i]) left = mid+1;
else right = mid-1;
}
//最后返回的位置是left
res[i]=left;
//插入nums[i]
tmp.insert(tmp.begin()+left,nums[i]);
}
return res;
}
};

//归并:先引入逆序数;不同于逆序数对:

res[nums[i].second] += (j-mid-1);
这个里面坑比较多
class Solution {
public:
//法二:利用归并排序求逆序对数的方法
//https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/submissions/ vector<int> countSmaller(vector<int>& nums) {
int n=nums.size();
vector<int> res(n,0);
if(n==0 || n==1) return res;
vector<pair<int,int>> tmp(n,pair<int,int>{0,0});
vector<pair<int,int>> idx;
for(int i=0;i<n;i++){
idx.push_back(make_pair(nums[i],i));
}
mergesort(idx,tmp,0,n-1,res);
return res;
} //merge的过程将left到right有序重新存入nums.归并nums[left,mid],nums[mid+1,right]
void merge(vector<pair<int,int>>& nums,vector<pair<int,int>>& tmp,int left,int mid,int right,vector<int>& res) {
int i=left,j=mid+1,k=left;
for(;i<=mid&&j<=right;){
if(nums[i].first<=nums[j].first){
//不同于算整个数组逆序数
//这里的i不是之前的i。归并后数字的位置被改变了.所以利用pari记录nums[i]原始位置
//res[i] += (j-mid-1);
res[nums[i].second] += (j-mid-1);
tmp[k++] = nums[i++];
}else{
tmp[k++] = nums[j++];
}
}
//还有未归并完成的
while(i<=mid){
//先计算res
res[nums[i].second] += (j-mid-1);
tmp[k++]=nums[i++];
}
while(j<=right){
tmp[k++]=nums[j++];
}
//将tmp重新放入nums,那么nums[left,right]即有序了
for(int i=left;i<=right;i++){
nums[i] = tmp[i];
}
return;
}
//归并排序
void mergesort(vector<pair<int,int>>& nums,vector<pair<int,int>>& tmp,int left,int right,vector<int>& res) {
if(left < right){
int mid = left+(right-left)/2;
mergesort(nums,tmp,left,mid,res);
mergesort(nums,tmp,mid+1,right,res);
//合并nums[left,mid] nums[mid+1,right]
merge(nums,tmp,left,mid,right,res);
}
return;
} };

315. Count of Smaller Numbers After Self(二分或者算法导论中的归并求逆序数对)的更多相关文章

  1. [LeetCode] 315. Count of Smaller Numbers After Self (Hard)

    315. Count of Smaller Numbers After Self class Solution { public: vector<int> countSmaller(vec ...

  2. leetcode 315. Count of Smaller Numbers After Self 两种思路(欢迎探讨更优解法)

    说来惭愧,已经四个月没有切 leetcode 上的题目了. 虽然工作中很少(几乎)没有用到什么高级算法,数据结构,但是我一直坚信 "任何语言都会过时,只有数据结构和算法才能永恒". ...

  3. leetcode 315. Count of Smaller Numbers After Self 两种思路

    说来惭愧,已经四个月没有切 leetcode 上的题目了. 虽然工作中很少(几乎)没有用到什么高级算法,数据结构,但是我一直坚信 "任何语言都会过时,只有数据结构和算法才能永恒". ...

  4. 315. Count of Smaller Numbers After Self

    You are given an integer array nums and you have to return a new counts array. The counts array has ...

  5. [LeetCode] 315. Count of Smaller Numbers After Self 计算后面较小数字的个数

    You are given an integer array nums and you have to return a new counts array. The countsarray has t ...

  6. LeetCode 315. Count of Smaller Numbers After Self

    原题链接在这里:https://leetcode.com/problems/count-of-smaller-numbers-after-self/ 题目: You are given an inte ...

  7. 315.Count of Smaller Numbers After Self My Submissions Question

    You are given an integer array nums and you have to return a new counts array. Thecounts array has t ...

  8. 315. Count of Smaller Numbers After Self(Fenwick Tree)

    You are given an integer array nums and you have to return a new counts array. The counts array has ...

  9. 第十四周 Leetcode 315. Count of Smaller Numbers After Self(HARD) 主席树

    Leetcode315 题意很简单,给定一个序列,求每一个数的右边有多少小于它的数. O(n^2)的算法是显而易见的. 用普通的线段树可以优化到O(nlogn) 我们可以直接套用主席树的模板. 主席树 ...

随机推荐

  1. Rust之路(4)——所有权

    [未经书面同意,严禁转载] -- 2020-10-14 -- 所有权是Rust的重中之重(这口气咋像高中数学老师 WTF......). 所有权是指的对内存实际存储的数据的访问权(包括读取和修改),在 ...

  2. MeteoInfoLab脚本示例:TOMS HDF数据

    TOMS (Total Ozone Mapping Spectrometer)数据是全球臭氧观测.脚本程序: #Add data file folder = 'D:/Temp/hdf/' fns = ...

  3. 新手学习C语言/C++编程你所必须要了解的知识!从计算机原理开始!

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  4. Ubuntu18.04中安装virtualenv和virtualenvwrapper

    1.安装virtualenv和virtualenvwrapper pip3 install virtualenv pip3 install virtualenvwrapper 2.创建目录用来存放虚拟 ...

  5. MySQL5.6的二进制安装

    5.6 5.7 用的最多 差别不大. 首先从网上下在二进制文件 先去官网找到自己想要的版本 https://dev.mysql.com/downloads/mysql/ https://dev.mys ...

  6. mysql You can't specify target table 'sys_right_menu' for update in FROM clause (不能从Objor子句中指定目标表“SysRyType菜单)

    错误语句: DELETE from sys_right_menu where right_id  in (SELECT m.right_id from sys_right_menu  mLEFT JO ...

  7. 获取和设置pdf目录

    目录 前言 工具 获取pdf目录 获取toc格式目录 获取json格式目录 设置pdf目录 结语 前言 获取pdf目录:主要场景是为了拿到目录信息做编辑,从pdf软件里面一个个复制那肯定费时费力. 设 ...

  8. Redis---08Redis集群(一)

    一.什么是Redis集群 Redis 集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N. Redis 集群通过分区(parti ...

  9. 使用udev高效、动态的管理Linux设备文件

    导读: 在Linux环境中,所有的设备都以文件的形式存在,在早期的Linux版本中,/dev目录包含了了所有可能出现的设备文件,很难想象Linux用户如何从大量的设备文件中找到想要的设备文件.举个例子 ...

  10. Spark性能调优的方法

    原则一:避免创建重复的RDD 通常来说,我们在开发一个Spark作业时,首先是基于某个数据源(比如Hive表或HDFS文件)创建一个初始的RDD:接着对这个RDD执行某个算子操作,然后得到下一个RDD ...