代码随想录第十三天| 递归遍历 、 迭代遍历、统一迭代、层序遍历

二叉树遍历笔记


144. 二叉树的前序遍历

题目:给定一个二叉树的根节点 root ,返回其节点值的 前序遍历

解题思路
前序遍历顺序为:根节点 -> 左子树 -> 右子树。使用递归的方法,将当前节点值加入到结果列表中,然后递归遍历其左子节点,再递归遍历其右子节点。

代码

class Solution {
    public void traversal(TreeNode root, List<Integer> result) {
        if (root == null) {
            return;
        }
        result.add(root.val); // 访问根节点
        traversal(root.left, result); // 递归遍历左子树
        traversal(root.right, result); // 递归遍历右子树
    }

    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        traversal(root, result);
        return result;
    }
}

145. 二叉树的后序遍历

题目:给定一个二叉树的根节点 root ,返回其节点值的 后序遍历

解题思路
后序遍历顺序为:左子树 -> 右子树 -> 根节点。通过递归遍历左子树,然后递归遍历右子树,最后将当前节点值加入结果列表中。

代码

class Solution {
    public void traversal(TreeNode root, List<Integer> result) {
        if (root == null) {
            return;
        }
        traversal(root.left, result); // 递归遍历左子树
        traversal(root.right, result); // 递归遍历右子树
        result.add(root.val); // 访问根节点
    }

    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        traversal(root, result);
        return result;
    }
}

94. 二叉树的中序遍历

题目:给定一个二叉树的根节点 root ,返回其节点值的 中序遍历

解题思路
中序遍历顺序为:左子树 -> 根节点 -> 右子树。先递归遍历左子树,之后将当前节点值加入结果列表,再递归遍历右子树。

代码

class Solution {
    public void traversal(TreeNode root, List<Integer> result) {
        if (root == null) {
            return;
        }
        traversal(root.left, result); // 递归遍历左子树
        result.add(root.val); // 访问根节点
        traversal(root.right, result); // 递归遍历右子树
    }

    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        traversal(root, result);
        return result;
    }
}

二叉树遍历笔记(迭代法)


144. 二叉树的前序遍历(迭代法)

题目:给定一个二叉树的根节点 root ,返回其节点值的 前序遍历

解题思路
前序遍历顺序为:根节点 -> 左子树 -> 右子树。使用栈来模拟递归调用的过程,将根节点首先加入栈中,然后在每次迭代中将栈顶节点弹出并访问该节点,将右子节点和左子节点(如果存在)依次压入栈中,确保左子节点先于右子节点访问。

代码

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

145. 二叉树的后序遍历(迭代法)

题目:给定一个二叉树的根节点 root ,返回其节点值的 后序遍历

解题思路
后序遍历顺序为:左子树 -> 右子树 -> 根节点。可以先使用栈进行 根 -> 右 -> 左 的顺序遍历,将节点值添加到结果列表,然后将列表反转得到正确的后序遍历顺序。

代码

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        if (root == null) {
            return result;
        }
        Stack<TreeNode> st = new Stack<>();
        st.push(root);
        while (!st.isEmpty()) {
            TreeNode node = st.pop();
            result.add(node.val);
            if (node.left != null) st.push(node.left);
            if (node.right != null) st.push(node.right);
        }
        // Reverse the result list to get the correct order
        int left = 0;
        int right = result.size() - 1;
        while (left < right) {
            int temp = result.get(left);
            result.set(left, result.get(right));
            result.set(right, temp);
            left++;
            right--;
        }
        return result;
    }
}

94. 二叉树的中序遍历(迭代法)

题目:给定一个二叉树的根节点 root ,返回其节点值的 中序遍历

解题思路
中序遍历顺序为:左子树 -> 根节点 -> 右子树。使用栈模拟递归过程,将所有左子节点依次压入栈中,直到遇到最左下的节点,然后出栈访问节点,并将其右子节点(如果存在)继续处理。

代码

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        if (root == null) {
            return result;
        }
        Stack<TreeNode> st = new Stack<>();
        TreeNode node = root;

        while (node != null || !st.isEmpty()) {
            if (node != null) {
                st.push(node);
                node = node.left;
            } else {
                node = st.pop();
                result.add(node.val);
                node = node.right;
            }
        }
        return result;
    }
}

二叉树遍历笔记(统一迭代法)


144. 二叉树的前序遍历(统一迭代法)

