算法框架:
void traverse(TreeNode root) {
// 前序遍历
traverse(root.left)
// 中序遍历
traverse(root.right)
// 后序遍历
}
1.重建二叉树
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
import java.util.Arrays;
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length==0||in.length==0){
return null;
}
TreeNode root=new TreeNode(pre[0]);
for(int i=0;i<in.length;i++){
if(pre[0]==in[i]){
//每次都找子树的左和右
root.left=reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
root.right=reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
break;
}
continue;
}
return root;
}
}
2.树的子结构
链接:https://www.nowcoder.com/questionTerminal/6e196c44c7004d15b1610b9afca8bd88?answerType=1&f=discussion
来源:牛客网
public class Solution {
public boolean jude(TreeNode node, TreeNode no) { // 第二步
if (no == null) {
return true;
}
if (node == null) {
return false;
}
if (node.val == no.val) {
return jude(node.left, no.left) && jude(node.right, no.right);
} else {
return false;
}
}
public boolean HasSubtree(TreeNode root1, TreeNode root2) { // 第一步 深度遍历
if (root1 == null || root2 == null) {
return false;
}
return jude(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
}
}
3.二叉树的镜像
链接:https://www.nowcoder.com/questionTerminal/564f4c26aa584921bc75623e48ca3011?answerType=1&f=discussion
来源:牛客网
public void Mirror(TreeNode root) {
if(root == null) return;
Queue<TreeNode> nodes = new LinkedList<>();
TreeNode curr, temp;
nodes.offer(root);
while(!nodes.isEmpty()){
int len = nodes.size();
for(int i = 0; i < len; i++){
curr = nodes.poll();
temp = curr.left;
curr.left = curr.right;
curr.right = temp;
if(curr.left != null) nodes.offer(curr.left);
if(curr.right != null) nodes.offer(curr.right);
}
}
}
4.二叉树的后序遍历序列
链接:https://www.nowcoder.com/questionTerminal/a861533d45854474ac791d90e447bafd?answerType=1&f=discussion
来源:牛客网
public class Solution {
public boolean helpVerify(int [] sequence, int start, int root){
if(start >= root)return true;
int key = sequence[root];
int i;
//找到左右子数的分界点
for(i=start; i < root; i++)
if(sequence[i] > key)
break;
//在右子树中判断是否含有小于root的值,如果有返回false
for(int j = i; j < root; j++)
if(sequence[j] < key)
return false;
return helpVerify(sequence, start, i-1) && helpVerify(sequence, i, root-1);
}
public boolean VerifySquenceOfBST(int [] sequence) {
if(sequence == null || sequence.length == 0)return false;
return helpVerify(sequence, 0, sequence.length-1);
}
}
5.打印二叉树
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> res;
if(root==NULL)
return res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
res.push_back(q.front()->val);
if(q.front()->left!=NULL)
q.push(q.front()->left);
if(q.front()->right!=NULL)
q.push(q.front()->right);
q.pop();
}
return res;
}
};
6.二叉树中和为某一值的路径
链接:https://www.nowcoder.com/questionTerminal/b736e784e3e34731af99065031301bca?answerType=1&f=discussion
来源:牛客网
public class Solution {
private ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
private ArrayList<Integer> list = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
if(root == null)return result;
list.add(root.val);
target -= root.val;
if(target == 0 && root.left == null && root.right == null)
result.add(new ArrayList<Integer>(list));
//因为在每一次的递归中,我们使用的是相同的result引用,所以其实左右子树递归得到的结果我们不需要关心,
//可以简写为FindPath(root.left, target);FindPath(root.right, target);
//但是为了大家能够看清楚递归的真相,此处我还是把递归的形式给大家展现了出来。
ArrayList<ArrayList<Integer>> result1 = FindPath(root.left, target);
ArrayList<ArrayList<Integer>> result2 = FindPath(root.right, target);
list.remove(list.size()-1);
return result;
}
}
7.二叉搜索树与双向链表
链接:https://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5?answerType=1&f=discussion
来源:牛客网
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null){
return null;
}
ArrayList<TreeNode> list = new ArrayList<>();
Convert(pRootOfTree, list);
return Convert(list);
}
//中序遍历,在list中按遍历顺序保存
public void Convert(TreeNode pRootOfTree, ArrayList<TreeNode> list){
if(pRootOfTree.left != null){
Convert(pRootOfTree.left, list);
}
list.add(pRootOfTree);
if(pRootOfTree.right != null){
Convert(pRootOfTree.right, list);
}
}
//遍历list,修改指针
public TreeNode Convert(ArrayList<TreeNode> list){
for(int i = 0; i < list.size() - 1; i++){
list.get(i).right = list.get(i + 1);
list.get(i + 1).left = list.get(i);
}
return list.get(0);
}
8.二叉树的深度
/**
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;
int left=TreeDepth(root.left);
int right=TreeDepth(root.right);
int result=Math.max(left,right)+1;
return result;
}
}
9.平衡二叉树
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
return deepOftree(root)!=-1;
}
int deepOftree(TreeNode root){
if(root==null)return 0;
int a=deepOftree(root.left);
int b=deepOftree(root.right);
if(a==-1||b==-1||Math.abs(a-b)>1)return -1;
else return (a>b?a:b)+1;
}
}
10.二叉树的下一个结点
分析二叉树的下一个节点,一共有以下情况: 1.二叉树为空,则返回空; 2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点; 3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。代码如下:
链接:https://www.nowcoder.com/questionTerminal/9023a0c988684a53960365b889ceaf5e?f=discussion
来源:牛客网
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if(pNode==NULL)
return NULL;
if(pNode->right!=NULL)
{
pNode=pNode->right;
while(pNode->left!=NULL)
pNode=pNode->left;
return pNode;
}
while(pNode->next!=NULL)
{
TreeLinkNode *proot=pNode->next;
if(proot->left==pNode)
return proot;
pNode=pNode->next;
}
return NULL;
}
};
11.对称的二叉树
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
return pRoot==null||judge(pRoot.right,pRoot.left);
}
boolean judge(TreeNode right,TreeNode left){
if(right==null&&left==null)return true;
if(right==null||left==null)return false;
if(right.val!=left.val){
return false;
}else{
return judge(right.left,left.right)&&judge(right.right,left.left);
}
}
}
12.按之字形顺序打印二叉树
链接:https://www.nowcoder.com/questionTerminal/91b69814117f4e8097390d107d2efbe0?f=discussion
来源:牛客网
public static ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
int layer = 1;
//s1存奇数层节点
Stack<TreeNode> s1 = new Stack<TreeNode>();
s1.push(pRoot);
//s2存偶数层节点
Stack<TreeNode> s2 = new Stack<TreeNode>();
ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
while (!s1.empty() || !s2.empty()) {
if (layer%2 != 0) {
ArrayList<Integer> temp = new ArrayList<Integer>();
while (!s1.empty()) {
TreeNode node = s1.pop();
if(node != null) {
temp.add(node.val);
System.out.print(node.val + " ");
s2.push(node.left);
s2.push(node.right);
}
}
if (!temp.isEmpty()) {
list.add(temp);
layer++;
System.out.println();
}
} else {
ArrayList<Integer> temp = new ArrayList<Integer>();
while (!s2.empty()) {
TreeNode node = s2.pop();
if(node != null) {
temp.add(node.val);
System.out.print(node.val + " ");
s1.push(node.right);
s1.push(node.left);
}
}
if (!temp.isEmpty()) {
list.add(temp);
layer++;
System.out.println();
}
}
}
return list;
}
13.把二叉树打印成多行
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;
}
}
*/
//特殊点:按行打印。所以不能普通的bfs,要对每一行的元素存进list里,对一行的元素左右压入队列才能进行下一次的循环
//要学会存数组的头节点进result数组然后返回
//java的queue方法&集合的创建
public class Solution {
ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer> >result=new ArrayList<>();
if(pRoot==null)return result;
Queue<TreeNode> queue=new LinkedList<>();
ArrayList<Integer>list;
queue.offer(pRoot);
while(!queue.isEmpty()){
list=new ArrayList<>();
int size=queue.size();
while(size!=0){
TreeNode tmp=queue.poll();
System.out.print(tmp.val+" ");
list.add(tmp.val);
if(tmp.left!=null)queue.offer(tmp.left);
if(tmp.right!=null)queue.offer(tmp.right);
size--;
}
result.add(list);
}
return result;
}
}
14.序列化二叉树
链接:https://www.nowcoder.com/questionTerminal/cf7e25aa97c04cc1a68c8f040e71fb84?answerType=1&f=discussion
来源:牛客网
public class SerializeTree {
int index = -1;
/**
* 分别遍历左节点和右节点,空使用#代替,节点之间,隔开
*
* @param root
* @return
*/
public String Serialize(TreeNode root) {
if (root == null) {
return "#";
} else {
return root.val + "," + Serialize(root.left) + "," + Serialize(root.right);
}
}
/**
* 使用index来设置树节点的val值,递归遍历左节点和右节点,如果值是#则表示是空节点,直接返回
*
* @param str
* @return
*/
TreeNode Deserialize(String str) {
String[] s = str.split(",");//将序列化之后的序列用,分隔符转化为数组
index++;//索引每次加一
int len = s.length;
if (index > len) {
return null;
}
TreeNode treeNode = null;
if (!s[index].equals("#")) {//不是叶子节点 继续走 是叶子节点出递归
treeNode = new TreeNode(Integer.parseInt(s[index]));
treeNode.left = Deserialize(str);
treeNode.right = Deserialize(str);
}
return treeNode;
}
}
15.二叉搜索树的第k个结点
链接:https://www.nowcoder.com/questionTerminal/ef068f602dde4d28aab2b210e859150a?answerType=1&f=discussion
来源:牛客网
import java.util.ArrayList;
// {8,6,10,5,7,9,11},8
// null,5
public class Solution {
ArrayList<TreeNode> list = new ArrayList<>(); // (1)
TreeNode KthNode(TreeNode pRoot, int k)
{
addNode(pRoot);
if(k>=1 && list.size()>=k) {
return list.get(k-1);
}
return null;
}
// 中序遍历
void addNode(TreeNode cur) { // (2)
if(cur != null) {
addNode(cur.left);
list.add(cur);
addNode(cur.right);
}
}
}
二叉树最大路径和
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int ans=Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxcount(root);
return ans;
}
public int maxcount(TreeNode root){
if(root==null)return 0;
int left=maxcount(root.left);
int right=maxcount(root.right);
//第一种情况
int lmr=root.val+Math.max(0,right)+Math.max(0,left);
//第二、三种情况
int ret=root.val+Math.max(0,Math.max(left,right));
//每次比较ans、lmr、ret
ans=Math.max(ans,Math.max(lmr,ret));
//由于第二、三种情况是要用递归的,所以要返回ret
return ret;
}
}