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 counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].

Example:

1
2
3
4
5
6
7
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.

这道题第一反应肯定是暴力求解,时间复杂度为O(n^2)。确实应该也能过。
思考优化的算法,首先确定,这个题肯定与排序有关。实现加速的排序,可以选择插入二分法,也就是二叉搜索树。
不同的是我们需要在每一个节点定义该节点左子树上的所有节点的个数,这样才能实现不需要遍历子树就能确定有多少个小于该节点的数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Solution {
public:

struct TreeNode{
int val;
int count;
TreeNode* left;
TreeNode* right;

TreeNode(int x): val(x), count(0), left(NULL), right(NULL) {}
};

vector<int> countSmaller(vector<int>& nums) {

int n = nums.size();
if(n == 0) return vector<int>{};
vector<int> ans(n, 0);

TreeNode* root = new TreeNode(nums[n-1]);

for(int i = n-2; i>=0; i--){
TreeNode* tmp = new TreeNode(nums[i]);
TreeNode* curr = root;
int nodes = 0;
while(true){ //将tmp添加进BST

if(tmp->val > curr->val){ //在当前节点右子树中
nodes += curr->count+1;
if(!curr->right){ //找到空位
curr->right = tmp;
break;
} else{
curr = curr->right; //在右子树中继续寻找
}
} else{ //在左子树中
curr->count += 1; //那么当前节点要的个数要加1
if(!curr->left){ //找到空位
curr->left = tmp;
break;
} else{
curr = curr->left;
}
}
}
ans[i] = nodes;

}
return ans;
}
};