从尾到头打印链表&&重建二叉树

从尾到头打印链表

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

思路

  • 解法1
    栈结构存储数据。正向遍历,将node.val压栈,利用栈先进后出的特点,返回ArrayList。
  • 解法2
    链表结构反向。创建三个指针cur,pre,temp。遍历链表时,pre为cur的前驱节点,temp保存cur的后继节点后,修改cur的后继节点为pre。遍历结束时,cur指向空,pre指向尾节点。从尾节点开始遍历,返回链表值即可。
  • 解法3
    递归思想求解。将问题化简为更小的问题。每次调用函数时,在ArrayList的尾端添加node.val,head节点在ArrayList[-1]添加元素,head.next在ArrayList[:1][-1]中添加元素。递归的出口是None,此时创建空的ArrayList。
    注意:Python中list的append方法没有返回值,因此采用“+”这种组合列表的方法。

代码

# -*- coding: utf-8 -*-
class ListNode:
    def __init__(self,x):
        self.val = x
        self.next = None

class Solution:
    def printListFromTailToHead1(self,listNode):                                        #利用栈的先进后出
        temp,res = [],[]                                                                #额外空间复杂度O(n)
        while listNode:
            temp.append(listNode.val)                                                   #temp中存储正向链表值
            listNode = listNode.next
        while temp:
            res.append(temp.pop())                                                      #res中存储反向链表值
        return res

    def printListFromTailToHead2(self,listNode):                                        #反转链表指针
        res = []                                                                        #额外空间复杂度O(1)
        cur,pre = listNode,None
        while cur:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp                                                                  #循环结束时,链表反向,pre指向尾节点
        while pre:
            res.append(pre.val)
            pre = pre.next
        return res

    def printListFromTailToHead3(self,listNode):                                        #方法1的递归版本
        if not listNode:
            return []
        return self.printListFromTailToHead3(listNode.next)+[listNode.val]              #用+代替append

    def printListFromTailToHead4(self,listNode):                                        #方法1的错误递归版本
        if not listNode:
            return []
        return self.printListFromTailToHead4(listNode.next).append(listNode.val)        #a.append(1)无返回值
            
        
if __name__ == "__main__":
    listNode = ListNode(1)
    listNode.next = ListNode(2)
    listNode.next.next = ListNode(3)
    solution = Solution()
    print solution.printListFromTailToHead4(listNode)

重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
注意: 输入前序和后序的数据类型是List,输出返回类型为Node

思路

递归思想求解。考虑到二叉树根节点的lchild和rchild也是二叉树,将问题化简成更小的问题。每次递归中,前序中的首节点为树的根节点root,在中序序列中,root的左边是root.lchild,root的右边是root.rchild。而root.lchild是左子树的根节点,处理方法相同。递归函数的出口是,前序数组长度为1(此时中序数组也为1),创建叶节点并返回。
特殊情况,前序数组长度为1,说明没有左子树或右子树,返回None。

代码

# -*- coding: utf-8 -*-
class TreeNode:
    def __init__(self,x):
        self.val = x
        self.left = None
        self.right = None
        
    def preOrderRec(self,x):                                                                    #测试函数
        if x is None:
            return
        print x.val,
        self.preOrderRec(x.left)
        self.preOrderRec(x.right)
        
class Solution:
    def reConstructBinaryTree(self,pre,tin):                                                    #递归实现二叉树重建
        if len(pre) == 0:                                                                       #没有子树
            return None
        elif len(pre) == 1:                                                                     #pre[0]对应叶节点
            return TreeNode(pre[0])
        else:
            root = TreeNode(pre[0])
            rootIndex = tin.index(pre[0])                                                   
            root.left = self.reConstructBinaryTree(pre[1:rootIndex+1],tin[:rootIndex+1])       #中序中,根节点左侧为左子树
            root.right = self.reConstructBinaryTree(pre[rootIndex+1:],tin[rootIndex+1:])       #中序中,根节点右侧为右子树 
            return root

if __name__ == "__main__":
    pre = [1,2,4,7,3,5,6,8]
    tin = [4,7,2,1,5,3,8,6]
    solution = Solution()
    root = solution.reConstructBinaryTree(pre,tin)
    root.preOrderRec(root)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值