二叉树的创建及遍历
力扣链接
接口类型的OJ题目:
1.必须要给一个public类型的Main类
2.手动引入用到的包
import java.util.Scanner;
class BTNode{
BTNode left = null;//指向该节点的左子树
BTNode right = null;//指向该节点的右子树
char val;
public BTNode(char val){
this.val=val;
}
}
class BinTree{
public BTNode root=null;
public int index=0;
public BinTree(String s, char invalid) {
root = create(s,invalid);
this.index = index;
}
//按前序遍历的规则穿件二叉树
BTNode create(String s,char invalid){
BTNode newRoot=null;
if(index < s.length() && s.charAt(index) != invalid){
//创建根节点
newRoot=new BTNode(s.charAt(index));
//递归创建根节点的左子树
++index;
newRoot.left=create(s,invalid);
++index;
newRoot.right=create(s,invalid);
}
return newRoot;
}
public void inOrder(){
inOrder(root);
System.out.println();
}
private void inOrder(BTNode root){
if(null != root){
inOrder(root.left);
System.out.print(root.val+" ");
inOrder(root.right);
}
}
}
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
//对应IO类型的题目,必须进行循环输入
while(sc.hasNextLine()){
String s=sc.nextLine();
BinTree bt=new BinTree(s,'#');
bt.inOrder();
}
}
}
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先
情况一:
如果二叉树是通过双亲表示法或孩子双亲表示法进行表示的,则可转化为链表相交问题
情况二:
如果树是二叉搜索树
1.如果q和p有一个在根的位置 || 如果p和q分别在根节点的左右子树中,最近公共祖先一定是根节点
2.q和p都在root的左子树中,递归到左子树中求最近公共祖先
3.q和p都在root的右子树中,递归到右子树中求最近公共祖先
二叉搜索树特点:
1.根节点比左子树中所有节点都大
2.根节点比右子树中所有节点都小
3.左右子树也满足上述两点
情况三:
二叉树既不是双亲表示法,也不是二叉搜索树,就是一颗普通的二叉树
求解方式:可以参考情况一和情况二
力扣链接
参考情况一:获取一个节点的路径(从根到该节点所经路径中的所有节点)
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null || p==null|| q==null){
return null;
}
//获取p和q在root中的路径
Stack<TreeNode> pPath=new Stack<>();
Stack<TreeNode> qPath=new Stack<>();
egtNodepath(root,p,pPath);
egtNodepath(root,q,qPath);
//两个路径对应栈:
//1.应该让节点个数多的栈,先出栈到节点个数相同
//2.依次比较两个栈顶元素
// a.相等---->即最近公共祖先节点
// b.不相等---->两个栈同时出,然后继续2
int sizep=pPath.size();
int sizeq=qPath.size();
while(sizep != 0 && sizeq!=0){
if(sizep>sizeq){
pPath.pop();
sizep--;
}else if(sizep<sizeq){
qPath.pop();
sizeq--;
}else{
if(pPath.peek()==qPath.peek()){
return pPath.peek();
}else{
qPath.pop();
pPath.pop();
sizeq--;
sizep--;
}
}
}
return null;
}
//获取节点路径
private boolean egtNodepath(TreeNode root, TreeNode node , Stack<TreeNode> sPath){
if(null== root){
return false;
}
sPath.push(root);
if(root==node){
return true;
}
//递归到root的左子树||右子树中找到弄得路径
if(egtNodepath(root.left,node,sPath)||egtNodepath(root.right,node,sPath)){
return true;
}
sPath.pop();
return false;
}
}
参考情况二:
假设能够知道p和q在root子树中的情况:
1.如果q和p有一个在根的位置 || 如果p和q分别在根节点的左右子树中,最近公共祖先一定是根节点
2.q和p都在root的左子树中,递归到左子树中求最近公共祖先
3.q和p都在root的右子树中,递归到右子树中求最近公共祖先
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null || p==null|| q==null){
return null;
}
//如果有一个节点在根的位置,最近公共祖先一定是根节点
if(root==p || root ==q){
return root;
}
//检测p和q在root子树中的情况
boolean ispleft=false;
boolean ispright=false;
boolean isqleft=false;
boolean isqright=false;
//检测p是否在左子树
if(isNodeTree(root.left,p)){
ispright=false;
ispleft=true;
}else{
ispright=true;
ispleft=false;
}
if(isNodeTree(root.left,q)) {
isqright=false;
isqleft=true;
}else{
isqright=true;
isqleft=false;
}
//p和q分别在root的左右子树中
if(ispleft && isqright || ispright && isqleft){
return root;
}else if(ispleft && isqleft){
return lowestCommonAncestor(root.left,p,q);
}else{
return lowestCommonAncestor(root.right,p,q);
}
}
//检测是否在一棵子树中
private boolean isNodeTree(TreeNode root,TreeNode s){
if(root == null){
return false;
}
if(root == s){
return true;
}
if(isNodeTree(root.left,s) || isNodeTree(root.right,s)){
return true;
}
return false;
}
}