一、二叉树层次遍历
从上往下打印二叉树
利用队列从上至下,从左至右,依次存储每一个结点。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
# write code here
res=[]
q=[]
if not root:
return []
q.append(root)//根节点加入队列中
while(q):
res.append(q[0].val)//队头元素的值
if q[0].left://判读对头节点的左右节点加入队列
q.append(q[0].left)
if q[0].right:
q.append(q[0].right)
q.pop(0)
return res
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> res=new ArrayList<>();
Queue<TreeNode> queue=new LinkedList<>();//queue是抽象类,要用LinkedList创建
if(root==null) return res;
queue.add(root);
while(!queue.isEmpty()){
res.add(queue.peek().val);//peek()取对头元素
TreeNode node=queue.poll();//将队头元素删除,没有则返回null
if(node.left!=null) queue.add(node.left);
if(node.right!=null) queue.add(node.right);
}
return res;
}
}
把二叉树打印成多行
每行记录当前行个数和下一行个数;或者当前行列表,下一行列表。
每行记录成一个列表,然后总的res
python
思路:利用层次遍历,但加入本层levelque和下一层nextlevel,res存放最终值
1.根节点加入levelque中
2.while leveque:针对每层创建一个nextlevel(存入左子树和右子树),curvalue存放当前层的值
3.然后将curvalue加入res中,nextlevel给level
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回二维列表[[1,2],[4,5]]
def Print(self, pRoot):
# write code here
if not pRoot:
return []
levelque=[pRoot]
res=[]
while levelque:
curvalue=[]
nextlevel=[]
for i in levelque:
curvalue.append(i.val)
if i.left:
nextlevel.append(i.left)
if i.right:
nextlevel.append(i.right)
if curvalue:
res.append(curvalue)
levelque=nextlevel
return res
层次遍历,利用current count和nextcount计数。
import java.util.*;
/*
public class TreeNode {
int val = 0;n
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res=new ArrayList<>();
ArrayList<Integer> list=new ArrayList<>();
if(pRoot==null) return res;
Queue<TreeNode> q=new LinkedList<>();
int curcount=0;
int nextcount=1;
q.add(pRoot);
while(!q.isEmpty()){
TreeNode cur=q.poll();
curcount+=1;
list.add(cur.val);
if(cur.left!=null)q.add(cur.left);
if(cur.right!=null) q.add(cur.right);
if(curcount==nextcount){
res.add(list);
curcount=0;
nextcount=q.size();
list=new ArrayList<Integer>();
}
}
return res;
}
}
按之字形顺序打印二叉树
思路一:按层次遍历,偶数行,逆序加入
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def Print(self, pRoot):
# write code here
if not pRoot:
return []
levelque=[pRoot]
righttoleft=False
res=[]
while levelque:
curvalue=[]
nextlevel=[]
for i in levelque:
curvalue.append(i.val)
if i.left:
nextlevel.append(i.left)
if i.right:
nextlevel.append(i.right)
if righttoleft:
curvalue.reverse()
if curvalue:
res.append(curvalue)
levelque=nextlevel
righttoleft= not righttoleft
return res
public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res=new ArrayList<>();
ArrayList<Integer> list=new ArrayList<>();
if(pRoot==null) return res;
Queue<TreeNode> q=new LinkedList<>();
int curcount=0;
int nextcount=1;
boolean righttoleft=false;
q.add(pRoot);
while(!q.isEmpty()){
TreeNode cur=q.poll();
curcount+=1;
list.add(cur.val);
if(cur.left!=null)q.add(cur.left);
if(cur.right!=null) q.add(cur.right);
if(curcount==nextcount){
if(!righttoleft) res.add(list);
else{
Collections.reverse(list);
res.add(list);
}
curcount=0;
nextcount=q.size();
list=new ArrayList<Integer>();
righttoleft=!righttoleft;
}
}
return res;
}
}
思路二:利用两个stack,后进先出特性
import java.util.ArrayList;
import java.util.Stack;
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res=new ArrayList<>();
if(pRoot==null) return res;
Stack<TreeNode> s1=new Stack<>();
Stack<TreeNode> s2=new Stack<>();
s1.push(pRoot);
int level=1;
while(!s1.isEmpty()||!s2.isEmpty()){
ArrayList<Integer> list=new ArrayList<>();
if(level++%2!=0){//层级,奇数,偶数
while(!s1.isEmpty()){
TreeNode cur=s1.pop();
list.add(cur.val);
if(cur.left!=null) s2.push(cur.left);//s2逆序,先进后厨
if(cur.right!=null) s2.push(cur.right);
}
}
else{//逆序
while(!s2.isEmpty()){
TreeNode cur=s2.pop();
list.add(cur.val);
if(cur.right!=null) s1.push(cur.right);
if(cur.left!=null) s1.push(cur.left);
}
}
res.add(list);
}
return res;
}
}
二、递归相关
二叉树的最大深度
思路:
递归:左树右树的深度最大值+1
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def TreeDepth(self, pRoot):
# write code here
if not pRoot:
return 0
lefttree=self.TreeDepth(pRoot.left)
righttree=self.TreeDepth(pRoot.right)
return max(lefttree,righttree)+1
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
public class Solution {
public int TreeDepth(TreeNode root) {
if(root==null) return 0;
return Math.max(TreeDepth(root.left),TreeDepth(root.right))+1;
}
}
非递归:
层次遍历
利用currentcount和nextcount来记录当前层的应遍历的节点个数,满足遍历完后,depth+=1
public class Solution {
public int TreeDepth(TreeNode root) {
if(root==null) return 0;
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
int depth=0;
int currentcount=0;//记录当前层的节点个数
int nextcount=1;//当前层应有的节点个数
while(!queue.isEmpty()){
TreeNode currentnode=queue.poll();
currentcount+=1;
if(currentnode.left!=null) queue.add(currentnode.left);
if(currentnode.right!=null) queue.add(currentnode.right);
if(currentcount==nextcount){//满足时,表示当前层遍历完,深度可以加1
currentcount=0;
nextcount=queue.size();
depth+=1;
}
}
return depth;
}
}
最小深度
import java.util.*;
public class Solution {
public int run(TreeNode root) {
if(root==null)
return 0;
else if(root.left==null && root.right==null)
return 1;
else if(root.left==null)
return run(root.right)+1;
else if(root.right==null)
return run(root.left)+1;
return Math.min(run(root.left),run(root.right))+1;
}
}
思路二:广度遍历(BFS),用linkedlist创建queue,注意利用queue.size()判断每层节点数queue.poll()利用level记录,遇到子节点(无左右子树的节点)则返回深度level
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
import java.util.*;
public class Solution {
public int run(TreeNode root) {
if(root==null)
return 0;
if(root.left==null && root.right==null)
return 1;
Queue<TreeNode> queue=new LinkedList<TreeNode>();
queue.add(root);
int level=1;
while(!queue.isEmpty()){
int size=queue.size();//每层看有几个节点
for(int i=0;i<size;i++){//对于每层的每个节点判断
TreeNode node=queue.poll();
if(node.left!=null)
queue.add(node.left);
if(node.right!=null)
queue.add(node.right);
if(node.left==null && node.right==null)//如果左右子树都为空则表示该节点为叶子节点,当前既是最小深度
return level;
}
level++;
}
return level;
}
}
平衡二叉树
二叉树的左右子树高度差不超过1
先计算二叉树的最大高度
遍历每一个节点,根据该结点的左右子树高度差判断是否平衡,然后递归地对左右子树进行判断。
超过1,False;不超过1,左右子树都判断
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def IsBalanced_Solution(self, pRoot):
# write code here
if pRoot is None:#递归退出条件
return True
if abs(self.TreeDepth(pRoot.left)-self.TreeDepth(pRoot.right))>1:#根节点的左子树右子树判断
return False
return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)#左子树右子树分别递归
def TreeDepth(self,Root):#判断树的深度
if Root is None:
return 0
left=self.TreeDepth(Root.left)
right=self.TreeDepth(Root.right)
return max(left,right)+1
三、二叉树的镜像和对称
1.对称的二叉树
判断比较
思路:
定义一个比较函数比较左右子树
1.左子树为空,返回右子树是否为空
2.右子树为空,返回false
3.左右节点的值不同,返回false
4.递归比较 左子树的右子树和右子树的左子树 and 右子树的左子树和左子树的右子树
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSymmetrical(self, pRoot):
# write code here
if not pRoot:
return True
return self.compare(pRoot.left,pRoot.right)
def compare(self,leftroot,rightroot):
if leftroot==None:
return rightroot==None
if rightroot==None:
return False
if leftroot.val!=rightroot.val:
return False
return self.compare(leftroot.right,rightroot.left) and self.compare(leftroot.left,rightroot.right)
2.二叉树的镜像
将二叉树转成镜像,交换节点和递归
思路一:递归:若root为空,若root.left and root.right都为空,则返回;
其次进行左右节点交换;
然后左节点不空,则左节点Mirror;右节点不空,则右节点Mirror
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# write code here
if root is None:
return
if (root.left is None and root.right is None):
return
tmp=root.left
root.left=root.right
root.right=tmp
if root.left is not None:
self.Mirror(root.left)
if root.right is not None:
self.Mirror(root.right)
return root
四、重构二叉树
根据前序遍历和中序遍历,重建二叉树
思路一:找到中序中根节点所在位置,分为左子树,右子树递归调用重建
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if len(pre)==0 or len(tin)==0:
return None
root=TreeNode(pre[0])//创建根节点
pos=tin.index(pre[0])
root.left=self.reConstructBinaryTree(pre[1:pos+1],tin[:pos])//左子树
root.right=self.reConstructBinaryTree(pre[pos+1:],tin[pos+1:])//右子树
return root
五、二叉树的下一个结点
思路:
1.空,返回空
2.该节点存在右子节点,则指针指向该节点的右子节点,循环判断右子节点的左节点,直到左子节点为空
3.该节点不存在右子节点,循环条件(该节点的下一个节点不为空)创建一个根节点(指向该节点的下一个节点),若该节点为根节点的左子节点,返回该节点;否则继续.next
# -*- coding:utf-8 -*-
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None
class Solution:
def GetNext(self, pNode):
# write code here
if pNode==None:
return None
if pNode.right!=None:
pNode=pNode.right
while(pNode.left!=None):
pNode=pNode.left
return pNode
while pNode.next!=None:
root=pNode.next
if root.left==pNode:
return root
pNode=pNode.next
return None