剑指offer 树

二叉树

完全二叉树

二叉搜索树

AVL树

红黑树

Trie树


遍历

1.1 题目(面试题23):分层打印二叉树

解法一:广度优先,借助队列数据结构

public class Solution {  
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {  
        ArrayList<Integer> array=new ArrayList<Integer>();  
        if(root==null)  
            return array;  
        Queue<TreeNode> q=new LinkedList<TreeNode>();  
        q.offer(root);  
        while(!q.isEmpty()){  
            TreeNode temp=q.poll();  
            array.add(temp.val);  
            if(temp.left!=null){  
                q.offer(temp.left);  
            }  
            if(temp.right!=null){  
                q.offer(temp.right);  
            }  
        }  
        return array;  
    }  
}  

相关题目

题目1:分层打印成多行

public class Solution {  
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {  
        ArrayList<ArrayList<Integer> > result=new ArrayList<ArrayList<Integer> > ();  
        if(pRoot==null)  
            return result;  
          
        Queue<TreeNode> q= new LinkedList<TreeNode>();         
        q.offer(pRoot);        
          
        while(!q.isEmpty()){  
            int start=0;  
            int end=q.size();  
            ArrayList<Integer> temp=new ArrayList<Integer>();  
             
            while(start<end){  
                TreeNode node=q.poll();  
                temp.add(node.val);  
                if(node.left!=null)  
                    q.offer(node.left);  
                if(node.right!=null)  
                    q.offer(node.right);  
                start++;  
            }  
            result.add(temp);  
        }  
        return result;  
    }       
}  
题目2:之字形打印二叉树
import java.util.ArrayList;  
import java.util.LinkedList;  
import java.util.Queue;  
   
public class Solution {  
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {  
        ArrayList<ArrayList<Integer> > result=new ArrayList<ArrayList<Integer> >();  
        if(pRoot==null)  
            return result;  
           
        Queue<TreeNode> q=new LinkedList<TreeNode>();  
        q.offer(pRoot);  
        int count=1;  
        while(!q.isEmpty()){  
            int start=0;  
            int end=q.size();  
            ArrayList<Integer> temp= new ArrayList<Integer>();  
            while(start<end){  
                TreeNode node=q.poll();  
                temp.add(node.val);  
                if(node.left!=null)  
                    q.offer(node.left);  
                if(node.right!=null)  
                    q.offer(node.right);           
                start++;  
            }  
            if(count%2==1)  
                result.add(temp);  
            else{  
                result.add(reverse(temp));  
            }  
            count++;  
        }  
        return result;  
    }  
       
    private  ArrayList<Integer> reverse( ArrayList<Integer> temp){  
         ArrayList<Integer> result=new ArrayList<Integer>();  
         for(int i=temp.size()-1;i>=0;i--){  
             result.add(temp.get(i));             
         }  
         return result;  
    }     
}  

1.2  题目(面试题6):重建二叉树

解法一:递归,前序序列和中序序列或者后序序列和中序序列

import java.util.Arrays;
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if(pre.length!=in.length || pre==null || in==null)
            return null;
        if(pre.length==0 && in.length==0)
            return null;
         
        TreeNode root=new TreeNode(pre[0]);
        if(in.length==1)
            return root;
        int i=0;
        for(;i<in.length;i++){
            if(in[i]==root.val)
                break;
        }       
        if(i>0)
            root.left=reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
        if(i<in.length-1)
            root.right=reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
        return root;
    }   
}

1.3 题目(面试题24):二叉搜索树的后续遍历序列

import java.util.Arrays;    
public class Solution {    
    public boolean VerifySquenceOfBST(int [] sequence) {    
        int len=sequence.length;    
        if(len==0 || sequence==null)    
            return false;    
        int root=sequence[len-1];            
        int i=0;    
        for(;i<len-1;i++){    
            if(sequence[i]>root)    
                break;    
        }    
        int j=i;    
        for(;j<len-1;j++){    
            if(sequence[j]<root)    
                return false;    
        }    
        boolean left=true;    
        boolean right=true;    
        if(i>0){    
            left=VerifySquenceOfBST(Arrays.copyOfRange(sequence, 0, i));    
        }    
        if(i<sequence.length-1)    
            right=VerifySquenceOfBST(Arrays.copyOfRange(sequence, i, sequence.length-1));    
        return (left && right);    
    }    
}    
相关题目:
输入一个数组,判断该数组是不是某二叉搜索树的前序遍历结果

