面試常見二叉樹算法題集錦-Java實現


1.求二叉樹的深度或者說最大深度
/*
***1.求二叉樹的深度或者說最大深度
 */
public static int maxDepth(TreeNode root){
    if(root==null) return 0;
    int left=maxDepth(root.left);
    int right=maxDepth(root.right);
    return Math.max(left,right)+1;
}

2.求二叉樹的最小深度
/*
***2.求二叉樹的最小深度
 */
public static int MinDepth(TreeNode root){
    if(root==null) return 0;
    if(root.left==null&&root.right==null) return 1;
    int left=MinDepth(root.left);
    int right=MinDepth(root.right);
    if(root.left==null||root.right==null)  return Math.max(left,right)+1;
   return Math.min(left,right)+1;
}

3.求二叉樹中節點的個數
/*
***3.求二叉樹中節點的個數
 */
public static int nodeCount(TreeNode root){
    if(root==null) return 0;
    int left=nodeCount(root.left);
    int right=nodeCount(root.right);
    return left+right+1;
}

4.求二叉樹中葉子節點的個數
/*
***4.求二叉樹中葉子節點的個數
 */
public static int leafNodeCount(TreeNode root){
    if(root==null) return 0;
    if(root.left==null&&root.right==null) return 1;
    int left=leafNodeCount(root.left);
    int right=leafNodeCount(root.right);
    return left+right;
}

5.求二叉樹中第k層節點的個數
/*
***5.求二叉樹中第k層節點的個數
 */
public static int KlevelCount(TreeNode root,int k){
    if(root==null||k<1) return 0;
    if(k==1) return 1;  //K=1的那一層總是我們想找的那一層
    int left=KlevelCount(root.left,k-1);
    int right=KlevelCount(root.right,k-1);
    return left+right;      //或者可以用層次遍歷的方法
}


6.判斷二叉樹是否為平衡二叉樹
/*
***6.判斷二叉樹是否為平衡二叉樹  平衡二叉樹的左右子樹高度差的不超過1
 */
public static boolean isBalancedTree(TreeNode root){
    if(root==null) return false;
    return isBalancedhelper(root)!=-1;
}
public static int isBalancedhelper(TreeNode root){
    if(root==null) return 0;
    int left=isBalancedhelper(root.left);
    int right=isBalancedhelper(root.right);
    if(Math.abs(left-right)>1) return -1;   //返回-1說明不平衡
    return Math.max(left,right)+1;
}

7.判斷二叉樹是否是二叉完全樹
/*
***7.判斷二叉樹是否是二叉完全樹
 */
public static boolean isCompleteTree(TreeNode root){
    if(root==null) return false;
    Queue<TreeNode> queue=new LinkedList<>();
    queue.add(root);
    boolean res=true;
    boolean hasNoChild=false;
    while(!queue.isEmpty()){
        TreeNode tmp=queue.remove();
        if(hasNoChild){    //hasNoChild=true說明在tmp節點之前有無右孩子的節點,這時tmp只能為葉子節點
            if(tmp.left!=null||tmp.right!=null) return false;
        }
        else{
            if(tmp.left!=null&&tmp.right!=null){
                queue.add(tmp.left);
                queue.add(tmp.right);
            }
            else if(tmp.left!=null&&tmp.right==null){
                queue.add(tmp.left);
                hasNoChild=true;
            }
            else if(tmp.left==null&&tmp.right!=null) return false;
            else hasNoChild=true;
        }
    }
    return res;
}

8.兩個二叉樹是否完全相同
/*
***8.兩個二叉樹是否完全相同
 */
public static boolean isSameTree(TreeNode root1,TreeNode root2){
    if(root1==null) return root2==null;
    if(root2==null) return false;
    if(root1.val!=root2.val) return false;
    return isSameTree(root1.left,root2.left)&&isSameTree(root1.right,root2.right);
}


9.兩個二叉樹是否為鏡像二叉樹
/*
***9.兩個二叉樹是否為鏡像二叉樹
 */
private static boolean isMirror(TreeNode root1,TreeNode root2){
    if(root1==null) return root2==null;   //如果是判斷某棵樹是不是鏡像的,令root2=root1即可
    if(root2==null) return false;
    if(root1.val!=root2.val) return false;
    return isMirror(root1.left,root2.right)&&isMirror(root1.right,root2.left);
}


