给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i]
的值是 nums[i]
右侧小于 nums[i]
的元素的数量。
示例:
输入: [5,2,6,1] 输出:[2,1,1,0] 解释:
5 的右侧有 2 个更小的元素 (2 和 1). 2 的右侧仅有 1 个更小的元素 (1). 6 的右侧有 1 个更小的元素 (1). 1 的右侧有 0 个更小的元素.
暴力法,从左往右循环+内部循环:O(n^2)复杂度。正确解法:二分搜索树BST算法。
我们考虑能否在二分搜索树时每插入一个元素,就输出一个结果?比如题目中的例子:插入5,输出2;插入2,输出2...但是发现最开始的空树,我们插入5如何输出2?因为后面的元素还没有输入进来,没法确定这个2。自然想到将原数组取反:【1,6,2,5】,这时插入1,输出0;插入6输出1...(每插入一个数,就返回当前比该结点小的节点数目。)插入2,由于前面只有1比他小,输出1;最后插入5,前面有1和2比他小,输出2!
那如何利用BST呢?因为我们的解题思想是每插入一个数,就返回当前比该结点小的节点数目。而BST每个节点的左子树的结点数可不是当前比该节点小的节点数目吗?有了这一观察,就可以写一个BST了。
1 class Node():
2 def __init__(self, val):
3 self.val = val
4 self.count = 1 # 所有val值一样的结点数目
5 self.leftsize = 0 # 左子树节点数目
6 self.left=None
7 self.right = None
8
9
10 class BST():
11 def __init__(self):
12 self.root = None # 初始化为一个空树
13 def insert(self, root, val): # insert函数的含义:对根为root的结点插入结点val时返回的小于该节点的数目
14 if not root:
15 self.root = Node(val)
16 return 0
17
18 if root.val==val: # 如果当前要插入的结点值就等于根节点的值,那count数加1
19 root.count+=1
20 return root.leftsize # 返回的小于该节点的数目只能是其左子树的节点数了
21
22 if val<root.val:
23 root.leftsize+=1 # 子树结点数+1(重要)
24 if not root.left: # 左子树空,则加入该节点,返回0!因为当前没有比他小的节点
25 root.left = Node(val)
26 return 0
27 return self.insert(root.left, val) # 左子树非空,则递归在左孩子为根的子树插入该节点
28
29 if val>root.val:
30 if not root.right: # 右子树为空,则先插入该节点,返回的应该是根节点的重复元素数目+左子树的结点数
31 root.right = Node(val)
32 return root.count+root.leftsize
33 return root.count+root.leftsize+self.insert(root.right, val) # 右子树非空,同上递归就好
34
35
36 class Solution:
37 def countSmaller(self, nums):
38 nums = nums[::-1] # 先逆个序
39 bst = BST()
40 res = []
41 for i in nums:
42 res.append(bst.insert(bst.root,i)) # 依次插入结点
43 return res[::-1]
总结:关于树的代码大多可用递归,值得注意的是:
**315. Count of Smaller Numbers After Self
原文:https://www.cnblogs.com/king-lps/p/10789100.html