征战二叉树-第二站

继上一篇二叉树之后,这次加深难度了,对前序、后序、中序遍历的迭代算法进行练习了一下,还有一些其他算法,那就来快看一下吧!

1. 前序遍历(迭代)

/**
 * 前序遍历的迭代算法
 * 要点:使用栈来进行装载节点
 * @param root
 * @return
 */
public List<T> preOrderWithIteration(TreeNode<T> root){

    if (root == null) {
        return null;
    }

    List<T> list = new ArrayList<T>();
    Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();
    stack.push(root);
    while(!stack.isEmpty()){
        TreeNode<T> currentNode = stack.pop();
        list.add(currentNode.getData());

        if (currentNode.right != null) {
            stack.push(currentNode.right);
        }

        if (currentNode.left != null) {
            stack.push(currentNode.left);
        }
    }
    return list;
}

2. 中序遍历(迭代)

/**
     * 中序遍历的迭代算法
     * @param root
     * @return
     */
    public List<T> inOrderWithIteration(TreeNode<T> root){

        if(root == null){
            return null;
        }
        List<T> list = new ArrayList<T>();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();

        while(root != null || !stack.isEmpty()){

            while(root != null){
                stack.push(root);
                root = root.left;
            }
            if (!stack.isEmpty()) {

                TreeNode<T> currentNode = stack.pop();
                list.add(currentNode.getData());
                root = currentNode.right;
            }
        }
        return list;
 }

3. 后序遍历(迭代)

思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存 在左孩子或者右孩子, 但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了 每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结>点前面被访问。

/**
     * 后序遍历,非递归算法
     * @param root
     * @return
     */
    public List<T> postOrderWithIteration(TreeNode<T> root){

        if(root == null){
            return null;
        }

        List<T> list = new ArrayList<T>();
        Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();
        TreeNode<T> curNode;
        TreeNode<T> preNode = null;
        stack.push(root);

        while(!stack.isEmpty()){

            curNode = stack.peek();
            if ((curNode.left == null && curNode.right == null) || (preNode != null
                    && (preNode == curNode.left || preNode == curNode.right))) {

                list.add(curNode.getData());
                preNode = curNode;
                stack.pop();
            }
            else {
                if (curNode.right != null) {
                    stack.push(curNode.right);
                }
                if(curNode.left != null){
                    stack.push(curNode.left);
                }
            }
        }
        return list;
    }

4. 判断两个二叉树是否镜像

/**
     * 判断两个二叉树是否镜像
     * @param root1
     * @param root2
     * @return
     */
    public boolean isMirror(TreeNode<T> root1,TreeNode<T> root2){

        if (root1 == null && root2 == null) {
            return true;
        }
        else if (root1 != null || root2 != null) {
            return false;
        }
        else if(root1.getData() != root2.getData()){
            return false;
        }

        return isMirror(root1.left, root2.right) && isMirror(root1.right, root2.left);

    }

5. 求镜像二叉树,或者是翻转二叉树

/**
     * 求镜像二叉树,或者是翻转二叉树
     * @param root
     * @return
     */
    public TreeNode<T> mirrorTreeNode(TreeNode<T> root){
        if (root == null) {
            return null;
        }
        TreeNode<T> left = mirrorTreeNode(root.left);
        TreeNode<T> right = mirrorTreeNode(root.right);

        root.left = right;
        root.right = left;

        return root;
    }

6. 寻找连个节点的最小祖先节点

/**
     * 寻找连个节点的最小祖先节点
     * @param root
     * @param nodeA
     * @param nodeB
     * @return
     */
    public TreeNode<T> getLowestAncestor(TreeNode<T> root,TreeNode<T> nodeA,TreeNode<T> nodeB){
        if (findNode(root.left,nodeA)) {
            if (findNode(root.right, nodeB)) {
                return root;
            }
            else {
                return getLowestAncestor(root.left, nodeA, nodeB);
            }

        }
        else {
            if (findNode(root.left, nodeB)) {
                return root;
            }
            else {
                return getLowestAncestor(root.right, nodeA, nodeB);
            }
        }

    }

    private boolean findNode(TreeNode<T> root, TreeNode<T> node) {

        if (root == null || node == null) {
            return false;
        }
        if (root == node) {
            return true;
        }
        boolean isFound = findNode(root.left, node);
        if (!isFound) {
            isFound = findNode(root.right, node);
        }
        return isFound;
    }