题目:给定一个二叉树的根节点 root ,返回其节点值的 前序遍历

解题思路
采用统一迭代法,通过在每个节点前加入一个空节点标记。遇到节点时,将右子节点和左子节点依次压入栈,并将当前节点及一个空节点(用于标记访问)压入栈。遇到空节点时,弹出栈顶元素,将真正的节点值加入结果列表。

代码

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

145. 二叉树的后序遍历(统一迭代法)

题目:给定一个二叉树的根节点 root ,返回其节点值的 后序遍历

解题思路
使用统一迭代法,在每个节点访问前添加空节点标记。首先将节点本身加入栈,再依次将其右子节点和左子节点压入栈。遇到空节点时,从栈中弹出真正的节点并将其值加入结果列表。

代码

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

94. 二叉树的中序遍历(统一迭代法)

题目:给定一个二叉树的根节点 root ,返回其节点值的 中序遍历

解题思路
在中序遍历中,使用统一迭代法,通过在访问前加入空节点标记。将左子节点首先压入栈,空节点次之,再将右子节点压入栈。遇到空节点时,弹出栈顶元素,访问真正的节点并添加到结果列表。

代码

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

层序遍历
102.二叉树的层序遍历(opens new window)
题目:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
解题思路:
代码:

class Solution {
	public List<List<Integer>> resList = new ArrayList<List<Integer>>();
    public List<List<Integer>> levelOrder(TreeNode root) {
		checkFun01(root,0);
		return resList;
    }
	public void checkFun01(TreeNode node,int deep){
		if(node == null)return;
		deep++;
		if(resList.size()<deep){
			List<Integer> item = new ArrayList<Integer>();
			resList.add(item);
		}
		resList.get(deep-1).add(node.val);
		checkFun01(node.left, deep);
		checkFun01(node.right,deep);
	}
	public void checkFun02(TreeNode root){
		if(root==null){
			return;
		}
		Queue<TreeNode> que = new LinkedList<TreeNode>();
		que.offer(root);
		while(!que.isEmpty()){
			List<Integer> item = new ArrayList<Integer>();
			int size = que.size();
			while(size>0){
				TreeNode node = que.poll();
				item.add(node.val);
				if(node.left!=null)que.offer(node.left);
				if(node.right!=null)que.offer(node.right);
				size--;
			}
			resList.add(item);
		}
	}
}

107.二叉树的层次遍历II(opens new window)
题目:给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
解题思路:
代码:

class Solution {
	public List<List<Integer>> levelOrderBottom(TreeNode root) {
		// 利用链表可以进行 O(1) 头部插入, 这样最后答案不需要再反转
		List<List<Integer>> list = new ArrayList<>();
		Deque<TreeNode> que = new LinkedList<>();

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

		que.offerLast(root);
		while (!que.isEmpty()) {
			List<Integer> levelList = new ArrayList<>();

			int levelSize = que.size();
			for (int i = 0; i < levelSize; i++) {
				TreeNode peek = que.peekFirst();
				levelList.add(que.pollFirst().val);

				if (peek.left != null) {
					que.offerLast(peek.left);
				}
				if (peek.right != null) {
					que.offerLast(peek.right);
				}
			}
			list.add(levelList);
		}

		List<List<Integer>> result = new ArrayList<>();
		for (int i = list.size() - 1; i >= 0; i-- ) {
			result.add(list.get(i));
		}

		return result;
	}
}

199.二叉树的右视图(opens new window)
题目:给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
解题思路:
代码:

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
		Queue<TreeNode> que = new LinkedList<TreeNode>();
		if(root==null){
			return result;
		}
		que.offer(root);
		while(!que.isEmpty()){
			int len = que.size();
			TreeNode node = null;
			while(len>0){
				node = que.poll();
				if(node.left!=null)que.offer(node.left);
				if(node.right!=null)que.offer(node.right);
				len--;
			}
			result.add(node.val);
		}
		return result;
    }
}

637.二叉树的层平均值(opens new window)
题目:
解题思路:
代码:

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
		List<Double> result = new ArrayList<Double>();
		Queue<TreeNode> que = new LinkedList<TreeNode>();
		if(root==null){
			return result;
		}
		que.offer(root);
		while(!que.isEmpty()){
			int len = que.size();
			TreeNode node = null;
			Double sum = 0.0;
			int count = 0;
			while(len>0){
				node = que.poll();
				if(node.left!=null)que.offer(node.left);
				if(node.right!=null)que.offer(node.right);
				len--;
				sum = sum + node.val;
				count++;
			}
			result.add(sum/count);
		}
		return result;
	}
}

