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 the property where counts[i]
is the number of smaller elements to the right of nums[i]
.
Example:
Input: [5,2,6,1] Output:[5,2,6,1]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.
Approach #1: C++. [Fenwick Tree / Binary Indexed Tree]
class FenwickTree { public: FenwickTree(int n): sums_(n+1, 0) {} void update(int i, int delta) { while (i < sums_.size()) { sums_[i] += delta; i += lowbit(i); } } int query(int i) const { int sum = 0; while (i > 0) { sum += sums_[i]; i -= lowbit(i); } return sum; } private: static inline int lowbit(int x) { return x & (-x); } vector<int> sums_; }; class Solution { public: vector<int> countSmaller(vector<int>& nums) { set<int> sorted(nums.begin(), nums.end()); unordered_map<int, int> ranks; int rank = 0; for (const int num : sorted) ranks[num] = ++rank; vector<int> ans; FenwickTree tree(ranks.size()); for (int i = nums.size() - 1; i >= 0; --i) { ans.push_back(tree.query(ranks[nums[i]] - 1)); tree.update(ranks[nums[i]], 1); } std::reverse(ans.begin(), ans.end()); return ans; } };
Prefix sums of frequencise, convert the number to its rank as in sorted array.
For example:
Input: [5, 2, 6, 1]
sorted: [1, 2, 5, 6]
ranks: [1, 4, 2, 3]
Increase the freq[rank] by 1.
Num | Rank | Freq | Prefix sum / Query(rank - 1) |
- | - | [0, 0, 0, 0, 0] | - |
1 | 1 | [0, 1, 0, 0, 0] | 0 |
6 | 4 | [0, 1, 0, 0, 1] | 1 |
2 | 2 | [0, 1, 1, 0, 1] | 1 |
5 | 3 | [0, 1, 1, 1, 1] | 2 |
Approach #2: Java. [BST]
class Solution { class Node { Node left, right; int val, sum, dup = 1; public Node(int v, int s) { val = v; sum = s; } } public List<Integer> countSmaller(int[] nums) { Integer[] ans = new Integer[nums.length]; Node root = null; for (int i = nums.length - 1; i >= 0; i--) { root = insert(nums[i], root, ans, i, 0); } return Arrays.asList(ans); } private Node insert(int num, Node node, Integer[] ans, int i, int preSum) { if (node == null) { node = new Node(num, 0); ans[i] = preSum; } else if (node.val == num) { node.dup++; ans[i] = preSum + node.sum; } else if (node.val > num) { node.sum++; node.left = insert(num, node.left, ans, i, preSum); } else { node.right = insert(num, node.right, ans, i, preSum + node.dup + node.sum); } return node; } }
永远渴望,大智若愚(stay hungry, stay foolish)