Leetcode 315. Count of Smaller Numbers After Self
Problem:
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:
Input: [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.
Solution:
这道题我看到的第一想法是模拟一个插入排序的过程。从右往左扫描,用vec数组保存已经从小到大排序好的数组,用二分法找到下一个元素应该插入的位置,将索引号保存并插入vec数组即可,虽然看似时间复杂度为O(nlogn),其实插入操作的时间复杂度为O(n),所以其实时间复杂度为O(n2)。
1 class Solution { 2 public: 3 vector<int> countSmaller(vector<int>& nums) { 4 vector<int> result(nums.size()); 5 if(nums.size() == 0) return result; 6 vector<int> vec; 7 for(int i = nums.size()-1;i >= 0;--i){ 8 int start = 0; 9 int end = vec.size(); 10 while(start < end){ 11 int pivot = start + (end-start)/2; 12 if(nums[i] > vec[pivot]) 13 end = pivot; 14 else 15 start = pivot+1; 16 } 17 result[i] = vec.size()-start; 18 if(start == vec.size()) vec.push_back(nums[i]); 19 else vec.insert(vec.begin()+start,nums[i]); 20 } 21 return result; 22 } 23 };
现在讲讲另一种用FenwickTree树状数组的解法,我们用一个rank数组记录数组中每个元素的rank,比如[5,2,6,1]的rank数组是[3,2,4,1],然后将rank数组逆序去更新一个FenwickTree树状数组,数组初始化为[0,0,0,0,0],在这个例子中的更新过程为:
rank数组:[1,4,2,3]
逆转数组:[1,6,2,5]
1. [0,1,0,0,0] //对于第一个数1,对应rank数组中的1,其左侧的和为0,所以result[4-0-1]=0
2. [0,1,0,0,1] //对于第二个数6,对应rank数组中的4,其左侧和为1,所以result[2]=1
3. [0,1,1,0,1] //对于第三个数2,对应rank数组中的2,其左侧和为1,所以result[1]=1
4. [0,1,1,1,1] //对于第四个数5,对应rank数组中的3,其左侧和为2,所以result[1]=2
Code:
1 class FenwickTree{ 2 public: 3 FenwickTree(int N){ 4 data = vector<int>(N+1); 5 tree = vector<int>(N+1); 6 } 7 void update(int index){ 8 for(int i = index;i < tree.size();i+=lowBit(i)) 9 tree[i] += 1; 10 data[index]++; 11 } 12 int getSum(int last){ 13 int result = 0; 14 for(int i = last;i > 0;i-=lowBit(i)) 15 result += tree[i]; 16 return result; 17 } 18 private: 19 int lowBit(int x){ 20 return x&(-x); 21 } 22 vector<int> tree; 23 vector<int> data; 24 }; 25 class Solution { 26 public: 27 vector<int> countSmaller(vector<int>& nums) { 28 set<int> s(nums.begin(),nums.end()); 29 unordered_map<int,int> um; 30 int index = 0; 31 for(auto i:s){ 32 um[i] = index; 33 index++; 34 } 35 vector<int> rank; 36 for(int i = nums.size()-1;i >= 0;--i) 37 rank.push_back(um[nums[i]]+1); 38 FenwickTree tree(s.size()); 39 int m = nums.size(); 40 vector<int> result(m); 41 for(int i = 0;i != rank.size();++i){ 42 result[m-i-1] = tree.getSum(rank[i]-1); 43 tree.update(rank[i]); 44 } 45 return result; 46 } 47 };