429.N叉树的层序遍历(opens new window)
题目:给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。
解题思路:
代码:

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
		List<List<Integer>> resList = new ArrayList<List<Integer>>();

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

		Queue<Node> que = new LinkedList<Node>();
		que.offer(root);
		while(!que.isEmpty()){
			List<Integer> item = new ArrayList<Integer>();
			int size = que.size();
			while(size>0){
				Node node = que.poll();
				if (node != null){
					item.add(node.val);
					List<Node> children = node.children;
					for(Node child:children){
						if(child!=null){
							que.offer(child);
						}
					}
				}
				size--;

			}
			resList.add(item);
		}
		return resList;
    }
}

515.在每个树行中找最大值(opens new window)
题目:您需要在二叉树的每一行中找到最大的值。
解题思路:
代码:

class Solution {
    public List<Integer> largestValues(TreeNode root) {
		List<Integer> result = new ArrayList<Integer>();
		Queue<TreeNode> que = new LinkedList<TreeNode>();
		if(root==null){
			return result;
		}
		que.offer(root);
		while(!que.isEmpty()){
			int len = que.size();
			TreeNode node = null;
			int max = Integer.MIN_VALUE;
			while(len>0){
				node = que.poll();
				if(node.left!=null)que.offer(node.left);
				if(node.right!=null)que.offer(node.right);
				len--;
				if(node.val>max)max=node.val;
			}
			result.add(max);
		}
		return result;
    }
}

116.填充每个节点的下一个右侧节点指针(opens new window)
题目:给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
解题思路:
代码:

class Solution {
    public Node connect(Node root) {
		Queue<Node> que = new LinkedList<Node>();
		if(root!=null){
			que.add(root);
		}
		while(que.size() != 0){
			int len = que.size();
			Node  node = que.poll();
			if(node.left!=null)que.add(node.left);
			if(node.right!=null)que.add(node.right);
			while(len>1){
				Node  next = que.poll();
				if(next.left!=null)que.offer(next.left);
				if(next.right!=null)que.offer(next.right);
				node.next = next;
				node = next;
				len--;
			}
		}
		return root;
    }
}

117.填充每个节点的下一个右侧节点指针II(opens new window)
题目:这道题目说是二叉树,但116题目说是完整二叉树,其实没有任何差别,一样的代码一样的逻辑一样的味道
解题思路:
代码:

class Solution {
    public Node connect(Node root) {
		Queue<Node> que = new LinkedList<Node>();
		if(root!=null){
			que.add(root);
		}
		while(que.size() != 0){
			int len = que.size();
			Node  node = que.poll();
			if(node.left!=null)que.add(node.left);
			if(node.right!=null)que.add(node.right);
			while(len>1){
				Node  next = que.poll();
				if(next.left!=null)que.offer(next.left);
				if(next.right!=null)que.offer(next.right);
				node.next = next;
				node = next;
				len--;
			}
		}
		return root;
    }
}

104.二叉树的最大深度(opens new window)
题目:
给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。
解题思路:
代码:

class Solution {
    public int maxDepth(TreeNode root) {
		int result = 0;
		Queue<TreeNode> que = new LinkedList<TreeNode>();
		if(root==null){
			return result;
		}
		que.offer(root);
		while(!que.isEmpty()){
			int len = que.size();
			TreeNode node = null;
			while(len>0){
				node = que.poll();
				if(node.left!=null)que.offer(node.left);
				if(node.right!=null)que.offer(node.right);
				len--;
			}
			result++;
		}
		return result;
    }
}

111.二叉树的最小深度
题目:相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。

需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点
解题思路:
代码:

class Solution {
    public int minDepth(TreeNode root) {
		int result = 0;
		Queue<TreeNode> que = new LinkedList<TreeNode>();
		if(root==null){
			return result;
		}
		que.offer(root);
		while(!que.isEmpty()){
			int len = que.size();
			TreeNode node = null;
			result++;
			while(len>0){
				node = que.poll();
				if(node.left!=null)que.offer(node.left);
				if(node.right!=null)que.offer(node.right);
				if(node.left==null && node.right==null)return result;
				len--;
			}
		}
		return result;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值