刷LeetCode二叉树题目,简单明了,保证一看就懂的代码。
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。递归实现【左->根->右】
import java.util.*;
/**
* 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> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
inorder(root, res);
return res;
}
// 递归实现中序遍历
public void inorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
inorder(root.left, res);
res.add(root.val);
inorder(root.right, res);
}
}
104. 二叉树的最大深度【递归实现】
给定一个二叉树 root
,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:3
示例 2:
输入:root = [1,null,2] 输出:2
提示:
- 树中节点的数量在
[0, 104]
区间内。 -100 <= Node.val <= 100
/**
* 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 int maxDepth(TreeNode root) {
if (root == null) {
return 0;
// 递归计算二叉树的高度
} else {
int leftHeight = maxDepth(root.left);
int rightHeight = maxDepth(root.right);
// 最大高度即为最大深度
return Math.max(leftHeight, rightHeight) + 1;
}
}
}
简化版写法:
public int maxDepth(TreeNode root) {
if (root == null)
return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
public static int minDepth(TreeNode root) {
if (root == null)
return 0;
//如果左子树等于空,我们返回右子树的最小高度+1
if (root.left == null)
return minDepth(root.right) + 1;
//如果右子树等于空,我们返回左子树的最小高度+1
if (root.right == null)
return minDepth(root.left) + 1;
//如果左右子树都不为空,我们返回左右子树深度最小的那个+1
return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
}
226. 翻转二叉树【递归算法,根->左->右】
/**
* 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 TreeNode invertTree(TreeNode root) {
if(Objects.isNull(root)){
return null;
}
TreeNode tmp=root.right;
root.right=root.left;
root.left=tmp;
// 递归最子树节点
invertTree(root.left);
invertTree(root.right);
return root;
}
}
101. 对称二叉树 【递归的前序遍历】
**
* 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 boolean isSymmetric(TreeNode root) {
return check(root, root);
}
// 二叉树的前序遍历实现
public boolean check(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
}
if (p == null || q == null) {
return false;
}
return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
}
}
543. 二叉树的直径【递归的前序遍历】
/**
* 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 {
int maxd=0;
public int diameterOfBinaryTree(TreeNode root) {
depth(root);
return maxd;
}
public int depth(TreeNode node){
if(node==null){
return 0;
}
int Left = depth(node.left);
int Right = depth(node.right);
// 将每个节点最大直径(左子树深度+右子树深度)当前最大值比较并取大者
maxd=Math.max(Left+Right,maxd);
// 所以求直径(即求路径长度的最大值)等效于求路径经过节点数的最大值减,已该节点为起点的加一
return Math.max(Left,Right)+1;
}
}
import java.util.*;
/**
* 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<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ret = new ArrayList<List<Integer>>();
if (root == null) {
return ret;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> level = new ArrayList<Integer>();
int currentLevelSize = queue.size();
for (int i = 1; i <= currentLevelSize; ++i) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
ret.add(level);
}
return ret;
}
}
108. 将有序数组转换为二叉搜索树【递归的前序实现】
/**
* 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 TreeNode sortedArrayToBST(int[] nums) {
return helper(nums, 0, nums.length - 1);
}
public TreeNode helper(int[] nums, int left, int right) {
if (left > right) {
return null;
}
// 总是选择中间位置左边的数字作为根节点,二叉搜索树特点:根节点大于左节点,小于右节点,那么类似二叉搜索树的中序遍历
int mid = left+(right-left)/2;
TreeNode root = new TreeNode(nums[mid]);
// 递归实现
root.left = helper(nums, left, mid - 1);
root.right = helper(nums, mid + 1, right);
return root;
}
}
/**
* 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 boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
// 是二叉搜索树,那么子树也要是二叉搜索树
public boolean isValidBST(TreeNode node, long lower, long upper) {
if (node == null) {
return true;
}
if (node.val <= lower || node.val >= upper) {
return false;
}
return isValidBST(node.left, lower, node.val) && isValidBST(node.right, node.val, upper);
}
}
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
示例 1:
输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]
示例 2:
输入:root = [2,1,3] 输出:[2,3,1]
示例 3:
输入:root = [] 输出:[] 提示:
- 树中节点数目范围在
[0, 100]
内 -100 <= Node.val <= 10
递归的前序遍历实现.
public TreeNode invertTree(TreeNode root) {
//递归的边界条件判断
if (root == null)
return null;
//先交换子节点
TreeNode left = root.left;
root.left = root.right;
root.right = left;
//递归调用
invertTree(root.left);
invertTree(root.right);
return root;
}
BFS遍历,层序交换两个节点.
public TreeNode invertTree(TreeNode root) {
if (root == null)
return root;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);//相当于把数据加入到队列尾部
while (!queue.isEmpty()) {
//poll方法相当于移除队列头部的元素
TreeNode node = queue.poll();
//先交换子节点
TreeNode left = node.left;
node.left = node.right;
node.right = left;
if (node.left != null)
queue.add(node.left);
if (node.right != null)
queue.add(node.right);
}
给你两棵二叉树: root1
和 root2
。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
示例 1:
输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7] 输出:[3,4,5,5,4,null,7]
示例 2:
输入:root1 = [1], root2 = [1,2] 输出:[2,2]
提示:
- 两棵树中的节点数目在范围
[0, 2000]
内 -104 <= Node.val <= 104
/**
* 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 TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1==null){
return root2;
}
if(root2==null){
return root1;
}
// 前序遍历实现
root1.val+=root2.val;
root1.left=mergeTrees(root1.left,root2.left);
root1.right=mergeTrees(root1.right,root2.right);
return root1;
}
}
给定二叉搜索树(BST)的根节点 root
和一个整数值 val
。
你需要在 BST 中找到节点值等于 val
的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null
。
示例 1:
输入:root = [4,2,7,1,3], val = 2 输出:[2,1,3]
示例 2:
输入:root = [4,2,7,1,3], val = 5 输出:[]
提示:
- 树中节点数在
[1, 5000]
范围内 1 <= Node.val <= 107
root
是二叉搜索树1 <= val <= 107
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
/**
二叉搜索树是一个有序树
若它的左子树不空,则左子树上的所有节点的值均小于它的根节点的值
若它的右子数不空,则右子数上所有节点的值均大于它 的根节点的值
它的左右字数也分别是二叉搜索树
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if(root==null||root.val==val){
return root;
}
// 二叉树搜索树的定义,如果根节点大于搜索值,如果根节点小于搜索值
if(root.val>val){
return searchBST(root.left,val);
}else{
return searchBST(root.right,val);
}
}
}
965. 单值二叉树 【递归的前序遍历】
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true
;否则返回 false
。
示例 1:
输入:[1,1,1,1,1,null,1] 输出:true
示例 2:
输入:[2,2,2,5,2] 输出:false
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
// 解题思路如下:
// 1、首先判断根节点
// 2、依次和根节点的左右子节点对比,不为null,并且不相等
// 3、然后依次递归根节点的左右子节点
class Solution {
public boolean isUnivalTree(TreeNode root) {
if(root==null){
return true;
}
if(root.left!=null&&root.val!=root.left.val){
return false;
}
if(root.right!=null&&root.val!=root.right.val){
return false;
}
return (isUnivalTree(root.left)&&(isUnivalTree(root.right)));
}
}
给定一个二叉树,判断它是否是
平衡二叉树
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:true
示例 2:
输入:root = [1,2,2,3,3,null,null,4,4] 输出:false
示例 3:
输入:root = [] 输出:true
提示:
- 树中的节点数在范围
[0, 5000]
内 -104 <= Node.val <= 104
public boolean isBalanced(TreeNode root) {
if (root == null)
return true;
//分别计算左子树和右子树的高度
int left = depth(root.left);
int right = depth(root.right);
//这两个子树的高度不能超过1
return Math.abs(left - right) <= 1;
}
//计算树中节点的高度
public int depth(TreeNode root) {
if (root == null)
return 0;
return Math.max(depth(root.left), depth(root.right)) + 1;
}
给定一个 N 叉树,找到其最大深度。
最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。
示例 1:
输入:root = [1,null,3,2,4,null,5,6] 输出:3
示例 2:
输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14] 输出:5
提示:
- 树的深度不会超过
1000
。 - 树的节点数目位于
[0, 104]
之间。
DFS的遍历
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public int maxDepth(Node root) {
if(root==null){
return 0;
}
// 计算N叉数的节点,然后DFS计算.
int size=root.children.size();
int max=0;
for(int i=0;i<size;i++){
max=Math.max(max,maxDepth(root.children.get(i)));
}
return max+1;
}
}
BFS的实现
public int maxDepth(Node root) {
if (root == null)
return 0;
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while (!queue.isEmpty()) {
//到下一层了,深度要加1
depth++;
//levelCount是当前层的节点数,
int levelCount = queue.size();
for (int i = 0; i < levelCount; i++) {
//当前层的每一个节点都要出队,然后再
//把他们的子节点加入到队列中
Node current = queue.poll();
for (Node child : current.children)
queue.offer(child);
}
}
return depth;
}
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
import java.util.*;
/**
* 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<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ret = new ArrayList<List<Integer>>();
if (root == null) {
return ret;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> level = new ArrayList<Integer>();
int currentLevelSize = queue.size();
for (int i = 1; i <= currentLevelSize; ++i) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
ret.add(level);
}
return ret;
}
}
控制台打印的实现方式
public static void levelOrder(TreeNode tree) {
if (tree == null)
return;
//链表,这里我们可以把它看做队列
LinkedList<TreeNode> list = new LinkedList<>();
//相当于把数据加入到队列尾部
list.add(tree);
while (!list.isEmpty()) {
//poll方法相当于移除队列头部的元素
TreeNode node = list.poll();
System.out.println(node.val);
if (node.left != null)
list.add(node.left);
if (node.right != null)
list.add(node.right);
}
}
给定一个非空二叉树的根节点 root
, 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5
以内的答案可以被接受。
/**
* 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<Double> averageOfLevels(TreeNode root) {
List<Double> averages = new ArrayList<Double>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while(!queue.isEmpty()){
// 每一层的定义,sum=0.
double sum=0;
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode node=queue.poll();
sum+=node.val;
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
averages.add(sum/size);
}
return averages;
}
}
给定一棵二叉树的根节点 root
,请找出该二叉树中每一层的最大值。
示例1:
输入: root = [1,3,2,5,3,null,9] 输出: [1,3,9]
示例2:
输入: root = [1,2,3] 输出: [1,3]
提示:
- 二叉树的节点个数的范围是
[0,104]
-231 <= Node.val <= 231 -
BFS遍历每层比较最大值,然后放入List中返回即可.
/**
* 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> largestValues(TreeNode root) {
if(root==null){
return new ArrayList<>();
}
Queue<TreeNode> queue = new LinkedList<>();
List<Integer> list=new ArrayList<Integer>();
queue.offer(root);
while(!queue.isEmpty()){
int maxValue=Integer.MIN_VALUE;
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode node= queue.poll();
maxValue=Math.max(maxValue,node.val);
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
list.add(maxValue);
}
return list;
}
}
中序遍历,总是选择中间位置左边的数字作为根节点
/**
* 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 TreeNode sortedArrayToBST(int[] nums) {
return helper(nums, 0, nums.length - 1);
}
public TreeNode helper(int[] nums, int left, int right) {
if (left > right) {
return null;
}
// 总是选择中间位置左边的数字作为根节点,二叉搜索树特点:根节点大于左节点,小于右节点,那么类似二叉搜索树的中序遍历
int mid = left+(right-left)/2;
TreeNode root = new TreeNode(nums[mid]);
// 递归实现
root.left = helper(nums, left, mid - 1);
root.right = helper(nums, mid + 1, right);
return root;
}
}
给你一个二叉树的根节点 root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3,null,5] 输出:["1->2->5","1->3"]
示例 2:
输入:root = [1] 输出:["1"]
提示:
- 树中节点的数目在范围
[1, 100]
内 -100 <= Node.val <= 100
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 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<String> binaryTreePaths(TreeNode root) {
List<String> pathList=new ArrayList<>();
getPath(root,"",pathList);
return pathList;
}
private void getPath(TreeNode root,String path,List<String> result){
if(Objects.isNull(root)){
return;
}
// 处理根节点
if(Objects.isNull(root.left)&&Objects.isNull(root.right)){
result.add(path+root.val);
return;
}
// 递归处理各个节点
getPath(root.left, path+root.val+"->", result);
getPath(root.right, path+root.val+"->", result);
}
}
BFS遍历,每层路径记录在List中.
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<>();
if (root == null)
return res;
//队列,节点和路径成对出现,路径就是从根节点到当前节点的路径
Queue<Object> queue = new LinkedList<>();
queue.add(root);
queue.add(root.val + "");
while (!queue.isEmpty()) {
TreeNode node = (TreeNode) queue.poll();
String path = (String) queue.poll();
//如果到叶子节点,说明找到了一条完整路径
if (node.left == null && node.right == null) {
res.add(path);
}
//右子节点不为空就把右子节点和路径存放到队列中
if (node.right != null) {
queue.add(node.right);
queue.add(path + "->" + node.right.val);
}
//左子节点不为空就把左子节点和路径存放到队列中
if (node.left != null) {
queue.add(node.left);
queue.add(path + "->" + node.left.val);
}
}
return res;
}
给你 root1
和 root2
这两棵二叉搜索树。请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序。.
示例 1:
输入:root1 = [2,1,4], root2 = [1,0,3] 输出:[0,1,1,2,3,4]
示例 2:
输入:root1 = [1,null,8], root2 = [8,1] 输出:[1,1,8,8]
提示:
- 每棵树的节点数在
[0, 5000]
范围内 -105 <= Node.val <= 105
/**
* 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 {
private void dfs(TreeNode root, List<Integer> ansList) {
if (root == null) {
return;
}
dfs(root.left, ansList);
ansList.add(root.val);
dfs(root.right, ansList);
}
private List<Integer> merge(List<Integer> list1, List<Integer> list2) {
List<Integer> ansList = new ArrayList<>();
int size1 = list1.size();
int size2 = list2.size();
int index1, index2;
for (index1 = 0, index2 = 0; index1 < size1 && index2 < size2;) {
int num1 = list1.get(index1);
int num2 = list2.get(index2);
if (num1 < num2) {
ansList.add(num1);
index1++;
} else {
ansList.add(num2);
index2++;
}
}
while (index1 < size1) {
ansList.add(list1.get(index1++));
}
while (index2 < size2) {
ansList.add(list2.get(index2++));
}
return ansList;
}
public List<Integer> getAllElements(TreeNode root1, TreeNode root2) {
List<Integer> ansList1 = new ArrayList<>();
List<Integer> ansList2 = new ArrayList<>();
dfs(root1, ansList1);
dfs(root2, ansList2);
return merge(ansList1, ansList2);
}
}
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
这题比较简单,常见的有两种解决思路,一种是使用BFS一种是使用DFS,我们来看下使用DFS怎么解决。
可以参照二叉树的前序遍历,访问到每个节点的时候就用targetSum减去当前节点的值,到叶子节点的时候,如果targetSum的值正好等于该叶子节点的值,说明存在一条这样的路径,直接返回true即可。
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null)
return false;
// 如果到叶子节点了,并且剩余值等于叶子节点的值,返回true。
if (root.left == null && root.right == null && targetSum == root.val)
return true;
// 分别沿着左右子节点走下去,然后顺便把当前节点的值减掉,
// 左右子节点只要有一个返回true,说明存在这样的结果。
return hasPathSum(root.left, targetSum - root.val)
|| hasPathSum(root.right, targetSum - root.val);
}
二叉树的序列化和反序列化,DFS的实现,序列化直接递归拼接即可.
1class Codec {
2
3 //把树转化为字符串(使用DFS遍历,也是前序遍历,顺序是:根节点→左子树→右子树)
4 public String serialize(TreeNode root) {
5 //边界判断,如果为空就返回一个字符串"#"
6 if (root == null)
7 return "#";
8 return root.val + "," + serialize(root.left) + "," + serialize(root.right);
9 }
10
11 //把字符串还原为二叉树
12 public TreeNode deserialize(String data) {
13 //把字符串data以逗号","拆分,拆分之后存储到队列中
14 Queue<String> queue = new LinkedList<>(Arrays.asList(data.split(",")));
15 return helper(queue);
16 }
17
18 private TreeNode helper(Queue<String> queue) {
19 //出队
20 String sVal = queue.poll();
21 //如果是"#"表示空节点
22 if ("#".equals(sVal))
23 return null;
24 //否则创建当前节点
25 TreeNode root = new TreeNode(Integer.valueOf(sVal));
26 //分别创建左子树和右子树
27 root.left = helper(queue);
28 root.right = helper(queue);
29 return root;
30 }
31}
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。后序遍历.
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出:3 解释:节点5
和节点1
的最近公共祖先是节点3 。
示例 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出:5 解释:节点5
和节点4
的最近公共祖先是节点5 。
因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2 输出:1
1,如果两个节点都在左子树上,就返回左子树上的结果。
2,如果两个节点都在右子树上,就返回右子树上的结果。
3,如果两个节点分别在两棵子树上,说明当前节点就是它俩的最近公共祖先节点,直接返回当前节点即可。
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == root || q == root)
return root;
// 参考二叉树的后序遍历
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null)// 左子树为空,肯定都在右子树上
return right;
if (right == null)// 右子树为空,肯定都在左子树上
return left;
// 左右子树都不为空,一个在左子树一个在右子树,所以root就是他们的最近公共祖先节点。
return root;
}
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点2
和节点8
的最近公共祖先是6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 输出: 2 解释: 节点2
和节点4
的最近公共祖先是2
, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉搜索树中。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
/**
如果两个节点值都小于根节点,说明他们都在根节点的左子树上,我们往左子树上找
如果两个节点值都大于根节点,说明他们都在根节点的右子树上,我们往右子树上找
如果一个节点值大于根节点,一个节点值小于根节点,说明他们他们一个在根节点的左子树上一个在根节点的右子树上,那么根节点就是他们的最近公共祖先节点。
*/
TreeNode ancestor = root;
while (true) {
if (p.val < ancestor.val && q.val < ancestor.val) {
ancestor = ancestor.left;
} else if (p.val > ancestor.val && q.val > ancestor.val) {
ancestor = ancestor.right;
} else {
break;
}
}
return ancestor;
}
请设计一个函数判断一棵二叉树是否 轴对称 。
示例 1:
输入:root = [6,7,7,8,9,9,8] 输出:true 解释:从图中可看出树是轴对称的。
示例 2:
输入:root = [1,2,2,null,3,null,3] 输出:false 解释:从图中可看出最后一层的节点不对称。
对称二叉树定义: 对于树中 任意两个对称节点 L 和 R,一定有:
L.val = R.val :即此两对称节点值相等。
L.left.val = R.right.val :即 L 的 左子节点 和 R 的 右子节点 对称;
L.right.val = R.left.val :即 L 的 右子节点 和 R 的 左子节点 对称。
递归实现如下:
class Solution {
public boolean checkSymmetricTree(TreeNode root) {
return root==null||recur(root.left,root.right);
}
// 判断左节点和右节点
public boolean recur(TreeNode L,TreeNode R){
if(L==null && R==null){
return true;
}
if(L==null || R==null || L.val!=R.val ){
return false;
}
// 递归左子树和右子树,右子树和左子树
return recur(L.left,R.right)&&recur(L.right,R.left);
}
}
给你一棵二叉树的根节点 root
,请你判断这棵树是否是一棵 完全二叉树 。
解题思路:
把一颗树的节点(包括空节点)按层序遍历排成一行。
当且仅当存在两个相邻节点:
-
前一个为
null
,后一个不为null
时,才不是完全二叉树。
class Solution {
public boolean isCompleteTree(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
TreeNode prev = root;
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.remove();
if (prev == null && node != null) {
return false;
}
if (node != null) {
queue.add(node.left);
queue.add(node.right);
}
prev = node;
}
return true;
}
}
给你一棵二叉树的根节点 root
,返回树的 最大宽度 。
树的 最大宽度 是所有层中最大的 宽度 。
每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null
节点,这些 null
节点也计入长度。
题目数据保证答案将会在 32 位 带符号整数范围内。
示例 1:
输入:root = [1,3,2,5,3,null,9] 输出:4 解释:最大宽度出现在树的第 3 层,宽度为 4 (5,3,null,9) 。
示例 2:
输入:root = [1,3,2,5,null,null,9,6,null,7] 输出:7 解释:最大宽度出现在树的第 4 层,宽度为 7 (6,null,null,null,null,null,7) 。
示例 3:
输入:root = [1,3,2,5] 输出:2 解释:最大宽度出现在树的第 2 层,宽度为 2 (3,2) 。
提示:
- 树中节点的数目范围是
[1, 3000]
class Solution {
public int widthOfBinaryTree(TreeNode root) {
if(root==null){
return 0;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
// 最大宽度
int maxWide=0;
// 设置根节点值为1
root.val=1;
while(!queue.isEmpty()){
int levelCount=queue.size();
// 当前层最左边节点的值
int left=queue.peekFirst().val;
// 当前层最右边节点的值
int right=queue.peekLast().val;
// 两边的值位置差值相减
maxWide=Math.max(maxWide,right-left+1);
for(int i=0;i<levelCount;i++){
TreeNode node=queue.poll();
int position=node.val;
if(node.left!=null){
node.left.val=position*2;
queue.offer(node.left);
}
if(node.right!=null){
node.right.val=position*2+1;
queue.offer(node.right);
}
}
}
return maxWide;
}
}
给定二叉搜索树的根结点 root
,返回值位于范围 [low, high]
之间的所有结点的值的和。
示例 1:
输入:root = [10,5,15,3,7,null,18], low = 7, high = 15 输出:32
示例 2:
输入:root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10 输出:23
class Solution {
public int rangeSumBST(TreeNode root, int low, int high) {
if(root==null){
return 0;
}
// 比最大的值都大,那就计算左边的值
if(root.val>high){
return rangeSumBST(root.left,low,high);
}
// 比最小的值都大,那就计算右子树
if(root.val<low){
return rangeSumBST(root.right,low,high);
}
// 如果当前节点值在[low,high],二叉树的中序遍历
return root.val+rangeSumBST(root.left,low,high)+rangeSumBST(root.right,low,high);
}
}