翻转二叉树
交换左右指针
java
//DFS递归
class Solution {
/**
* 前后序遍历都可以
* 中序不行,因为先左孩子交换孩子,再根交换孩子(做完后,右孩子已经变成了原来的左孩子),再右孩子交换孩子(此时其实是对原来的左孩子做交换)
*/
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
invertTree(root.left);
invertTree(root.right);
swapChildren(root);
return root;
}
private void swapChildren(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
java
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null) return null;
TreeNode temp=root.left;
root.left=invertTree(root.right);
root.right=invertTree(temp);
return root;
}
}
java
//BFS
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {return null;}
ArrayDeque<TreeNode> deque = new ArrayDeque<>();
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
while (size-- > 0) {
TreeNode node = deque.poll();
swap(node);
if (node.left != null) deque.offer(node.left);
if (node.right != null) deque.offer(node.right);
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
N叉树的前序遍历
java
/*
// 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 List<Integer> preorder(Node root) {
List<Integer> res=new ArrayList<>();
if(root==null){
return res;
}
preorderorder(root,res);
return res;
}
public void preorderorder(Node root,List<Integer> res){
res.add(root.val);
for(Node child:root.children){
preorderorder(child,res);
}
}
N叉树的后序遍历
java
/*
// 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 List<Integer> postorder(Node root) {
List<Integer> res=new ArrayList<>();
if(root==null){
return res;
}
postorderorder(root,res);
return res;
}
public void postorderorder(Node root,List<Integer> res){
for(Node child:root.children){
postorderorder(child,res);
}
res.add(root.val);
}
}
对称二叉树
java
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root==null) return true;
return compare(root.left,root.right);
}
public boolean compare(TreeNode left,TreeNode right){
if(left==null&&right==null)
return true;
if(left==null&&right!=null)
return false;
if(left!=null&&right==null)
return false;
if(left.val!=right.val)
return false;
boolean compare_innner=compare(left.left,right.right);
boolean compare_outside=compare(left.right,right.left);
return compare_innner&&compare_outside;
}
}
变型题目
相同的树
java
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q==null)
return true;
if(p==null&&q!=null)
return false;
if(p!=null&&q==null)
return false;
if(p.val!=q.val)
return false;
boolean inner=isSameTree(p.left,q.left);
boolean outside=isSameTree(p.right,q.right);
return inner&&outside;
}
}
变形题目二:
另一棵数的子树
两个树相同是里面一种特殊的情况
运用迭代的思路
java
class Solution {
public boolean isSubtree(TreeNode p, TreeNode q) {
if(q==null) return true;
if(p==null) return false;
return isSubtree(p.left,q)||isSubtree(p.right,q)||isSameTree(p,q);
}
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q==null)
return true;
if(p==null&&q!=null)
return false;
if(p!=null&&q==null)
return false;
if(p.val!=q.val)
return false;
boolean inner=isSameTree(p.left,q.left);
boolean outside=isSameTree(p.right,q.right);
return inner&&outside;
}
}
二叉树的最大深度
利用层序遍历的思路
java
class Solution {
public int maxDepth(TreeNode root) {
int res=0;
if(root==null) return res;
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int len=queue.size();
while(len>0){
TreeNode node=queue.poll();
len--;
if(node.left!=null) queue.offer(node.left);
if(node.right!=null) queue.offer(node.right);
}
res++;
}
return res;
}
}
官方题解:这个太巧妙了,我感觉我记不住
尝试去理解官方说的前序的思路
java
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth, rightDepth) + 1;
N叉树的最大深度
利用层序遍历的思路
java
class Solution {
public int maxDepth(Node root) {
int res=0;
if(root==null) return res;
Queue<Node> queue=new LinkedList<Node>();
queue.offer(root);
while(!queue.isEmpty()){
int len=queue.size();
while(len>0){
Node node=queue.poll();
len--;
for(Node n:node.children){
if(n!=null){
queue.offer(n);
}
}
}
res++;
}
return res;
}
}
官方题解:
java
class Solution {
/*递归法,后序遍历求root节点的高度*/
public int maxDepth(Node root) {
if (root == null) return 0;
int depth = 0;
if (root.children != null){
for (Node child : root.children){
depth = Math.max(depth, maxDepth(child));
}
}
return depth + 1; //中节点
}
}
二叉树的最小深度
java
class Solution {
public int minDepth(TreeNode root) {
int res=0;
if(root==null) return res;
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int len=queue.size();
res++;
while(len>0){
TreeNode node=queue.poll();
len--;
if(node.left!=null) queue.offer(node.left);
if(node.right!=null) queue.offer(node.right);
if(node.left==null&&node.right==null)return res;
}
}
return res;
}
}
完美二叉树的节点个数
java
class Solution {
public int countNodes(TreeNode root) {
int res=0;
if(root==null) return res;
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int len=queue.size();
while(len>0){
TreeNode node=queue.poll();
res++;
len--;
if(node.left!=null) queue.offer(node.left);
if(node.right!=null) queue.offer(node.right);
}
}
return res;
}
}
平衡二叉树
这里强调一波概念:
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
一个是从上到下,一个是从下到上
遍历方式不同,一个是中左右,一个是左右中
java
class Solution {
public boolean isBalanced(TreeNode root) {
return getheight(root)!=-1;
}
public int getheight(TreeNode root){
if(root==null){
return 0;
}
int left=getheight(root.left);
if(left==-1){
return -1;
}
int right=getheight(root.right);
if(right==-1){
return -1;
}
if(Math.abs(left-right)>1){
return -1;
}
return Math.max(left,right)+1;
}
}
二叉树的所有路径
说这道题目利用回溯的思想,第二个代码传入
deal(root.right,temp); 相当于回去了
deal(root.left,temp);
deal(root.right,temp);
本周小结!(二叉树系列二) | 代码随想录 (programmercarl.com)
就是遍历二叉树的所有路径,遇到遍历,一般的思路就是迭代和递归
这里用迭代的思想,递归的思想我脑子是真的转不过来
迭代三要素:
确定参数:传入参数和返回参数
终止条件:
处理逻辑:
如果处理逻辑比较麻烦,可以单独写一个函数抽离出来,不一定非得自己反复调用自己
java
class Solution {
List<String> res=new ArrayList<>();
public List<String> binaryTreePaths(TreeNode root) {
deal(root,"");
return res;
}
public void deal(TreeNode root,String s){
if(root==null) {
return ;
}
if(root.left==null&&root.right==null){
res.add(new StringBuilder(s).append(root.val).toString());
return ;
}
String temp=new StringBuilder(s).append(root.val).append("->").toString();
deal(root.left,temp);
deal(root.right,temp);
}
}
讲了这么多二叉树题目的迭代法,有的同学会疑惑,迭代法中究竟什么时候用队列,什么时候用栈?
如果是模拟前中后序遍历就用栈,如果是适合层序遍历就用队列,当然还是其他情况,那么就是 先用队列试试行不行,不行就用栈。
左叶子之和
首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。
java
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root==null)
return 0;
int left=sumOfLeftLeaves(root.left);
int right=sumOfLeftLeaves(root.right);
int mid=0;
if(root.left!=null&&root.left.left==null&&root.left.right==null){
mid=root.left.val;
}
return mid+left+right;
}
}