1.4 题目(面试题58):二叉树的下一个结点

1.5 题目(面试题64):二叉搜索树的第K个结点

解法一:前序序列

public class Solution {  
    int k;  
    TreeNode KthNode(TreeNode pRoot, int k)  
    {     
        if(pRoot==null || k==0)  
            return null;  
        this.k=k;         
        return KthNodeRec(pRoot);  
    }  
    TreeNode KthNodeRec(TreeNode pRoot){  
        TreeNode target=null;  
        if(pRoot.left!=null)  
            target=KthNode(pRoot.left,k);  
        if(target==null){  
            if(k==1)  
                return target=pRoot;  
            k--;  
        }  
        if(target==null && pRoot.right!=null)  
            target=KthNode(pRoot.right,k);  
        return target;  
    }  
}  

查找

2.1 题目(面试题18):树的子结构

解法一:前序遍历两个树,然后判断是否包含,空间复杂度是O(m+n);

import java.util.ArrayList;  
public class Solution {  
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {  
            if((root1==null)||(root2==null))  
                return false;  
            ArrayList<Integer> array1=new ArrayList<Integer>();  
               
            ArrayList<Integer> array2=new ArrayList<Integer>();  
               
            array1=preOrder(root1);  
            array2=preOrder(root2);  
               
            if(array1.containsAll(array2))  
                return true;  
            return false;  
    }  
       
    private ArrayList<Integer> preOrder(TreeNode root){  
            if(root==null)  
                return null;  
            ArrayList<Integer> temp=new ArrayList<Integer>();  
            temp.add(root.val);  
            ArrayList<Integer> left=preOrder(root.left);  
            if(left!=null)  
                temp.addAll(left);  
            ArrayList<Integer> right=preOrder(root.right);  
            if(right!=null)  
                temp.addAll(right);  
            return temp;  
    }  
}  
解法二:递归解法,空间复杂度低

public class Solution {  
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {  
        boolean result=false;  
        if(root1!=null && root2!=null){  
            if(root1.val==root2.val){  
                result=DoTree1HasTree2(root1,root2);  
            }  
            if(!result){  
                result=HasSubtree(root1.left,root2);  
            }  
            if(!result){  
                result=HasSubtree(root1.right,root2);  
            }  
        }  
        return result;  
    }  
    private boolean DoTree1HasTree2(TreeNode root1,TreeNode root2){  
        if(root2==null){  
            return true;  
        }  
        if(root1==null)  
            return false;  
        if(root1.val!=root2.val){  
            return false;  
        }  
        return DoTree1HasTree2(root1.left,root2.left)&&DoTree1HasTree2(root1.right,root2.right);  
    }  
}  
2.2 题目(面试题19):二叉树的镜像
解法一:递归实现

public class Solution {  
    public void Mirror(TreeNode root) {  
        if(root==null)  
            return;  
        if(root.left==null && root.right==null)  
            return;  
        else {  
            TreeNode temp=root.right;  
            root.right=root.left;  
            root.left=temp;  
            Mirror(root.left);  
            Mirror(root.right);  
        }  
    }  
}  

相关题目:

题目1:对称二叉树,二叉树和它的镜像一样则为对称

public class Solution {  
    boolean isSymmetrical(TreeNode pRoot)  
    {  
        if(pRoot==null)  
            return true;  
        return rec(pRoot.left,pRoot.right);  
    }  
    private boolean rec(TreeNode left, TreeNode right){  
        if(left==null && right==null)  
            return true;  
        else if(left==null || right==null)  
            return false;  
        else if(left.val!=right.val)  
            return false;  
       return rec(left.right, right.left) && rec(left.left, right.right);  
    }  
}  

