**315. Count of Smaller Numbers After Self

1. 原始题目

计算右侧小于当前元素的个数

给定一个整数数组 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 个更小的元素.

2. 思路

暴力法,从左往右循环+内部循环: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了。

3. 实现

 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]

总结:关于树的代码大多可用递归,值得注意的是:

  • 弄清楚递归函数的输入与输出
  • 终止条件和当前情况的考虑

猜你喜欢

转载自www.cnblogs.com/king-lps/p/10789100.html