二叉树的遍历

二叉树节点定义

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;
}
}

LeeCode 144: 二叉树的前序遍历

题目描述

给你一棵二叉树的根节点 root ,返回其节点值的前序遍历

Java代码实现

递归实现
public List<Integer> preorderRecursive(TreeNode root) {
List<Integer> res = new ArrayList<>();
preorderRecursiveImpl(root, res);
return res;
} public void preorderRecursiveImpl(TreeNode root, List<Integer> res) {
if (root == null) {
return;
} res.add(root.val);
preorderRecursiveImpl(root.left, res);
preorderRecursiveImpl(root.right, res);
return;
}
迭代实现

递归实现本质上是维护了一个隐藏的栈结构,而在迭代时需要手动维护。

public List<Integer> preorderIterative(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
} Stack<TreeNode> stack = new Stack<>();
/**
* 添加顺序: 根 -> 左 -> 右
*/
while (root != null || !stack.isEmpty()) {
while (root != null) {
res.add(root.val);
stack.push(root);
root = root.left;
} root = stack.pop();
root = root.right;
} return res;
}
Morris 实现
public List<Integer> preorderMorris(TreeNode root) {
List<Integer> res = new ArrayList<>();
TreeNode cur = root;
TreeNode prev = null; while (cur != null) {
// 当前节点没有左子节点,则直接访问当前节点,并将指针指向右子节点
if (cur.left == null) {
res.add(cur.val);
cur = cur.right; // 通过 cur.right 返回父节点
continue;
} prev = cur.left; // 寻找当前节点左子节点的最右子结点
while (prev.right != null && prev.right != cur) {
prev = prev.right;
} if (prev.right == null) {
prev.right = cur;
res.add(cur.val); // 前序访问根节点
cur = cur.left;
}
else {
prev.right = null;
cur = cur.right;
}
} return res;
}

LeeCode 94: 二叉树的中序遍历

题目描述

给你一棵二叉树的根节点 root,返回其节点值的中序遍历

Java代码实现

递归实现
public List<Integer> inorderRecursive(TreeNode root) {
List<Integer> res = new ArrayList<>();
inorderRecursiveImpl(root, res);
return res;
} public void inorderRecursiveImpl(TreeNode root, List<Integer> res) {
if (root == null) {
return;
} inorderRecursiveImpl(root.left, res);
res.add(root.val);
inorderRecursiveImpl(root.right, res);
return;
}
迭代实现
public List<Integer> inorderIterative(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
} Stack<TreeNode> stack = new Stack<>();
/**
* 添加顺序: 左 -> 根 -> 右
*/
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
} root = stack.pop();
res.add(root.val);
root = root.right;
} return res;
}
Morris 实现

Morris实现的核心想法是找到当前节点的左子节点的最右子结点,即当前节点中序遍历的前一个节点。

public List<Integer> inorderMorris(TreeNode root) {
List<Integer> res = new ArrayList<>();
TreeNode cur = root;
TreeNode prev = null; while (cur != null) {
// 当前节点没有左子节点,则直接访问该节点,然后将指针指向右子结点
if (cur.left == null) {
res.add(cur.val);
cur = cur.right; // 通过 cur.right 返回父节点
continue;
} prev = cur.left; // 寻找当前节点左子节点的最右子结点,即中序遍历中当前节点的前一个节点
while (prev.right != null && prev.right != cur) {
prev = prev.right;
} if (prev.right == null) {
prev.right = cur;
cur = cur.left;
}
else {
prev.right = null;
res.add(cur.val); // 中序访问根节点
cur = cur.right;
}
} return res;
}

LeeCode 145: 二叉树的后序遍历

题目描述

给你一棵二叉树的根节点 root,返回其节点值的后序遍历

Java代码实现

递归实现
public List<Integer> postorderRecursive(TreeNode root) {
List<Integer> res = new ArrayList<>();
postorderRecursiveImpl(root, res);
return res;
} public void postorderRecursiveImpl(TreeNode root, List<Integer> res) {
if (root == null) {
return;
} postorderRecursiveImpl(root.left, res);
postorderRecursiveImpl(root.right, res);
res.add(root.val);
return;
}
迭代实现
public List<Integer> postorderIterative(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
} Stack<TreeNode> stack = new Stack<>();
TreeNode previous = null;
/**
* 添加顺序: 左 -> 右 -> 根
*/
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
} root = stack.pop();
// 若右子树为空 或 右子树已经访问过,则添加根节点值
if (root.right == null || root.right == previous) {
res.add(root.val);
previous = root;
root = null;
}
else {
stack.push(root);
root = root.right;
}
} return res;
}

LeeCode 102: 二叉树的层序遍历

题目描述

给你一棵二叉树的根节点 root,返回其节点值的层序遍历。(即逐层地从左到右访问所有节点)。

建立模型

  1. 这是一个广度优先搜索的问题,先遍历顶层所有节点,再往下遍历
  2. 使用一个队列来维护遍历的节点
  3. 使用变量size记录当前层节点个数

代码实现

