leetcode刷题自记录——剑指offer06. 从尾到头打印链表 07.重建二叉树

169 阅读3分钟

题目06——从尾到头打印链表

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。难度是easy

思路和代码

还是比较简单的,对于python来说遍历一遍链表取出结点值存入list然后翻转list即可

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        if not head:
            return []

        res = []

        while head:
            res.append(head.val)
            head = head.next

        return res[::-1]

题目07——重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。难度是medium

思路

对于一颗二叉树,前序遍历遍历顺序为中左右,中序遍历遍历顺序为左中右。

     3
    / \
   9   20
  / \  / \
 8  4 15  7

以上面这个二叉树为例,它的前序遍历是[3,9,8,4,20,15,7],中序遍历是[8,9,4,3,15,20,7],想了很久没有什么特别好的思路,这里直接按照官方题解的思路写一下。

首先用一个栈stack来维护当前节点的所有还没有考虑过右儿子的祖先节点,栈顶就是当前元素。因为中序遍历是按照左中右的顺序,所以中序遍历的首元素一定是二叉树中看起来最靠右的。我们用指针index指向中序遍历的首元素,它对应的节点就是从当前节点不断往左走达到的最终节点。以上述例子为例,中序遍历的首元素 8,就对应了从前序遍历首元素 3 一直往左走能到达的尽头。

首先我们将根节点 3 入栈,再初始化 index 所指向的节点为 8 ,随后对于前序遍历中的每个节点,我们依次判断它是栈顶节点的左儿子,还是栈中某个节点的右儿子。

先遍历 9 ,发现其是 3 的左儿子,原因是如果如果 9 是右儿子,则该树没有左儿子,中序遍历的首元素应该就是前序遍历的首元素,因此利用反证法说明 9 是 3 的左儿子,入栈。同理 8 也入栈。此时栈元素为[3,9,8]

当遍历到元素 4 时,发现栈顶元素为 8 ,中序遍历index指向元素也为 8 ,说明 4 没有左儿子,而是栈中某个节点的右儿子。

那么如何找到这个节点呢?栈中的节点的顺序和它们在前序遍历中出现的顺序是一致的,而且每一个节点的右儿子都还没有被遍历过,那么这些节点的顺序和它们在中序遍历中出现的顺序一定是相反的。

因此把index向右移并且和栈顶元素进行比较,如果一致则弹出栈顶并使index加1,直到出现第一个不相等的比较,则最后一个弹出的节点即为改右儿子的父节点。

在本例子中,8和8比较,相等,index+1,8出栈;9和9比较,相等,index+1,9出栈。3和4比较,不相等,则说明4是最后一个弹出元素9的右儿子。我们将4入栈。此时栈中情况为[3,4],index指向中序遍历中的元素4,重复上面的步骤,将4和3弹出,index向右移,使得栈空且index指向中序遍历元素15。

接下来问题就简化成了前序遍历为[20,15,7],中序遍历为[15,20,7]的二叉树的重建。

   20
   / \
  15  7

最终重建出全部的二叉树。

代码

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if not preorder:
            return None
            
        root = TreeNode(preorder[0])
        stack = [root]
        index = 0

        for i in range(1, len(preorder)):
            preval = preorder[i]
            stacktop = stack[-1]
            
            if stacktop.val != inorder[index]:
                stacktop.left = TreeNode(preval)
                stack.append(stacktop.left)
            
            else:
                while stack and stack[-1].val == inorder[index]:
                    stacktop = stack.pop()
                    index+=1
                stacktop.right = TreeNode(preval)
                stack.append(stacktop.right)
                
        return root