相同的树(深度优先搜索、广度优先搜索)
给定两个二叉树的根节点,判断两棵树是否完全相同
对两棵树使用相同的方式遍历比较即可
- 深度优先搜索
/**
* 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 isSameTree(TreeNode p, TreeNode q) {
//按照同样的顺序遍历两个树 然后对比
if(p == null && q == null){
return true;
}
if((p == null || q == null) || p.val != q.val){
return false;
}
return tdoTrav(p.left , q.left) && doTrav(p.right , q.right);
}
}
- 广度优先搜索
二叉树的遍历方法一般是按照深度有限的原则,但是可以使用队列来实现广度优先的搜索,即按照树的层数一层一层的向下搜索
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
//使用队列作为暂存
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
while( !(queue.size()== 0 && p == null && q == null)){
if(p == null && q == null){
p = queue.poll();
q = queue.poll();
continue;
}
if(p == null || q == null || p.val != q.val){
return false;
}
queue.add(p.left);
queue.add(q.left);
queue.add(p.right);
queue.add(q.right);
p = null;
q = null;
}
return true;
}
}
对称二叉树(深度优先搜索、广度优先搜索)
给定一个二叉树,判断该二叉树是不是轴对称的
- 取出root节点的左子节点和右子节点,对两棵子树进行深度优先遍历
class Solution {
public boolean isSymmetric(TreeNode root) {
//将树分为两棵树 完成后查看两棵树是否相同 使用深度优先检索
if(root == null){
return true;
}
return doTrav(root.left , root.right);
}
public boolean doTrav(TreeNode a , TreeNode b){
if(a == null && b == null){
return true;
}
if(a == null || b == null){
return false;
}
if(a.val != b.val){
return false;
}
//注意 这里不是比较两棵树是否是相同树,而是根据轴进行对称
return doTrav(a.left , b.right) && doTrav(a.right , b.left);
}
}
- 广度优先遍历root节点的两子树
class Solution {
public boolean isSymmetric(TreeNode root) {
//使用迭代法处理 这里使用广度优先检索
if(root == null){
return true;
}
TreeNode p = root.left;
TreeNode q = root.right;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
while(!(queue.isEmpty() && p == null && q == null)){
if(p == null && q == null){
p = queue.poll();
q = queue.poll();
continue;
}
if(p == null || q == null || p.val != q.val){
return false;
}
queue.add(p.left);
queue.add(q.right);
queue.add(p.right);
queue.add(q.left);
p = null;
q = null;
}
return true;
}
}
二叉树的最大深度
给定一个二叉树,请求出该二叉树的最大深度
- 深度优先遍历(递归调用)
/**
* 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) {
//递归处理 整个二叉树的最大深度为根节点加上max(左子树最大深度,右子树最大深度)
if(root == null){
return 0;
}
return 1 + Math.max(maxDepth(root.left) ,maxDepth(root.right));
}
}
- 广度优先遍历
同样可以使用队列来处理遍历,但是只有将当前层的节点全部处理完毕后才能继续向下层遍历。
/**
* 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;
}
//广度优先遍历
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int depth = 0;
while(!queue.isEmpty()){
int size = queue.size();
while(size > 0){
root = queue.poll();
if(root.left != null){
queue.add(root.left);
}
if(root.right != null){
queue.add(root.right);
}
size-- ;
}
depth ++;
}
return depth;
}
}
将有序数组转换为平衡二叉树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
- 递归法处理
因为给定的是有序数组,因此使用二分法找到每一段的中值作为节点即可
/**
* 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) {
TreeNode root = new TreeNode();
doGetMid(root,nums , 0 , nums.length - 1);
return root;
}
public void doGetMid(TreeNode root, int[] nums , int head , int tail){
int tempMid = head + (tail - head) / 2;
root.val = nums[tempMid];
if(tempMid - 1 >= head){
root.left = new TreeNode();
doGetMid(root.left , nums ,head , tempMid - 1 );
}
if(tempMid + 1 <= tail){
root.right = new TreeNode();
doGetMid(root.right , nums , tempMid + 1 , tail);
}
}
}
判断二叉树是不是平衡二叉树(递归)
给定一个二叉树,当某个节点的左右子树之间的高度差大于1时,该二叉树不是平衡二叉树
- 由顶至尾递归遍历(时间复杂度
O(n2)
)
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//确实纯想象的话是一个比较蠢的方法 因为有很多次递归 并且递归套递归
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
} else {
return Math.abs(height(root.left) - height(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
}
public int height(TreeNode root) {
if (root == null) {
return 0;
} else {
return Math.max(height(root.left), height(root.right)) + 1;
}
}
}
- 由尾至顶递归遍历(时间复杂度
O(n)
)
方法一由于是自顶向下递归,因此对于同一个节点,函数会被重复调用,导致时间复杂度较高。如果使用自底向上的做法,则对于每个节点,函数只会被调用一次。
自底向上递归的做法类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 -1−1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。
class Solution {
public boolean isBalanced(TreeNode root) {
return height(root) >= 0;
}
public int height(TreeNode root) {
if (root == null) {
return 0;
}
int leftHeight = height(root.left);
int rightHeight = height(root.right);
if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight - rightHeight) > 1) {
return -1;
} else {
return Math.max(leftHeight, rightHeight) + 1;
}
}
}
二叉树的最小深度
给定一个二叉树,请找出该二叉树的最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
只需要确定一点,当该节点没有左右子树时,可以认定为叶子节点。找出最近的叶子节点即可。
- 广度优先遍历
class Solution {
public int minDepth(TreeNode root) {
//尝试使用广度优先遍历处理
if(root == null){
return 0;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
int minDepth = 1;
queue.add(root);
while(root != null || !queue.isEmpty()){
int size = queue.size();
while(size > 0){
root = queue.poll();
if(root.left == null && root.right == null){
return minDepth;
}else{
if(root.left != null){
queue.add(root.left);
}
if(root.right != null){
queue.add(root.right);
}
}
size--;
}
minDepth++;
}
return minDepth;
}
}
- 深度优先遍历
class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
int min_depth = Integer.MAX_VALUE;
if (root.left != null) {
min_depth = Math.min(minDepth(root.left), min_depth);
}
if (root.right != null) {
min_depth = Math.min(minDepth(root.right), min_depth);
}
return min_depth + 1;
}
}
路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。
判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。
如果存在,返回 true ;否则,返回 false 。
- DFS回溯算法
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null){
return false;
}
targetSum -= root.val;
if(root.left == null && root.right == null){
if(targetSum != 0){
return false;
}else{
return true;
}
}
return hasPathSum(root.left , targetSum) || hasPathSum(root.right , targetSum) ;
}
}