public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) {
return res;
} // 使用基于双向链表实现的队列维护
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root); // 添加到队尾 while (!deque.isEmpty()) {
int size = deque.size();
List<Integer> temp = new ArrayList<>(); for (int i = 0; i < size; i++) {
TreeNode node = deque.poll(); // 从队首取出
temp.add(node.val); if (node.left != null) {
deque.offer(node.left);
} if (node.right != null) {
deque.offer(node.right);
}
} res.add(new ArrayList<>(temp));
} return res;
}

LeeCode 二叉树问题(一)的更多相关文章

  1. leecode刷题(30)-- 二叉树的后序遍历

    leecode刷题(30)-- 二叉树的后序遍历 二叉树的后序遍历 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 思路 ...

  2. leecode刷题(29)-- 二叉树的中序遍历

    leecode刷题(29)-- 二叉树的中序遍历 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 思路 跟 ...

  3. leecode刷题(28)-- 二叉树的前序遍历

    leecode刷题(28)-- 二叉树的前序遍历 二叉树的前序遍历 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 思路 ...

  4. leecode刷题(24)-- 翻转二叉树

    leecode刷题(24)-- 翻转二叉树 翻转二叉树 翻转一棵二叉树. 示例: 输入: 4 / \ 2 7 / \ / \ 1 3 6 9 输出: 4 / \ 7 2 / \ / \ 9 6 3 1 ...

  5. Leecode刷题之旅-C语言/python-111二叉树的最小深度

    /* * @lc app=leetcode.cn id=111 lang=c * * [111] 二叉树的最小深度 * * https://leetcode-cn.com/problems/minim ...

  6. Leecode刷题之旅-C语言/python-104二叉树最大深度

    /* * @lc app=leetcode.cn id=104 lang=c * * [104] 二叉树的最大深度 * * https://leetcode-cn.com/problems/maxim ...

  7. Leecode刷题之旅-C语言/python-101对称二叉树

    /* * @lc app=leetcode.cn id=101 lang=c * * [101] 对称二叉树 * * https://leetcode-cn.com/problems/symmetri ...

  8. 路径和 二叉树 leecode

    题目不难,很快ac,纯粹靠手感.https://oj.leetcode.com/problems/sum-root-to-leaf-numbers/ /** * Definition for bina ...

  9. leecode第二百三十六题(二叉树的最近公共祖先)

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...

  10. leecode第一百二十四题(二叉树中的最大路径和)

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...

随机推荐

  1. JS笔记(三):函数与对象

    镇楼图 Pixiv:torino 四.Function类型 Rest语法 一些函数如Math.max可以支持任意数量的参数,JS中对于这样的参数可以简单使用...来实现,使用剩余参数,它支持收集剩余的 ...

  2. python3GUI--在线小说播放器By:PyQt5(附ui源码)

    目录 一.准备工作 1.PyQt5 2.qtawesome 3.QMediaPlayer 4.LAVFilters 二.预览 1.启动 2.查看小说详情&播放小说 3.搜索后播放 4.动态演示 ...

  3. java不返回某些字段,包括 null

    一.使用 fastjson 包. (1) SimplePropertyPreFilter 可以将需要的字段留下来. import com.alibaba.fastjson.JSON;import co ...

  4. jquery的ajax方法获取不到return返回值

    /** 2 * 方式:(1)同步调用 (2)在ajax函数中return值 3 * 结果:返回 1.未成功获取返回值 4 * 失败原因:ajax内部是一个或多个定义的函数,ajax中return返回值 ...

  5. Selenium显式、隐式等待

    显式等待: 显式等待是你在代码中定义等待一定条件发生后再进一步执行你的代码.简单的说就是在指定时间内,一直等待某个条件成立,条件成立后立即执行定位元素的操作:如果超过这个时间条件仍然没有成立,则会抛出 ...

  6. 试题管理/在线课程/模拟考试/能力评估报告/艾思在线考试系统www.aisisoft.cn

    艾思软件发布在线考试系统, 可独立部署, 欢迎咨询索要测试账号 一. 主要特点: ThinkPHP前后端分离框式开发 主要功能有: 在线视频课程, 模拟考试, 在线考试, 能力评估报告, 考试历史错题 ...

  7. 2.3Dmax界面_视图调整

    一.试图模型显示效果的切换 '默认是真实显示效果' 线框模式 快捷键F3 ----> 真实显示效果和线框显示效果的切换(切换到线框显示效果再按F3就切换到了真实显示效果). 线面模式 快捷键F4 ...

  8. 将后端的application/json的格式数据类型转换成前端需要的类型格式

    前提:后端返回的数据内容 但是红框的数据对于前端来说是不正确的数据 所以我感觉前端处理这个数据本身这个操作都很傻X 但是我尝试进行转换代码如下: 得到的数据: 点击查看代码 const interfa ...

  9. mysql创建函数时提示1418。可选关闭二进制日志或者设置log_bin_trust_function_creators=1

    报错详情如下:1418--This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration a ...

  10. Leecode 160.相交链表(Java 哈希表、双指针 两种方法)

    找两个链表第一次指针相同的地方     想法:(本来是没有的,因为没读懂题目描述= =) 1.两个指针,长的先走(长减短相差的长度)这么多的步数,然后就可以开始比较指针,直到指向为空,期间如果指针相同 ...