2.3 题目(面试题25):二叉树中和为某一值的路径

public class Solution {  
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {  
        ArrayList<ArrayList<Integer>> pathlist=new ArrayList<ArrayList<Integer>>();  
        if(root==null)  
            return pathlist;  
        Stack<Integer> stack=new Stack<Integer>();  
        FindPath(root,target,stack,pathlist);  
        return pathlist;  
    }  
      
    private void FindPath(TreeNode root,int target,Stack<Integer> path,ArrayList<ArrayList<Integer>> pathlist){  
        if(root==null)  
            return;  
        if(root.left==null && root.right==null){  
            if(root.val==target){  
                ArrayList<Integer> list= new ArrayList<Integer>();  
                for(int p:path){  
                    list.add(new Integer(p));  
                }  
                list.add(new Integer(root.val));  
                pathlist.add(list);  
            }  
        }  
        else{  
            path.push(new Integer(root.val));  
            FindPath(root.left,target-root.val,path,pathlist);  
            FindPath(root.right,target-root.val,path,pathlist);  
            path.pop();  
        }  
    }  
}  

2.4 题目(面试题39):二叉树的深度,最长的路径

public class Solution {
    public int TreeDepth(TreeNode root) {
        if(root==null)
            return 0;
        TreeNode left=root.left;
        TreeNode right=root.right;
        return Math.max(1+TreeDepth(left),1+TreeDepth(right));
    }
}
相关题目:

题目1:平衡二叉树
解法一:基于二叉树的深度递归解法;

解法二:基于后序遍历的解法;

2.5 题目(面试题50):最低公共祖先

2.6 题目(面试题27):二叉搜索树与双向链表
方法二:递归版  
解题思路:  
1.将左子树构造成双链表,并返回链表头节点。  
2.定位至左子树双链表最后一个节点。  
3.如果左子树链表不为空的话,将当前root追加到左子树链表。  
4.将右子树构造成双链表,并返回链表头节点。  
5.如果右子树链表不为空的话,将该链表追加到root节点之后。  
6.根据左子树链表是否为空确定返回的节点。  
    public TreeNode Convert(TreeNode root) {  
        if(root==null)  
            return null;  
        if(root.left==null&&root.right==null)  
            return root;  
        // 1.将左子树构造成双链表,并返回链表头节点  
        TreeNode left = Convert(root.left);  
        TreeNode p = left;  
        // 2.定位至左子树双链表最后一个节点  
        while(p!=null&&p.right!=null){  
            p = p.right;  
        }  
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表  
        if(left!=null){  
            p.right = root;  
            root.left = p;  
        }  
        // 4.将右子树构造成双链表,并返回链表头节点  
        TreeNode right = Convert(root.right);  
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后  
        if(right!=null){  
            right.left = root;  
            root.right = right;  
        }  
        return left!=null?left:root;         
    }  
方法三:改进递归版  
解题思路:  
思路与方法二中的递归版一致,仅对第2点中的定位作了修改,新增一个全局变量记录左子树的最后一个节点。  
    // 记录子树链表的最后一个节点,终结点只可能为只含左子树的非叶节点与叶节点  
    protected TreeNode leftLast = null;  
    public TreeNode Convert(TreeNode root) {  
        if(root==null)  
            return null;  
        if(root.left==null&&root.right==null){  
            leftLast = root;// 最后的一个节点可能为最右侧的叶节点  
            return root;  
        }  
        // 1.将左子树构造成双链表,并返回链表头节点  
        TreeNode left = Convert(root.left);  
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表  
        if(left!=null){  
            leftLast.right = root;  
            root.left = leftLast;  
        }  
        leftLast = root;// 当根节点只含左子树时,则该根节点为最后一个节点  
        // 4.将右子树构造成双链表,并返回链表头节点  
        TreeNode right = Convert(root.right);  
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后  
        if(right!=null){  
            right.left = root;  
            root.right = right;  
        }  
        return left!=null?left:root;         
    }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值