# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def preorderTraversal(self, root):
result = []
def dfs(node):
if not node:
return
result.append(node.val)
dfs(node.left)
dfs(node.right)
dfs(root)
return result
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
preorder(root, result);
return result;
}
private:
void preorder(TreeNode* node, vector<int>& result) {
if (!node) return;
result.push_back(node->val);
preorder(node->left, result);
preorder(node->right, result);
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
preorder(root, result);
return result;
}
private void preorder(TreeNode node, List<Integer> result) {
if (node == null) return;
result.add(node.val);
preorder(node.left, result);
preorder(node.right, result);
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var preorderTraversal = function(root) {
const result = [];
function dfs(node) {
if (!node) return;
result.push(node.val);
dfs(node.left);
dfs(node.right);
}
dfs(root);
return result;
};
You are given the root
of a binary tree. Your task is to return the preorder traversal of its nodes' values as a list or array.
In preorder traversal, you visit the root node first, then recursively visit the left subtree, followed by the right subtree.
root
is null
).When asked to traverse a binary tree in preorder, the first idea is to simply "visit the root, then the left, then the right." This naturally suggests using recursion, since each subtree can be treated as a smaller tree with the same rules. The brute-force approach is to manually keep track of the order, but recursion simplifies this by using the call stack.
Alternatively, if we want to avoid recursion (for example, to prevent stack overflow on very deep trees), we can use an explicit stack to simulate the process.
Both approaches must ensure that every node is visited exactly once, and in the correct order: root, left, right. We also need to handle the case where the tree is empty.
root
node.null
, add its value to the result list.root
node (if not null
).
Example Tree:
1 \ 2 / 3
1
. Add 1
to result.null
, so move to right child: 2
. Add 2
to result.2
is 3
. Add 3
to result.3
has no children, so traversal is complete.
Final preorder traversal: [1, 2, 3]
O(N)
, where N
is the number of nodes. Each node is visited exactly once.O(N)
in the worst case (skewed tree), due to the recursion stack and the output list.O(N)
for the same reason: each node is processed once.O(N)
for the stack in the worst case (all nodes on one side).The preorder traversal problem is a classic example of tree traversal, easily solved using recursion or an explicit stack. The key insight is to process nodes in the order: root, left, right. Both recursive and iterative approaches achieve this efficiently, with time and space complexity linear in the number of nodes. This problem demonstrates how breaking a problem into smaller subproblems (recursion) or simulating recursion with a stack can simplify tree algorithms.