面試題7: 重建二叉樹---Android端實現方式

題目:

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

分析

1. 前序遍歷和中序遍歷的過程要明白(根節點的輸出次序,前序:根-左-右; 中序:左-根-右)

2. 對於每個節點都可理解爲其有左子樹和右子樹,即使爲空

3. 遞歸形式處理

代碼實現 : 代碼部分含有註釋可自行理解

    /**
     * 根據前序遍歷和中序遍歷重新構建二叉樹
     *
     * @param DLRList  前序遍歷數組
     * @param startDLR 前序數組的開始位置
     * @param endDLR   前序數組的結束位置
     * @param LDRList  中序遍歷數組
     * @param startLDR 中序數組的開始位置
     * @param endLDR   中序數組的結束位置
     * @return 返回當前二叉樹的根節點
     */
    private TreeNode getRoot(int[] DLRList, int startDLR, int endDLR,
                             int[] LDRList, int startLDR, int endLDR) {
        if (DLRList == null || LDRList == null) {
            // 如果前序數組和中序數組都不存在,則返回空
            return null;
        }
        // 定義二叉樹實體時value值設爲了String,所以在這需要轉換一下
        TreeNode rootNode = new TreeNode(String.valueOf(DLRList[startDLR]));
        // 定義左子樹
        TreeNode leftNode = null;
        // 定義右子樹
        TreeNode rightNode = null;
        if (startDLR == endDLR && startLDR == endLDR) {

            /**
             *  如果前序數組的開始位置等於結束位置並且中序數組的開始位置等於結束位置,
             *  則直接返回這個節點即可(無其他的左子樹或者右子樹)
             */
            return rootNode;
        }
        /**
         * 遍歷中序數組,起始位置爲中序的起始位置(startLDR),得到當前節點在中序數組
         * 中的位置,以便統計左子樹節點數量和右子樹節點數量
         */
        int rootLocation = startLDR;
        for (; rootLocation < LDRList.length; rootLocation++) {
            /**
             * 如果當前前序數組的第一個節點值等於中序數組中的某一值
             * 則判定當前位置rootLocation即爲中序中根節點的位置
             */
            if (DLRList[startDLR] == LDRList[rootLocation]) {
                break;
            }
        }

        // 根據中序數組中的節點位置計算,當前節點的左子樹的數量
        int leftLength = rootLocation - startLDR;
        // 根據中序數組中的節點位置計算,當前節點的右子樹的數量
        int rightLenth = endLDR - rootLocation;
        if (leftLength > 0) {
            /**
             * 如果有左子樹,則進入遞歸模式
             *  注意的是前序數組和中序數組不變,變化的是各個數組的起始位置
             *  前序數組: DLRList, 開始位置 startDLR + 1,
             *  結束位置:(前序數組中左子樹結束位置)startDLR + leftLength
             *  中序數組:LDRList, 開始位置 startLDR,
             *  結束位置:(中序中左子樹的結束位置) rootLocation - 1
             */
            leftNode = getRoot(DLRList, startDLR + 1, startDLR + leftLength,
                    LDRList, startLDR, rootLocation - 1);
            rootNode.setLeft(leftNode);
        }
        if (rightLenth > 0) {
            /**
             * 如果有右子樹,則進入遞歸模式
             *  注意的是前序數組和中序數組不變,變化的是各個數組的起始位置
             *  前序數組: DLRList,
             *  開始位置:(前序中右子樹的開始位置) startDLR + leftLength + 1,
             *  結束位置:(前序數組中的末尾位置)endDLR
             *  中序數組:LDRList,
             *  開始位置:(中序中右子樹的開始位置)rootLocation + 1,
             *  結束位置:(中序中右子樹的結束位置) endLDR
             */
            rightNode = getRoot(DLRList, startDLR + leftLength + 1, endDLR,
                    LDRList, rootLocation + 1, endLDR);
            rootNode.setRight(rightNode);
        }
        // 返回生成的節點
        return rootNode;

    }

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章