前序遍历和和中序遍历还原二叉树
链接:前序+中序还原二叉树
思路:
- 在前序遍历结果中确定二叉树的根结点(
原因:前序遍历是先遍历根结点,在遍历根的左子树,后遍历根的右子树 ); - 在中序遍历结果中找根的位置
pos ,以 pos 为分界点,左边为根的左子树元素所处的位置,右边为根的右子树元素所处的位置; - 还原根结点;
- 递归还原根的左子树;
- 递归还原根的右子树
代码实现 :
class Solution {
int index=0;
TreeNode rebuilderTree(int[] preorder,int[] inorder,int left, int right){
if(index>=preorder.length || left >= right){
return null;
}
int pos=left;
while(pos<right){
if(inorder[pos]==preorder[index]){
break;
}
pos++;
}
TreeNode root=new TreeNode(preorder[index]);
index++;
root.left=rebuilderTree(preorder,inorder,left,pos);
root.right=rebuilderTree(preorder,inorder,pos+1,right);
return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
index=0;
return rebuilderTree(preorder, inorder,0,inorder.length);
}
}
中序遍历和和后序遍历还原二叉树
链接:中序+后序还原二叉树
思路:
- 在后序遍历结果中确定二叉树的根结点(
原因:后序遍历是先遍历根的左子树,再遍历根的右子树,最后遍历根结点 ); - 在中序遍历结果中找根的位置
pos ,以 pos 为分界点,左边为根的左子树元素所处的位置,右边为根的右子树元素所处的位置; - 还原根结点;
- 递归还原根的右子树;
- 递归还原根的左子树
代码实现 :
class Solution {
int index=0;
TreeNode rebuilderTree(int[] postorder,int[] inorder,int left, int right){
if(index<0 || left >= right){
return null;
}
int pos=left;
while(pos<right){
if(inorder[pos]==postorder[index]){
break;
}
pos++;
}
TreeNode root=new TreeNode(postorder[index]);
index--;
root.right=rebuilderTree(postorder,inorder, pos+1,right);
root.left=rebuilderTree(postorder,inorder,left ,pos);
return root;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
index=postorder.length-1;
return rebuilderTree(postorder, inorder,0,inorder.length);
}
}
二叉树构造字符串
链接:二叉树构造字符串
思路:
该题目用到字符串,由于 string 是不可变类型,要拼接所以使用 stringbuilder ;
注意:题目中的左括号是不能省略的,要不然分不清左右子树的位置 ;
代码实现 :
class Solution {
public void preorder(TreeNode root, StringBuilder str) {
if (root == null) {
return;
}
str.append(root.val);
if (root.left != null) {
str.append('(');
preorder(root.left, str);
str.append(')');
}
if (root.left == null && root.right != null) {
str.append('(');
str.append(')');
}
if (root.right != null) {
str.append('(');
preorder(root.right, str);
str.append(')');
}
}
public String tree2str(TreeNode root) {
StringBuilder str = new StringBuilder();
preorder(root, str);
return str.toString();
}
}
求二叉树的最近公共祖先
链接:公共祖先
思路:
可以分三种情况来分析讨论: 情况一 :该二叉树采用双亲表示法或者是采用孩子双亲表示法; 求公共祖先就变成了两个链表相交求交点的问题了;
情况二 : 该二叉树如果为二叉搜索树,所谓二叉搜索树就是对于每个结点而言,都满足:(1)根结点大于根的左子树结点 ;(2)根结点小于根的右子树结点 ; 求公共祖先就有以下四种方式: 假设给定的两个结点,一个为 x ,一个为 y ; (1)当x == root 或y ==root 时,最近的公共祖先一定为根结点;(原因 :根结点是所有结点的祖先) (2)当 x .data< root.data && y.data>root.data 时 ,或者当 x .data> root.data && y.data<root.data ,最近的公共祖先也是根结点(原因:x, y 处在根结点的两侧); (3)当x .data< root.data && y.data<root.data 时,此时,x和y都处于根的左子树中,因此求最近的公共祖先就直接到根的左子树中找; (4)当x .data> root.data && y.data>root.data 时,此时,x 和y 都处于根的右子树中,因此求最近的公共祖先就直接到根的右子树中找;
情况三 :该二叉树就是一棵普通的二叉树;
那么:
- 受情况一的启发,只要找到从根结点出发的到某个结点的路径中遇到那些结点,并将其保存;因为当路径中的结点找到之后,需要从下往上进行比较,因此借助栈来保存;
该种情况下
(1)当栈中所存元素不相等时,让元素多的出栈 ; (2)相同且值域不同时,同时出栈 ; (3)公共祖先就是栈中元素个数相同时且值域也相同的元素 ;
代码实现 :
class Solution {
boolean getPathNode(TreeNode root,Stack<TreeNode> sPath,TreeNode node ){
if(node ==null || root==null){
return false;
}
sPath.push(root);
if(root==node){
return true;
}
if(getPathNode(root.left,sPath,node)){
return true;
}
if(getPathNode(root.right,sPath,node)){
return true;
}
sPath.pop();
return false;
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null ||p==null ||q==null){
return null;
}
Stack<TreeNode> pPath=new Stack();
Stack<TreeNode> qPath=new Stack();
getPathNode(root,pPath,p);
getPathNode(root,qPath,q);
int pSize=pPath.size();
int qSize=qPath.size();
while(!pPath.empty() && !qPath.empty()){
if(pPath.peek()==qPath.peek()){
return pPath.peek();
}
if(pSize>qSize){
pPath.pop();
pSize--;
}else if(pSize<qSize){
qPath.pop();
qSize--;
}else{
pPath.pop();
qPath.pop();
pSize--;
qSize--;
}
}
return null;
}
}
- 同样的,受情况二启发:
- 如果知道一个结点在其子树中的位置,也能找到公共祖先;
代码如下 :
class Solution {
boolean isNodeInTree(TreeNode root,TreeNode node){
if(root==null || node ==null){
return false;
}
if(root==node){
return true;
}
if(isNodeInTree(root.left,node)){
return true;
}
return isNodeInTree(root.right,node);
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null){
return null;
}
if(p == root|| q == root){
return root;
}
boolean ispInLeft=false;
boolean ispInRight=false;
boolean isqInLeft=false;
boolean isqInRight=false;
if(isNodeInTree(root.left,p)){
ispInLeft=true;
ispInRight=false;
}else{
ispInLeft=false;
ispInRight=true;
}
if(isNodeInTree(root.left,q)){
isqInLeft=true;
isqInRight=false;
}else{
isqInLeft=false;
isqInRight=true;
}
if(ispInLeft && isqInLeft){
return lowestCommonAncestor(root.left,p,q);
}else if(ispInRight && isqInRight){
return lowestCommonAncestor(root.right,p,q);
}else{
return root;
}
}
}
|