10.翻轉二叉樹或者鏡像二叉樹
/*
***10.翻轉二叉樹或者鏡像二叉樹
 */
private static boolean mirrorTree(TreeNode root){
    if(root==null) return root;
    TreeNode left=mirrorTree(root.left);   //先把左右子樹都先翻轉
    TreeNode right=mirrorTree(root.right);
    root.left=right;                  //再把左右孩子節點反轉
    root.right=left;
    return root;
}

11.求兩個二叉樹節點的最低公共祖先節點
/*
***11.求兩個二叉樹節點的最低公共祖先節點
 */
private static TreeNode lastCommonParent(TreeNode root,TreeNode node1,TreeNode node2){
    if(!lastCommonParentHelper(root,node1)||!lastCommonParentHelper(root,node2)) return null;
    if(lastCommonParentHelper(root.left,node1)){  //node1在左子樹上
        //
        if(lastCommonParentHelper(root.left,node2)) return lastCommonParent(root.left,node1,node2); //去root的左子樹上看看
        else {
            return root;//否則,1.如果兩個節點分居root的兩個子樹,那么root就是最近父節點 2.node2是根節點或者右邊的節點,那么公共節點一定是root
        }
    }
    else if(lastCommonParentHelper(root.right,node1)){   //node1不在左子樹上,而在右子樹上
        //如果node2也在右子樹上,那么就去右子樹看看
        if(lastCommonParentHelper(root.right,node2)) return lastCommonParent(root.right,node1,node2);
        else{
            return root; //node2不在右子樹,那么可能在root或者左子樹,則root是最近根節點
        }
    }
    else return root;
}
private static boolean lastCommonParentHelper(TreeNode root,TreeNode node){  //判斷node是不是root的子結構
    if(root==null||node=null) return false;  //約定null不是任何樹的子樹
    if(root==node) return true;
    return lastCommonParentHelper(root.left,node)||lastCommonParentHelper(root.right,node);
}

12.二叉樹的前序遍歷 
/*
***12.二叉樹的前序遍歷   用ArrayList<Integer>存儲
 */
private static ArrayList<Integer> preOrder(TreeNode root){
    ArrayList<Integer> list=new ArrayList<>();
    preOrder1(root,list);
    //preOrder2(root,list)
    return list;
}
//先序遍歷的遞歸寫法
private static void preOrder1(TreeNode root,ArrayList<Integer> list){
    if(root==null) return ;
    list.add(root.val);
    preOrder1(root.left,list);
    preOrder1(root.right,list);
}
//先序遍歷的迭代寫法
private static void preOrder2(TreeNode root,ArrayList<Integer> list){
    if(root==null) return ;
    Stack<Integer> stack=new Stack<>();
    stack.push(root);
    while(!stack.isEmpty()){
        TreeNode tmp=stack.pop();
        list.add(tmp.val);
        if(tmp.right!=null) stack.push(tmp.right); //先把右節點入棧,這樣出棧的時候總是左節點先讀取
        if(tmp.left!=null) stack.push(tmp.left);
    }
    return ;
}

13.二叉樹的中序遍歷
/*
 ***13.二叉樹的中序遍歷   用ArrayList<Integer>存儲
 */
private static ArrayList<Integer> inOrder(TreeNode root){
    ArrayList<Integer> list=new ArrayList<>();
    inOrder1(root,list);
    //inOrder2(root,list)
    return list;
}
//中序遍歷的遞歸寫法
private static void inOrder1(TreeNode root,ArrayList<Integer> list){
    if(root==null) return ;
    inOrder1(root.left,list);
    list.add(root.val);
    inOrder1(root.right,list);
}
//中序遍歷的迭代寫法
private static void inOrder(TreeNode root,ArrayList<Integer> list){
    if(root==null) return ;
    Stack<Integer> stack=new Stack<>();
    TreeNode p=root;
    while(p!=null||!stack.isEmpty()){
        while(p!=null){
            stack.push(p);
            p=p.left;
        }
        p=stack.pop();
        list.add(p.val);
        p=p.right;
    }
    return ;
}

14.二叉樹的后序遍歷
/*
 ***14.二叉樹的后序遍歷   用ArrayList<Integer>存儲
 */
