每天1题算法题(1)-二叉树的中序遍历

给定一个二叉树,返回它的中序 遍历。

 

输入: [1,null,2,3]
   1
    \
     2
    /
   3

输出: [1,3,2]


1.最简单也是最直接的,直接用递归算法实现
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> result = new ArrayList();
            dfs(root,result);
              return result;
    }

    public void dfs(TreeNode root, List list) {
        if(root == null) {
            return;
        }
        dfs(root.left, list);
        list.add(root.val);
        dfs(root.right, list);
    }

}
 

缺点:

效率低下

2.用迭代模拟递归
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> result = new ArrayList();
            Stack<TreeNode> stack = new Stack();
            while(stack.size() > 0 || root != null) {
                if(root != null) {
                    stack.add(root);
                    root = root.left;
                } else {
                    root = stack.pop();
                    result.add(root.val);
                    root = root.right;
                }
            }
            return result;
    }

}

  

缺点:

效率低下
3.莫里斯遍历
用递归和迭代的方式都使用了辅助的空间,而莫里斯遍历的优点是没有使用任何辅助空间。
缺点是改变了整个树的结构,强行把一棵二叉树改成一段链表结构。

 

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        TreeNode pre = null;
        while(root!=null) {
            //如果左节点不为空,就将当前节点连带右子树全部挂到
            //左节点的最右子树下面
            if(root.left!=null) {
                pre = root.left;
                while(pre.right!=null) {
                    pre = pre.right;
                }
                pre.right = root;
                //将root指向root的left
                TreeNode tmp = root;
                root = root.left;
                tmp.left = null;
            //左子树为空,则打印这个节点,并向右边遍历    
            } else {
                res.add(root.val);
                root = root.right;
            }
        }
        return res;
    }
}

 

进阶

 颜色标记法

其核心思想如下:

使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。
如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。
如果遇到的节点为灰色,则将节点的值输出。

class Solution {

    class ColorNode {
        TreeNode treeNode;
        String color;
        public ColorNode(String color, TreeNode treeNode) {
            this.treeNode = treeNode;
            this.color = color;
        }
    }

    public List<Integer> inorderTraversal(TreeNode root) {
            List<Integer> result = new ArrayList();
            if(root == null) {
                return result;
            }
            Stack<ColorNode> stack = new Stack();
            stack.push(new ColorNode("white", root));
            while(stack.size() > 0) {
                ColorNode colorNode = stack.pop();
                if("white".equals(colorNode.color)) {
                    if(colorNode.treeNode.right != null) {
                        stack.add(new ColorNode("white", colorNode.treeNode.right));
                    }
                    stack.add(new ColorNode("grey", colorNode.treeNode));
                    if(colorNode.treeNode.left != null) { 
                        stack.add(new ColorNode("white", colorNode.treeNode.left));
                    }
                } else {
                    result.add(colorNode.treeNode.val);
                }
            }
            return result;
    }

  如要实现前序、后序遍历,只需要调整左右子节点的入栈顺序即可。

 



posted @ 2020-09-16 20:30  GodTelMe  阅读(310)  评论(0编辑  收藏  举报