剑指offer6&7&8&9-链表&树&栈

Posted lyeeer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer6&7&8&9-链表&树&栈相关的知识,希望对你有一定的参考价值。

题目6 

输入一个链表的头节点,从尾到头反过来打印出每个结点的值

思路

1.使用递归。逆序打印a->b->c->d,可以先逆序打印b->c->d(看成新的链表),再打印a;那么同样逆序可以先逆序打印c->d,再打印b;直到打印到尾节点。

2.使用栈。栈具有后进先出的特点,刚好符合逆序要求。遍历链表时将值按顺序放入栈中,最后依次出栈。

 

解法

    class ListNode{
        int m_nKey;
        ListNode m_pNext;
    }
    //递归法
    public void PrintListReversingByRecursive(ListNode listNode) {
        if(listNode != null) {
            if(listNode.m_pNext!=null) {
                PrintListReversingByRecursive(listNode.m_pNext);
            }
            System.out.print(listNode.m_nKey+"	");
        }
    }
    //栈
    public void PrintListReversingByStack(ListNode listNode) {
        Stack<ListNode> stack=new Stack<ListNode>();
        while(listNode != null) {
            stack.push(listNode);
            listNode=listNode.m_pNext;
        }
        while(!stack.empty()) {
            System.out.print(stack.pop().m_nKey+"	");
        }
    }

 题目7

根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

思路

前序遍历-根左右

中序遍历-左根右

后序遍历-左右根

前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序遍历结果,右部分为右子树中序遍历结果。

然后不断根据左子树的中序和前序遍历结果构造左子树,右子树同理。

不断递归,得到结果。

解法

    class BinaryTreeNode{
        int m_nValue;
        BinaryTreeNode m_nLeft;
        BinaryTreeNode m_nRight;
        BinaryTreeNode(int m_nValue){
            this.m_nValue=m_nValue;
        }
    }
    
    public BinaryTreeNode Construct(int preorder[], int inorder[]) {
        if(preorder==null || inorder==null) {
            return null;
        }
        return ConstructCore(preorder, 0, preorder.length-1, inorder, 0, inorder.length-1); 
    }
    public BinaryTreeNode ConstructCore(int preorder[], int startPreorder,
            int endPreorder, int inorder[], int startInorder, int endInorder) {
        //停止递归的条件
        if(startPreorder>endPreorder || startInorder>endInorder) {
            return null;
        }
        //前序遍历的第一个数字是根节点
        BinaryTreeNode root=new BinaryTreeNode(preorder[startPreorder]);
        for(int i=startInorder;i<=endInorder;i++) {
            if(preorder[startPreorder]==inorder[i]) {
                //根据左子树的前序和中序遍历,构建左子树。i-startInorder为中序排列中左子树节点的个数
                root.m_nLeft=ConstructCore(preorder,startPreorder+1,
                        startPreorder+(i-startInorder), inorder, startInorder, i-1);
                //根据右子树的前序和中序遍历,构建右子树
                root.m_nRight=ConstructCore(preorder, startPreorder+1+(i-startInorder),
                        endPreorder, inorder, i+1, endInorder);
            }    
        }
        return root;
    }

 

题目8

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

思路

1.如果节点右子树不为空,那么该节点的下一个节点是右子树的最左节点。

2.如果右子树不为空,那么就是第一个左链接指向的树包含该节点的祖先节点。即沿着指向父节点的指针一路向上遍历,直到找到一个是它父节点的左子节点的节点。如果这个节点存在,那么这个节点的父节点就是下一个节点。

可以画出图来,找规律。

解法

    public class TreeLinkNode{
        int data;
        TreeLinkNode left=null;
        TreeLinkNode right=null;
        TreeLinkNode next=null;
        TreeLinkNode(int data){
            this.data=data;
        }    
    }
    
    public TreeLinkNode getNext(TreeLinkNode tNode) {
        if(tNode.right!=null) {
            TreeLinkNode node=tNode.right;
            while(node.left!=null) {
                node=node.left;
            }
            return node;
        }
        else {
            while(tNode.next!=null) {
                TreeLinkNode parent=tNode.next;
                if(parent.left==tNode) {
                    return parent;
                }
                tNode=tNode.next;
            }
        }    
        return null;
    }

题目9

 

用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。

思路

栈:后进先出

队列:先进先出

解答

 

 

扩展

以上是关于剑指offer6&7&8&9-链表&树&栈的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer-最小的K个数

剑指offer-最小的K个数

[剑指Offer]7-重建二叉树

剑指offer-二叉搜索树的第k个结点

刷题记录-剑指offer6:从尾到头打印链表

剑指offer6-用两个栈实现队列