144. Binary Tree Preorder Traversal

题目:

Given a binary tree, return the preorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    
     2
    /
   3

return [1,2,3].

Note: Recursive solution is trivial, could you do it iteratively?

Hide Tags
 Tree Stack
 

连接: http://leetcode.com/problems/binary-tree-preorder-traversal/

题解:

二叉树先序遍历, root -> left -> right。使用一个栈来维护已经访问过的节点。当root不为空时,当前节点入栈,输出节点值,继续向左子树遍历。当root为空,从栈中弹出节点,向右子树进行遍历。

Iterative:

Time Complexity - O(n),  Space Complexity - O(n)。

public class Solution {
    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if(root == null)
            return result;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        
        while(root != null || !stack.isEmpty()){
            if(root != null){
                stack.push(root);
                result.add(root.val);
                root = root.left;
            } else {
                root = stack.pop();
                root = root.right;
            }
        }
        
        return result;
    }
}

Recursive:

Time Complexity - O(n), Space Complexity - O(n)。

public class Solution {
    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if(root == null)
            return result;
        helper(result, root);
        return result;
    }
    
    private void helper(ArrayList<Integer> result, TreeNode root){
        if(root == null)
            return;
        result.add(root.val);
        helper(result, root.left);
        helper(result, root.right);
    }
}

Update:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root == null)
            return res;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        
        while(!stack.isEmpty()) {
            root = stack.pop();
            if(root != null) {
                res.add(root.val);
                if(root.right != null)
                    stack.push(root.right);
                if(root.left != null)
                    stack.push(root.left);
            }
        }
        
        return res;
    }
}

Morris-Travel: 待定。

二刷:

Java:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Stack<TreeNode> stack = new Stack<>();
        while (root != null || !stack.isEmpty()) {
            if (root != null) {
                res.add(root.val);
                stack.push(root.right);
                root = root.left;
            } else {
                root = stack.pop();
            }
        }
        return res;
    }
}

三刷:

Java:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        
        while (!stack.isEmpty() || root != null) {
            if (root != null) {
                res.add(root.val);
                stack.push(root.right);
                root = root.left;
            } else {
                root = stack.pop();
            }
        }
        return res;
    }
}

Recursive:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preorderTraversal(res, root);
        return res;
    }
    
    private void preorderTraversal(List<Integer> res, TreeNode root) {
        if (root == null) return;
        res.add(root.val);
        preorderTraversal(res, root.left);
        preorderTraversal(res, root.right);
    }
}

三刷:

Java:

Iterative with a stack:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        TreeNode node = root;
        Stack<TreeNode> stack = new Stack<>();
        while (node != null || !stack.isEmpty()) {
            if (node != null) {
                res.add(node.val);
                stack.push(node);
                node = node.left;
            } else {
                node = stack.pop();
                node = node.right;
            }
        }
        return res;
    }
}

Recursive:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preorderTraversal(res, root);
        return res;
    }
    
    private void preorderTraversal(List<Integer> res, TreeNode root) {
        if (root == null) return;
        res.add(root.val);
        preorderTraversal(res, root.left);
        preorderTraversal(res, root.right);
    }
}

Morris traversal:

使用了类似in-order Morris Traversal类似的代码。在可以改变树结构的情况下,使用空的右子树来连接到父节点,最后再还原树结构。下面详述一下步骤:

  1. 在当前node非空的情况下对树进行遍历。仍然是先判断左子树是否为空,假如为空,则我们将当前节点node.val加入到结果集里,继续向右遍历树
  2. 否则左子树非空,这时我们向左子树里查找当前节点node的predecessor,简称prev,即左子树中最右端的元素。依然是两种情况:
    1. 当prev.right为空时,我们第一次访问此节点,这时把prev.right设置为当前节点node,然后把当前节点node.val加入到结果集里,向左遍历树
    2. 否则prev.right = 为当前node,说明我们是第二次访问这个节点,这时要做一个树的还原操作,也就是断开prev和node的连接,即prev.right = null,然后向右遍历树。这时候因为我们的当前节点node已经被处理过了,所以不要再次处理node.val 
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        TreeNode node = root, prev = null;
        while (node != null) {
            if (node.left == null) {
                res.add(node.val);
                node = node.right;
            } else {
                prev = node.left;
                while (prev.right != null && prev.right != node) {
                    prev = prev.right;
                }
                if (prev.right == null) {
                    prev.right = node;
                    res.add(node.val);
                    node = node.left;
                } else {
                    prev.right = null;
                    node = node.right;
                }
            }
        }
        return res;
    }
}

Update:

简化了一下,反而比较古怪,不易理解。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        TreeNode node = root, prev = null;
        while (node != null) {
            prev = node.left;
            while (prev != null && prev.right != null && prev.right != node) {
                prev = prev.right;
            }
            if (prev != null && prev.right == null) {
                prev.right = node;
                res.add(node.val);
                node = node.left;
            } else {
                if (prev != null) prev.right = null;
                else res.add(node.val);
                node = node.right;
            }    
        }
        return res;
    }
}

Reference:

https://leetcode.com/discuss/9734/accepted-code-explaination-with-algo

https://leetcode.com/discuss/5331/whats-the-simplest-and-cleanest-answer

https://leetcode.com/discuss/23326/very-simple-iterative-python-solution

https://leetcode.com/discuss/19798/accepted-iterative-solution-in-java-using-stack

https://leetcode.com/discuss/32904/3-different-solutions

https://leetcode.com/discuss/49926/easy-read-java-solutions-for-both-iterative-recursive-300ms

https://leetcode.com/discuss/46894/java-solution-both-recursion-and-iteration 

94. Binary Tree Inorder Traversal

原文地址:https://www.cnblogs.com/yrbbest/p/4483758.html