private static ArrayList<Integer> postOrder(TreeNode root){
    ArrayList<Integer> list=new ArrayList<>();
    postOrder1(root,list);
    //postOrder2(root,list)
    return list;
}
//先序遍歷的遞歸寫法
private static void postOrder1(TreeNode root,ArrayList<Integer> list){
    if(root==null) return ;
    postOrder1(root.left,list);
    postOrder1(root.right,list);
    list.add(root.val);
}
//后序遍歷的迭代寫法
private static void postOrder2(TreeNode root,ArrayList<Integer> list){
    if(root==null) return ;
    Stack<Integer> stack=new Stack<>();
    stack.push(root);
    while(!stack.isEmpty()){
        TreeNode tmp=stack.pop();
        list.add(tmp.val);
        if(tmp.left!=null) stack.push(tmp.left);  //先把左節點入棧,這樣出棧的時候總是右節點先讀取
        if(tmp.right!=null) stack.push(tmp.right);  //進組的順序為  根->右->左 正好和后續遍歷的順序相反
    }

    Collections.reverse(list);   //反轉list即可
    return ;
}

15.二叉樹的層次遍歷
/*
***15.二叉樹的層次遍歷
 */
private static ArrayList<ArrayList<Integer>> leverOrder(TreeNode root){
    ArrayList<ArrayList<Integer>> listAll=new ArrayList<>();
    if(root==null) return listAll;
    ArrayList<Integer> list=new ArrayList<Integer>();
    Queue<TreeNode> queue=new LinkedList<>();
    queue.add(root);
    int count=0,nextCount=1;
    while(!queue.isEmpty()){
        TreeNode tmp=queue.remove();
        list.add(tmp.val);
        count++;
        if(tmp.left!=null) queue.add(tmp.left);
        if(tmp.right!=null) queue.add(tmp.right);
        if(count==nextCount){
            count=0;
            nextCount=queue.size();
            listAll.add(new ArrayList<Integer>(list));
            list.clear();
        }
    }
    return listAll;
}

16.先序遍歷和中序遍歷構造二叉樹
/*
***16.先序遍歷和中序遍歷構造二叉樹
 */
