144前序遍历

思路:(循环前入栈、先右节点入栈)

  • 建栈,入栈,循环,只要栈不为空

    • 出栈,把值加入res。
    • 如果右不为空,入栈。左一样。
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
} Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode curNode = stack.pop();
res.add(curNode.val);
// 下面用于非递归的反转二叉树
// TreeNode tempNode = node.left;
// node.left = node.right;
// node.right = tempNode; if (curNode.right != null) {
stack.push(curNode.right);
}
if (curNode.left != null) {
stack.push(curNode.left);
}
}
return res;

94中序遍历(98验证二叉搜索树、230二叉搜索树中第K小的元素)

思路:

  • 建栈、cur指针,不入栈循环,只要cur和栈不为空

    • 只要cur不为空,循环让左子节点入栈,cur做相应移动
    • 出栈,把值加入res。
    • cur移动到右节点
// 设置计数器(二叉搜索树中第K小的元素)
// int cnt = 0; List<Integer> res = new ArrayList<>(); if (root == null) {
return res;
} Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) { // 先把左子节点都入栈
/** 注意是cur != null,而不是cur.left != null */
while (cur != null) {
stack.push(cur);
cur = cur.left;
} cur = stack.pop();
// (二叉搜索树中第K小的元素)
// cnt++;
// if (cnt == k) return cur.val; // (验证二叉搜索树)
// if (pre != null && cur.val <= pre.val) return false;
// pre = cur;
res.add(cur.val);
cur = cur.right;
}
return res;

145后序遍历

思路:

  • 建栈、cur和pre指针
  • pop依然在中间,但add前要判断是否还有右节点或者之前就是右节点,否则把cur放回去,指向它的右节点。add后pre成为cur,cur变为null
Stack<TreeNode> stack = new Stack<>();
TreeNode pre = null;
TreeNode cur = root; while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
} cur = stack.pop();
if (cur.right == null || pre == cur.right) {
res.add(cur.val);
pre = cur;
cur = null;
} else {
stack.push(cur);
cur = cur.right;
}
}

102/107层次遍历(104二叉树最大深度、103

二叉树的锯齿形层次遍历)

