每天两道LeetCodeHard:(48)

399 阅读2分钟

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].

解释:

给一个数组,要求找到这个数组之后的所有比当前小的值

思考:

最初的想法是用单调栈来实现,实际就是查找当前的这个数字在目前排第几,然后把比他大的位置都加一,栈里面存的是下标,然后如果目前值比栈顶小,就pop,加一,然后重复,直到找到位置,这样的时间复杂度是On2的,最坏情况是一个递减序列,每次都要遍历所有。 更巧妙的做法其实是直接排序,记录原来的下标和排序之后的下标的关系,然后排序之后的下标就是比他小的数字的个数。时间是n2,插入排序 继续优化,有没有既能知道顺序,插入还是O1的办法呢,其实就是二叉搜索树了。这才是这个题真正想考察的点,实现一个二叉搜索树,每个点都从跟节点开始找,比较logn次一定能找到自己的位置,总时间就优化到nlogn了。

答案:

# 定义一个树的节点类
class TreeNode(object):
    def __init__(self, val):
        self.left = None
        self.right = None
        self.val = val  # 节点值
        self.count = 0  # 左子树节点数量

class Solution(object):
    def countSmaller(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        length = len(nums)        
        root = None
        # 结果集
        res = [0 for _ in range(length)]
        # nums 反序加入搜索树
        for i in reversed(range(length)):
            root = self.insertNode(root, nums[i], res, i)
        return res
    
    # 往二叉搜索树中插入新的节点
    def insertNode(self, root, val, res, res_index):
        if root == None:
            root = TreeNode(val)
        elif val <= root.val: # 小于当前节点值则放入左子树
            # root 的左侧节点数量值 +1
            root.count += 1
            root.left = self.insertNode(root.left, val, res, res_index)
        elif val > root.val: # 大于当前节点值则放入右子树
            # 计算题目所求的结果
            res[res_index] += root.count + 1
            root.right = self.insertNode(root.right, val, res, res_index)
            
        return root

答案补充: