Count of Smaller Numbers After Self -- LeetCode

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:

Given nums = [5, 2, 6, 1]

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.

Return the array [2, 1, 1, 0].

思路:O(nlogn)复杂度算法。

将数组排序然后构建二叉搜索树。一开始二叉搜索树上的节点都标记为未处理过。然后我们从所给的nums数组的最后一个数倒着向前遍历,依次将每一个数在二叉搜索树中对应的节点标记为处理过,然后返回二叉搜索树中已经被标记为处理过,且小于该值的个数。

具体实现中,我们在每一个节点中设置一个count变量,计数以该节点为根节点的子树中已经被标记为处理过的节点个数,初始为0。之后算法运行过程中不断更新该值并通过该值更快地求解。本质上来说这是一个线段树的应用。

当我们要求二叉搜索树中有多少被处理过的节点值小于所给的值时,有三种情况:

  • 所给的值是当前子树的根节点。则小于它的数只可能在左子树中,因此返回根节点左孩子的count值。
  • 所给的值在当前子树的左子树中。则小于它的数只可能在左子树中,因此递归求解,返回左子树中被处理过且小于所给值的节点个数。
  • 所给的值在当前子树的右子树中。则小于它的数可能在左子树中或者是该根节点,或者在右子树中。因此递归求解,返回左子树和根节点中被处理过且小于所给值的节点个数加上右子树中被处理过且小于所给值的节点个数。

二叉搜索树的构建O(n),二叉搜索树的单次查找更新操作O(logn)。 总复杂度为O(n) + O(nlogn) = O(nlogn)

 1 class treeNode {
 2 public:
 3     int val, count;
 4     treeNode *left, *right;
 5     treeNode(int v) : val(v), count(0), left(NULL), right(NULL) {}
 6 };
 7 class Solution {
 8 public:
 9     //convert a sortedArray to a binary search tree and return a pointer to its root node
10     treeNode* buildTree(vector<int>& sortedArray, int left, int right) {
11         if (right < left) return NULL;
12         int mid = left + (right - left) / 2;
13         treeNode* cur = new treeNode(sortedArray[mid]);
14         cur->left = buildTree(sortedArray, left, mid - 1);
15         cur->right = buildTree(sortedArray, mid + 1, right);
16         return cur;
17     }
18     //count numbers in this binary search tree that were processed and are less than the target 
19     int update(treeNode* node, int target) {
20         if (node == NULL) return -1;
21         if (node->val == target) {
22             node->count++;
23             return node->left ? node->left->count : 0;
24         }
25         else if (node->val < target) {
26             int lessCount = node->count - node->right->count;
27             int rightCount = update(node->right, target);
28             node->count++;
29             return lessCount + rightCount;
30         }
31         else {
32             int leftCount = update(node->left, target);
33             node->count++;
34             return leftCount;
35         }
36     }
37     vector<int> countSmaller(vector<int>& nums) {
38         vector<int> sortedArray = nums;
39         sort(sortedArray.begin(), sortedArray.end(), less<int>());
40         treeNode* node = buildTree(sortedArray, 0, sortedArray.size() - 1);
41         vector<int> res(nums.size());
42         for (int i = nums.size() - 1; i >= 0; i--)
43             res[i] = update(node, nums[i]);
44         return res;
45     }
46 };
原文地址:https://www.cnblogs.com/fenshen371/p/5778573.html