7. 获取二叉树两个节点之间最大距离

思路:二叉树中两个节点的最长距离可能有三种情况:

1.左子树的最大深度+右子树的最大深度为二叉树的最长距离

2.左子树中的最长距离即为二叉树的最长距离

3.右子树种的最长距离即为二叉树的最长距离

    /**
     * 获取二叉树两个节点之间的最大距离
     * @param root
     * @return
     */
    public int getMaxDistance(TreeNode<T> root){

        return getMaxDistanceHolder(root).maxDistance;
    }

    private DistanceHolder getMaxDistanceHolder(TreeNode<T> root){

        if (root == null) {
            return new DistanceHolder(-1,0);
        }
        DistanceHolder leftHolder = getMaxDistanceHolder(root.left);
        DistanceHolder rightHolder = getMaxDistanceHolder(root.right);

        DistanceHolder result = new DistanceHolder();
        result.maxDepth = Math.max(leftHolder.maxDepth, rightHolder.maxDepth) + 1;
        result.maxDistance = Math.max(leftHolder.maxDepth + rightHolder.maxDepth,
                Math.max(leftHolder.maxDistance, rightHolder.maxDistance));

        return result;
    }

    /**
     * 用来持有距离的最大深度的类
     * @author Administrator
     *
     */
    private static class DistanceHolder{

        public int maxDistance;
        public int maxDepth;

        public DistanceHolder(){}
        public DistanceHolder(int maxDistance, int maxDepth) {
            this.maxDistance = maxDistance;
            this.maxDepth = maxDepth;
        }

    }

8. 输入一个二叉树和一个整数,打印出二叉树中节点值的和等于输入整数所有的路径

注意:这里的路径是指从根节点到叶子节点

/**
 *
 * @param root
 * @param k
 * @return
 */
public List<Integer> findAllPath(TreeNode<Integer> root,int k){
    List<Integer> list = new ArrayList<Integer>();
    if (root == null) {
        return list;
    }
    int sum = 0;
    Stack<TreeNode<Integer>> stack = new Stack<TreeNode<Integer>>();
    findAllPath(root, k,list,stack,sum);
    return list;
}

private void findAllPath(TreeNode<Integer> root, int k, List<Integer> list,
        Stack<TreeNode<Integer>> stack, int sum) {

    sum += root.getData();
    stack.push(root);
    if (root.left == null && root.right == null && sum == k) {

        for(TreeNode<Integer> node : stack){
            list.add(node.getData());
        }
    }

    if (root.left != null) {
        findAllPath(root.left, k, list, stack, sum);
    }
    if (root.right != null) {
        findAllPath(root.right, k, list, stack, sum);
    }

    stack.pop();//这里每次要弹出栈,因为到这里已经不满足条件了,需要将本次检索的元素清除掉
}

总结

以上就是本次练习的二叉树几道算法题,当然,还有其他实现的方式,如后序遍历的迭代算法还有其他思路,这里我就给出我认为比较容易理解的思路,仅做参考,如果你有比较好的思路和其他写法,可以分享出来!

下一次练习,就开始对二叉树查找树进行练习,敬请期待!

参考

一篇文章搞定面试中的二叉树题目(java实现)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 树的概述 树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构 1.树的定...
    Jack921阅读 4,373评论 1 31
  • 数据结构和算法--二叉树的实现 几种二叉树 1、二叉树 和普通的树相比,二叉树有如下特点: 每个结点最多只有两棵子...
    sunhaiyu阅读 6,336评论 0 14
  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,016评论 0 12
  • 基于树实现的数据结构,具有两个核心特征: 逻辑结构:数据元素之间具有层次关系; 数据运算:操作方法具有Log级的平...
    yhthu阅读 3,943评论 1 5
  • 去年二叉树算法的事情闹的沸沸扬扬,起因是Homebrew 的作者 @Max Howell 在 twitter 上发...
    Masazumi柒阅读 1,530评论 0 8