Java 重建二叉樹 根據前序中序重建二叉樹


題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。

解題所需的知識

二叉樹的遍歷

這個先中后,是根據何時遍歷根節點命名的,左的優先級大於后,比如先序就先遍歷根結點,再遍歷左節點,最后遍歷右節點,中序同理,先左中根最后右,后序,先左再右后根。

二叉樹的先序遍歷

​ 來! 根據上面的的順序我們來走一遍,先根再左最后右。

​ 首先,顯而意見,1是根節點

​ 那么現在往左走,發現 2,4,7 也是一棵二叉樹,他也是二叉樹,我們可不能區別對待,所以理應也滿足先序遍歷,先根再左最后右。那么2就是這顆小二叉樹的根節點啦。

​ 找到了小二叉樹的根節點,按照先序再走左,發現4,7也是一棵二叉樹,這顆小小二叉樹也得滿足先序哦,4為根節點,再走左,發現左沒了,還記得先序得遍歷規則嘛 先根再左后右,左沒了那就輪到右啦,所以應該走7了,走完7以后,4,7這棵小小小二叉樹算是走完了,走完之后該走2,4,7這顆小二叉樹的右節點了,依次類推哦。

先序遍歷為 1,2,4,7,3,5,6,8

二叉樹的中序遍歷

同上 4,7,2,1,5,3,8,6

二叉樹的后序遍歷

同上 7,4,2,5,8,6,3,1

根據先序,中序構建二叉樹

​ 舉例 前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}

​ 首先,先序先遍歷根節點,那么1顯然就是最上面的那個根節點,中序是中間遍歷根節點,那么顯然可以得出如下圖

​ 那么繼續去前序得數組中找,發現4,7,2最先出現的是2,那顯然2是4,7,2的根結點,去中序找,4,7都在2之前,那顯然都是2的左子樹。

​ 再去先序找,發現4先出現,那么4就是4,7的根節點,去中序找,發現7在4的右邊,說明是右子樹。

​ 右子樹依次類推。。。。。

代碼實現

​ 人用迭代,神用遞歸

​ 我們用遞歸的思想,首先先序{1,2,4,7,3,5,6,8},中序{4,7,2,1,5,3,8,6},那么我們找到1是根節點:

​ 那么現在我們把4,7,2當成一棵二叉樹,那么先序從上面知道是{2,4,7} 中序根據上面也知道是{4,7,2},那接下來跟我們找出1是根節點然后分左右是不是一模一樣,只不過先序的數組和中序的數組變了

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
   //前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}
    public TreeNode reConstructBinaryTree(int[] pre, int[] in) {

        int len = pre.length;

        TreeNode root = new TreeNode(pre[0]);
        //說明只剩下一個了,表示葉子節點,遞歸可以退出了
        if (pre.length == 1) {
            root.left = null;
            root.right = null;
            return root;
        }

        //中間值 在{4,7,2,1,5,3,8,6} 這個中間值第一次應該是3
        int flag = 0;
        for (int i = 0; i < len; i++) {
            //在中序中找到
            if (pre[0] == in[i]) {
                flag = i;
                break;
            }
        }
        if (flag > 0) {
            //左子樹的先序
            int[] leftPre = new int[flag];
            //左子樹的中序
            int[] leftIn = new int[flag];
            for (int j = 0; j < flag; j++) {
                leftPre[j] = pre[j + 1];
            }
            for (int j = 0; j < flag; j++) {
                leftIn[j] = in[j];
            }
            //左子樹遞歸
            root.left = reConstructBinaryTree(leftPre, leftIn);
        } else {
            root.left = null;
        }
        if (pre.length - flag - 1 > 0) {
            //右子樹的先序,長度為 總-根-左子樹
            int[] rightPre = new int[pre.length - 1 - flag];
            //右子樹的中序
            int[] rightIn = new int[pre.length - 1 - flag];

            for (int j = flag + 1; j < len; j++) {
                //右子樹中序,為什么要j-flag-1呢 因為我的rightIn要從0開始 而j是k+1開始的 ,所以很尷尬,只能用j-flag-1
                rightIn[j - flag - 1] = in[j];

                rightPre[j - flag - 1] = pre[j];
            }

            root.right = reConstructBinaryTree(rightPre, rightIn);
        } else {
            root.right = null;
        }

        return root;

    }
 
}


免責聲明!

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



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