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 1smaller 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 intend = 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 };
Leetcode 315. Count of Smaller Numbers After Self