private static TreeNode pre_in_BuildTree(int[] preorder,int[] inorder){
    if(preorder.length!=inorder.length) return null;
    return pre_in_BuildTreeHelper(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
private static TreeNode pre_in_BuildTreeHelper(int[] preorder,int preStart,int preEnd,int[] inorder,int inStart,int inEnd){
    if(preStart>preEnd) return null;
    TreeNode root=new TreeNode(preorder[preStart]);
    int index=inStart;
    while(inorder[index]!=root.val) index++;
    root.left=pre_in_BuildTreeHelper(preorder,preStart+1,preStart+index-inStart,inorder,inStart,index-1);
    root.right=pre_in_BuildTreeHelper(preorder,preStart+index-inStart+1,preEnd,inorder,index+1,inEnd);
    return root;
}


17.中序遍歷和后續遍歷構造二叉樹
/*
 ***17.中序遍歷和后續遍歷構造二叉樹
 */
private static TreeNode in_post_BuildTree(int[] inorder,int[] postorder){
    if(postorder.length!=inorder.length) return null;
    return in_post_BuildTreeHelper(inorder,0,inorder.length-1,postorder,0,postorder.length-1);
}
private static TreeNode in_post_BuildTreeHelper(int[] inorder,int inStart,int inEnd,int[] postorder,int postStart,int postEnd,){
    if(postStart>postEnd) return null;
    TreeNode root=new TreeNode(postorder[postEnd]);
    int index=inStart;
    while(inorder[index]!=root.val) index++;
    root.left=in_post_BuildTreeHelper(inorder,inStart,index-1,postorder,postStart,postStart+index-inStart-1);
    root.right=in_post_BuildTreeHelper(inorder,index+1,inEnd,postorder,postStart+index-inStart,postEnd-1);
    return root;
}

18.輸入一個二叉樹和一個整數,打印出從二叉樹根節點到葉子節點的路徑上所有節點值之和值等於輸入整數所有的路徑
/*
***18.輸入一個二叉樹和一個整數,打印出從二叉樹根節點到葉子節點的路徑上所有節點值之和值等於輸入整數所有的路徑
 */
private static ArrayList<ArrayList<Integer>> findPath(TreeNode root, int target){
    ArrayList<ArrayList<Integer>> listAll=new ArrayList<>();
    if(root==null) return listAll;
    ArrayList<Integer> list=new ArrayList<>();
    findPathHelper(root,target,listAll,list);
    return listAll;
}
private static void findPathHelper(TreeNode root, int target,ArrayList<ArrayList<Integer>> listAll,ArrayList<Integer> list){
    if(root==null) return ;
    list.add(root.val);
    if(root.left==null&&root.right==null&&target==root.val) listAll.add(new ArrayList<Integer>(list));
    findPathHelper(root.left,target-root.val,listAll,list);
    findPathHelper(root.right,target-root.val,listAll,list);
    list.remove(list.size()-1);
}

19.二叉搜索樹的第k小的節點(中序遍歷解決)
/*
***19.二叉搜索樹的第k小的節點(中序遍歷解決)
 */
private static TreeNode KthNode(TreeNode pRoot, int k)
{
    if(pRoot==null||k==0) return null;
    Stack<TreeNode> stack=new Stack<>();
    int count=0;
    TreeNode p=pRoot;
    while(p!=null||!stack.isEmpty()){
        while(p!=null){
            stack.push(p);
            p=p.left;
        }
        p=stack.pop();
        if(++count==k) return p;
        p=p.right;
    }
    return null;
}

20.輸入一個整數數組,判斷該數組是不是某二叉搜索樹的后序遍歷的結果。
/*
***20.輸入一個整數數組,判斷該數組是不是某二叉搜索樹的后序遍歷的結果。
 */
private static boolean VerifySquenceOfBST(int [] sequence) {
    if(sequence.length==0) return false;
    if(sequence.length==1) return true;
    return isBST(sequence,0,sequence.length-1);
}
private static boolean isBST(int[] num,int start,int end){
    if(start>=end) return true;
    int i=start;
    while(num[i]<num[end]) i++;
    for(int j=i;j<end;j++){
        if(num[j]<num[end]) return false;
    }
    return isBST(num,start,i-1)&&isBST(num,i,end-1);
}

21.給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。
/*
***21.給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。
***注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指針。
 */
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;  //指向其父節點
    TreeLinkNode(int val) {
        this.val = val;
    }
}
private static 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){
        if(pNode.next.left==pNode) return pNode.next;
        pNode=pNode.next;
    }
    return null;
}

22.判斷二叉樹是不是二叉搜索樹
/*
***22.判斷二叉樹是不是二叉搜索樹
   */
private static boolean isBST(TreeNode root){
    if(root==null) return false; //約定空樹不是二叉搜索樹
    return isBSThelper(root,Long.MIN_VALUE,Long.MAX_VALUE);
}
private static boolean isBSThelper(TreeNode root,long low,long high){
   if(root==null) return true;
   if(root.val<low||root.val>high) return false;//這里加不加等號取決於具體的二叉搜索樹定義,如果不允許相等的值存在則加上等號
   return isBSThelper(root.left,low,root.val)&&isBSThelper(root.right,root.val,high);
}


23.求二叉樹中節點的最大距離
/*
***23.求二叉樹中節點的最大距離
 */
 private static int maxDistance=Integer.MIN_VALUE;
    private static int getMaxDistance(TreeNode root){
        if(root==null) return 0;
        getMaxDistanceHelper(root);
        return maxDistance;
    }
private static int getMaxDistanceHelper(TreeNode root){
    if(root==null) return -1;
    int leftMaxDistance=getMaxDistanceHelper(root.left);
    int rightMaxDistance=getMaxDistanceHelper(root.right);
    int temptMaxDistance=leftMaxDistance+rightMaxDistance+2;
    if(temptMaxDistance>maxDistance) maxDistance=temptMaxDistance;
    return leftMaxDistance>rightMaxDistance?leftMaxDistance+1:rightMaxDistance+1;
}


24.合並兩棵二叉樹

/*
 ***24.合並兩棵二叉樹
 */
private static TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
    if(t2==null) return t1;
    if(t1==null) return t2;
    TreeNode root=new TreeNode(t1.val+t2.val);
    root.left=mergeTrees(t1.left,t2.left);
    root.right=mergeTrees(t1.right,t2.right);
    return root;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM