Skip to content

230729 Median of BST

【题意】: 搜索二叉树的中位数

【Excepted】:

  • Time Complexity: O(N).
  • Auxiliary Space: O(Height of the Tree).

非递归中序遍历问题:

  • 中序遍历时,始终只有一个 p,这个 p 最开始是 "头"(左子树的头),然后会是 "左"。当 "左" 弹出时,它又是 "头"(右子树的头),然后又是 "左"。

morris 遍历:

  • 每到达一个非叶子节点时,都让其左子树的最右叶子节点连接到自己,确保了能够二次回到自己。
  • 这样一来,当左子树为空时,一定能确保右子树是向上指的,从而回到“头”

morris 中序遍历:

  • 叶子节点有两个: 左叶子和右叶子,因为我们是往左走的,所以能保证先到达左叶子
  • 叶子节点只会到达一次,但非叶子会到达两次,第一次到达非叶子节点时,此时还没有到达左叶子,所以不能打印
  • 当第二次到达非叶子节点时,能保证左叶子已经处理了,并且右叶子还没处理,所以可以打印。

Python3

【我的 - morrisIn】:

py
def findMedian(root):
    if root is None:
        return

    inorder = []

    cur = root
    while cur is not None:

        if cur.left is not None:
            most_right = cur.left
            while most_right.right is not None and most_right.right is not cur:
                most_right = most_right.right
            if most_right.right is None: # First come
                most_right.right = cur
                cur = cur.left
                continue
            # second come
            most_right.right = None
        # 最开始,肯定是 左节点为空才到达这里的,此时的节点是叶子节点
        # 之后,当第二次遍历时,也会走着一条路,此时的节点是“头节点”
        inorder.append(cur.data)
        # 当左空的时候,右节点一定非空,因为 most_right.right = cur 保证了此时右节点是向上指的
        cur = cur.right


    le = len(inorder)
    if le % 2 == 0:
        m = (inorder[le//2-1] + inorder[le//2])
        return m // 2 if m % 2 == 0 else m / 2

    return inorder[le//2]

【我的 - 非递归中序遍历】:

py
def findMedian(root):
    inorder = []

    stack = []
    p = root
    while len(stack) != 0 or p is not None:
        if p is not None:
            stack.append(p)
            p = p.left
        else:
            p = stack.pop()
            inorder.append(p.data)
            p = p.right

    le = len(inorder)
    if le % 2 == 0:
        m = (inorder[le//2-1] + inorder[le//2])
        return m // 2 if m % 2 == 0 else m / 2

    return inorder[le//2]

【我的 - 递归中序遍历】:

py
def recursion(root, arr):
    if root is None:
        return
    recursion(root.left, arr)
    arr.append(root.data)
    recursion(root.right, arr)

def findMedian(root):
    arr = []
    recursion(root, arr)
    le = len(arr)
    if le % 2 == 0:
        m = (arr[le//2-1] + arr[le//2])
        return m // 2 if m % 2 == 0 else m / 2

    return arr[le//2]