剑指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+"\t");
        }
    }
    //栈
    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+"\t");
        }
    }

题目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 操作。

思路

栈:后进先出

队列:先进先出

解答

扩展

原文地址:https://www.cnblogs.com/lyeeer/p/12199018.html

时间: 2024-11-08 06:54:26

剑指offer6&7&8&9-链表&树&栈的相关文章

剑指offer (37) 两个链表的第一个公共结点

题目:输入两个链表,找出它们的第一个公共结点 如果两个链表有公共结点,那么公共结点一定出现在两个链表的尾部 如果两链表长度不相等,那么达到公共结点的步数就不一致,如何确保 两个链表从头开始遍历,同步达到公共结点? 这是关键所在 如果两链表长度相同,那么就可以同步达到了? 由此,我们就需要 让两个链表长度"相等" 我们假设 两链表长度分别为m和n,且m > n, 那么我们可以在较长链表中 先走 m - n 步,然后 两个链表游标同步走,如果有公共结点,那么就一定同时达到 ListN

剑指OFFER之合并有序链表(九度OJ1519)

题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则.(hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为两个整数n和m(0<=n<=1000, 0<=m<=1000):n代表将要输入的第一个链表的元素的个数,m代表将要输入的第二个链表的元素的个数.下面一行包括n个数t(1<=t<=1000000):代表链表一中的元素.接下来一行包含m个元素,s(1<

【剑指offer】两个链表的第一个公共结点

转载请注明出处:http://blog.csdn.net/ns_code/article/details/26097395 简单题,剑指offer上的第37题,九度OJ上AC. 题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例.对于每个测试案例,输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的两个链表的元素的个数.接下来的两行,第一行为第一个链表的所有元素,中间用空格隔开.第二行为第二个链表的所有元素,中间用空格隔开. 输出: 对应

剑指offer-面试题7:俩个栈实现队列(java)

详细分析请参照C语言版,这里仅仅给出实现代码,注释很详细,不得不说java各种api用起来真是爽飞了 1 package com.xsf.SordForOffer; 2 3 import java.util.Stack; 4 5 /** 6 * 剑指offer pro7,俩个链表实现一个队列 7 * @author ELVIS 8 */ 9 class ListQueue{ 10 //定义俩个栈 11 private Stack<String> stack1 = new Stack<St

剑指offer之【复杂链表的复制】

题目: 复杂链表的复制 链接: https://www.nowcoder.com/practice/f836b2c43afc4b35ad6adc41ec941dba?tpId=13&tqId=11178&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为

【剑指offer】18.删除链表中重复节点

思路 实现 /* 说下大概思路: 与链表的其他题目类似,为了防止删除头结点的极端情况发生,先创建空结点dummy,使dummy指向传入的head结点. 然后创建cur的指针,指向链表的头部(即dummy). 接着对cur指针迭代,因为要对比cur(cur最初始的定义指向空结点)指针的下一个结点与下下一个结点的值是否相等,为了防止产生空指针异常,故退出迭代的条件为:cur.next != null && cur.next.next != null. 在迭代过程中,如果cur.next.val

【剑指offer】包括min函数的栈

转载请注明出处:http://blog.csdn.net/ns_code/article/details/26064213 剑指offer上的第21题,之前在Cracking the Coding interview上做过,思路參考这里,这次写了測试函数,在九度OJ上測试通过. 题目描写叙述: 定义栈的数据结构,请在该类型中实现一个可以得到栈最小元素的min函数. 输入: 输入可能包括多个測试例子,输入以EOF结束.对于每一个測试案例,输入的第一行为一个整数n(1<=n<=1000000),

剑指offer 56.删除有序链表中的重复结点

56. 删除有序链表中的重复结点 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 分析 借助辅助头结点,可避免单独讨论头结点的情况.设置两个结点 pre 和 cur,当 cur 和 cur.next 值相等,cur 一直向前走,直到不等退出循环,这时候 cur 指的值还是重复值,调整 cur 和 pre 的指针再次判断 /*

剑指offer六:反转链表

输入一个链表,反转链表后,输出链表的所有元素 public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } public class Solution { public ListNode ReverseList(ListNode head) { ListNode pre = null; ListNode next = null; while(head != null){