思路:

  • 新建queue,入列
  • 循环,只要q不为空
    • 新建level链表,记录本层元素的个数
    • 遍历此层
      • 出列,加入res。
      • 如果左节点不为空,入列。右节点一样。
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root); while (!queue.isEmpty()) {
// 下面用于 maxDepth
// res++; List<Integer> level = new ArrayList<>();
// 注意,由于循环中对queue进行修改,其size不断变化,所以这个值不能直接放到循环条件中
int length = queue.size(); // 下面用于 zigzagLevelOrder
// boolean flag = result.size() % 2 == 0; for (int i = 0; i < length; i++) { // 遍历一层的node
TreeNode node = queue.poll();
level.add(node.val); // 下面用于 zigzagLevelOrder
// if (flag) level.add(node.val);
// else level.add(0, node.val); if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
// levelOrderBottom就 add(0, level)
// 不断往0插入数据,旧数据就被挤到后面了
result.add(level);

105从前序与中序遍历序列构造二叉树

思路:

  • 新建preStart, preEnd, inStart, inEnd四个变量
  • 调用递归函数
    • 当“前序”或者“中序”中其中一个结束,就返回null
    • 取出pre中的preStart元素,新建节点,然后在中序数组中找出该节点的index。根据这个index来划分左右子树对应“前序”和“中序”的边界
// construct函数
if (preStart > preEnd || inStart > inEnd) {
return null;
} int val = preorder[preStart];
TreeNode p = new TreeNode(val); int k = 0;
for (int i = 0; i < inorder.length; i++) {
if (val == inorder[i]) {
k = i;
break;
}
} // 注意要减去inStart
p.left = construct(preorder, preStart + 1, preStart + (k - inStart),
inorder, inStart, k - 1);
p.right = construct(preorder, preStart + (k - inStart) + 1, preEnd,
inorder, k + 1, inEnd); return p;

114二叉树展开为链表

	1
/ \
2 5
/ \ \
3 4 6 1
\
2
\
3
\
4
\
5
\
6

只能说,从上面的观察结果来看,可以先处理右节点,再到左节点的顺序。

private TreeNode preNode = null;

public void flatten(TreeNode root) {
if (root == null) {
return;
}
flatten(root.right);
flatten(root.left);
root.right = preNode;
root.left = null;
preNode = root;
}

124二叉树中的最大路径和

思路:递归

  • 对左右节点递归调用函数,当节点为null时,返回0。如果返回的结果比0还小,可以不选该节点,所以以left为例,赋值为返回值及0中的最大值。
  • 返回左右节点值后,判断res是否需要更新,比较值是左右即当前节点值的和。
  • 最后只能返回一条路近的值,即从左到当前节点还是从右到当前节点的和。

235/236二叉树的最近公共祖先

236思路:

target是p和q的最近公共父节点,它有两种情况

要么p和q都不是target,要么p或q为target

第一种情况:p和q会分布在target的左右两边,所以左右返回的都不是null,返回当前即可

第二种情况:左右其中一个返回null,一个非null,直接返回非null即可

递归寻找,root绝对会等于null或者p、q中的一个

if (root == null || root == p || root == q) return root;

TreeNode left = lowestCommonAncestor1(root.left, p, q);
// 下面优化,说明左节点是一个非p或q的公共节点
// if (left != null && left != p && left != q) return left;
TreeNode right = lowestCommonAncestor1(root.right, p, q); if (left != null && right != null) return root; return left == null ? right : left;

235思路:

如果当前节点的值大于两个参数节点,说明它们的公共父节点在左边,反之。只有当当前节点的值处于两个值之间,当前节点才是公共父节点。

if (root.val > p.val && root.val > q.val) {
return lowestCommonAncestor2(root.left, p, q);
} else if (root.val < p.val && root.val < q.val) {
return lowestCommonAncestor2(root.right, p, q);
} else {
return root;
}

leetcode树相关的更多相关文章

  1. leetcode tree相关题目总结

    leetcode tree相关题目小结 所使用的方法不外乎递归,DFS,BFS. 1. 题100 Same Tree Given two binary trees, write a function ...

  2. 树 相关知识总结以及Java实现

    最近在温习树相关的知识,并且用java实现了一下树的遍历相关,先贴上代码供大家参考吧. package tree_problems; import java.util.ArrayDeque; impo ...

  3. [LeetCode] [链表] 相关题目总结

    刷完了LeetCode链表相关的经典题目,总结一下用到的技巧: 技巧 哑节点--哑节点可以将很多特殊case(比如:NULL或者单节点问题)转化为一般case进行统一处理,这样代码实现更加简洁,优雅 ...

  4. LeetCode树专题

    LeetCode树专题 98. 验证二叉搜索树 二叉搜索树,每个结点的值都有一个范围 /** * Definition for a binary tree node. * struct TreeNod ...

  5. [leetcode] 根据String数组构造TreeNode,用于LeetCode树结构相关的测试用例

    LeetCode 跟树结构相关的题目的测试用例中大多是通过String数组来构造树.例如{2,#,3,#,4,#,5,#,6},可以构造出如下的树(将树结构逆时针选择90度显示): 6         ...

  6. leetcode 树类型题

    树的测试框架: // leetcodeTree.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream& ...

  7. leetcode: 树

    1. sum-root-to-leaf-numbers Given a binary tree containing digits from0-9only, each root-to-leaf pat ...

  8. leetcode String相关

    目录 3无重复字符的最长子串 5最长回文子串 8字符串转换整数(atoi), 9回文数,7整数反转 28实现strStr(), 459重复的子字符串(KMP) 43字符串相乘 71简化路径 93复原I ...

  9. Trie树相关博客

    1. c++代码实现,包含删除操作:https://www.cnblogs.com/luxiaoxun/archive/2012/09/03/2668611.html 2. 一种典型实现及简单分析:h ...

随机推荐

  1. js分页插件

    //分页插件1function showView(option) {    //参数定义id,页容量,当前页,总数,页总数    var id = option.id,         pageSiz ...

  2. 用nginx实现分布式限流

    1.前言 一般对外暴露的系统,在促销或者黑客攻击时会涌来大量的请求,为了保护系统不被瞬间到来的高并发流量给打垮, 就需要限流 . 本文主要阐述如何用nginx 来实现限流. 听说 Hystrix 也可 ...

  3. C# 定时无操作则退出登陆,回到登陆界面。

    有时候根据需求需要为程序添加在规定的时间内无操作则退出当前的登陆程序的功能,如下代码模拟描述的需求功能. using System; using System.Collections.Generic; ...

  4. C# 打开模态对话框 和打开文件夹

    C# 打开另一个窗体,(模态对话框) Form1 frm= new Form1(); //创建对象 DialogResult retServer = frm.ShowDialog(); //模式对话框 ...

  5. 【转】下载对应内核版本的asmlib

    登陆oracle官网: http://www.oracle.com/ 注意:查询前,需要注册一个OTN账号,注册是免费的. 首页直接搜索“ASMLib”关键词(注意大小写) 进入搜索界面,点击第一项即 ...

  6. 11.11如何卖到一个亿:从0到1的电商爆品打造术 电子书 PDF

    内容转自:https://download.csdn.net/download/chenyao1994/11191034 下载地址:https://pan.baidu.com/s/1uQ1cjm9QH ...

  7. Python学习【第5篇】:Python之函数(自定义函数,内置函数,装饰器,迭代器,生成器、模块)

    一.为什么要使用函数? 1.避免代码重用 2.提高代码的可读性 二.函数的定义与调用 1. def  函数名(参数1,参数2): ''' 函数注释''' print('函数体') return 返回值 ...

  8. HDU 3401 Trade

    Trade Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 3401 ...

  9. OpenCV 基于超像素分割的图像区域选取方法及源码

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51386993 工程源码GitHub: ...

  10. hdu 4862KM&最小费用最大流

    /*最小K路径覆盖的模型,用费用流或者KM算法解决, 构造二部图,X部有N*M个节点,源点向X部每个节点连一条边, 流量1,费用0,Y部有N*M个节点,每个节点向汇点连一条边,流量1, 费用0,如果X ...