LeeCode 二叉树问题(一)
二叉树的遍历
二叉树节点定义
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,返回其节点值的层序遍历。(即逐层地从左到右访问所有节点)。
建立模型
- 这是一个广度优先搜索的问题,先遍历顶层所有节点,再往下遍历
- 使用一个队列来维护遍历的节点
- 使用变量
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 二叉树问题(一)的更多相关文章
- leecode刷题(30)-- 二叉树的后序遍历
leecode刷题(30)-- 二叉树的后序遍历 二叉树的后序遍历 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 思路 ...
- leecode刷题(29)-- 二叉树的中序遍历
leecode刷题(29)-- 二叉树的中序遍历 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 思路 跟 ...
- leecode刷题(28)-- 二叉树的前序遍历
leecode刷题(28)-- 二叉树的前序遍历 二叉树的前序遍历 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 思路 ...
- leecode刷题(24)-- 翻转二叉树
leecode刷题(24)-- 翻转二叉树 翻转二叉树 翻转一棵二叉树. 示例: 输入: 4 / \ 2 7 / \ / \ 1 3 6 9 输出: 4 / \ 7 2 / \ / \ 9 6 3 1 ...
- Leecode刷题之旅-C语言/python-111二叉树的最小深度
/* * @lc app=leetcode.cn id=111 lang=c * * [111] 二叉树的最小深度 * * https://leetcode-cn.com/problems/minim ...
- Leecode刷题之旅-C语言/python-104二叉树最大深度
/* * @lc app=leetcode.cn id=104 lang=c * * [104] 二叉树的最大深度 * * https://leetcode-cn.com/problems/maxim ...
- Leecode刷题之旅-C语言/python-101对称二叉树
/* * @lc app=leetcode.cn id=101 lang=c * * [101] 对称二叉树 * * https://leetcode-cn.com/problems/symmetri ...
- 路径和 二叉树 leecode
题目不难,很快ac,纯粹靠手感.https://oj.leetcode.com/problems/sum-root-to-leaf-numbers/ /** * Definition for bina ...
- leecode第二百三十六题(二叉树的最近公共祖先)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...
- leecode第一百二十四题(二叉树中的最大路径和)
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...
随机推荐
- Vuex----Getters
Getter 用于对 Store中的数据进行加工处理形成新的数据. Getter 不会修改 Store 中的原数据,它只起到一个包装器的作用,将Store中的数据加工后输出出来. const stor ...
- sar与ksar使用显示监控数据
一.Ksar: 1)下载ksar地址:https://github.com/vlsi/ksar/releases/tag/v5.2.4-snapshot.10-gf068072 2)启动:java - ...
- 微信小程序 css overflow :hidden 子元素不生效
原css .item .right { width: 70%; } .item .right .name { font-size: 32rpx; font-family ...
- 3vue
阻止冒泡 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
- 安卓手机qpython使用感觉
我是写C#的,最佳一时兴起,下载了个qpython来玩儿,发现这东西写点简单的爬虫还行,配合sqlite,可以做一些简单的事情,于是乎想写一个有趣的东西,在qpython写一个脚本,去收蚂蚁森林的能量 ...
- Delphi数据库备份
此处代码只是测试代码,仅仅是测试 //环境:D7+SQL Server 2008 1 unit Unit1; 2 3 interface 4 5 uses 6 Windows, Messages, S ...
- Docker不启动容器的情况下修改配置文件
应用场景: 1.容器中配置文件错误无法启动. 2.任何不启动容器时修改配置文件. 方法: 1.Copy容器中的配置文件出来. 2.修改此配置文件 3.将配置文件重新覆盖回容器内 命令 docker c ...
- EF 操作实例
一.Linq语法 List操作 1.1 有参 public List<GoodsInfo> ShowInfo(string GName,int?Gid) { //true ...
- 转发:All in one:项目级 monorepo 策略最佳实践
0. 前言 在最近的项目开发中,出现了一个令我困扰的状况.我正在开发的项目 A,依赖了已经线上发布的项目 B,但是随着项目 A 的不断开发,又需要不时修改项目 B 的代码(这些修改暂时不必发布线上), ...
- 一分钟教你分清各种光纤跳线接头(SC、ST、FC、LC、MPO)
一分钟教你分清各种光纤跳线接头(SC.ST.FC.LC.MPO) 市场上常见的光纤跳线有以下几种接头:SC.ST.FC.LC.MPO,相信很多入门者和小编一样,面对各种英文缩写也是我只认识他们,却不 ...