📜  在不构建树的情况下检查给定的中序和前序遍历是否对任何二叉树都有效(1)

📅  最后修改于: 2023-12-03 15:37:39.641000             🧑  作者: Mango

介绍-不构建树的情况下检查给定的中序和前序遍历是否对任何二叉树都有效

在二叉树中,前序遍历和中序遍历是经典的遍历方式。对于给定的前序和中序遍历,我们可以构造一棵唯一的二叉树。但是,反过来,如果我们只有前序和中序遍历,我们能否确定它们是有效的,即它们可以唯一地对应一棵二叉树呢?

答案是可以的!在本文中,我们将探讨如何在不构建二叉树的情况下检查给定的中序和前序遍历是否对任何二叉树都有效。

思路

首先,让我们回忆一下什么是前序遍历和中序遍历。前序遍历按照根节点、左子树、右子树的顺序遍历一颗二叉树,中序遍历则是先遍历左子树、再遍历根节点、最后遍历右子树。

因此,我们可以得到以下结论:

  • 前序遍历的第一个元素是根节点。
  • 在中序遍历中,根节点的左侧是它的左子树,右侧是它的右子树。

那么,我们可以采用递归的方法来检查给定的两个遍历数组是否有效。具体做法如下:

  • 如果任一数组为空,则该组遍历无效,返回false。

  • 如果前序遍历数组长度为1,则直接返回true。因为这意味着我们已经找到了一颗唯一的二叉树。

  • 在前序遍历数组中取第一个元素作为根节点。

  • 在中序遍历数组中找到根节点的位置,假设它在中序遍历数组中的索引为i。

  • 分别递归检查左子树和右子树,即:

  • 对前序遍历数组中从第二个元素到第i+1个元素进行递归调用。

  • 对前序遍历数组中从第i+2个元素到最后一个元素进行递归调用。

  • 对中序遍历数组中从第一个元素到第i个元素进行递归调用。

  • 对中序遍历数组中从第i+1个元素到最后一个元素进行递归调用。

  • 如果左子树和右子树都有效,则该组遍历有效。

代码

def is_valid(preorder: List[int], inorder: List[int]) -> bool:
    if not preorder or not inorder:
        return False
    if len(preorder) == 1 and len(inorder) == 1:
        return preorder[0] == inorder[0]
    root = preorder[0]
    i = inorder.index(root)
    left_preorder = preorder[1:i+1]
    right_preorder = preorder[i+1:]
    left_inorder = inorder[:i]
    right_inorder = inorder[i+1:]
    return is_valid(left_preorder, left_inorder) and is_valid(right_preorder, right_inorder)

复杂度分析

在最坏情况下,我们需要检查每个节点,所以时间复杂度为O(n^2),其中n是节点数。空间复杂度为递归栈的大小,最坏情况下为O(n)。