劍指offer-重建二叉樹-Java版題解

概述

本題來自牛客網-劍指offer在線測評

題目描述

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

原理與實現

思想:二分、遞歸

關鍵是:利用前序序列根節點在前找到根節點,用根節點去中序序列劃分成兩部分,左部分是左子樹,右部分是右子樹。再利用子樹長度去前序序列把前序序列中的左右子樹找出來,同時可以找出根節點。遞歸進行此步驟,如果子樹長度爲0,則不需要生成子問題。

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }
}

/**
 * 關鍵是:利用前序序列根節點在前找到根節點,用根節點去中序序列劃分成兩部分,左部分是左子樹,右部分是右子樹。再利用子樹長度去前序序列把前序序列中的左右子樹找出來,同時可以找出根節點。遞歸進行此步驟,如果子樹長度爲0,則不需要生成子問題。
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        TreeNode root = new TreeNode(pre[0]);
        build(root, pre, 0, pre.length, in, 0, in.length);
        return root;
    }

    /**
     * 遞歸和二分思想,將問題不斷劃分,直到問題容易解決。
     * 做法是:對於一個根節點,先去中序序列中找到根節點的值所在位置,利用這個位置分成2部分,左部分的中序序列長度即爲前序序列中左部分的中序序列長度,右部分亦然。
     * 然後開始生成子問題,如果序列長度爲0則不需要生成子問題。否則:利用前序序列第一個元素爲根節點的性質生成根節點,然後構造子問題。
     * @param root 根節點
     * @param pre 前序序列 範圍是[pleft,pright)
     * @param in 中序序列 範圍是[ileft,iright)
     */
    public void build(TreeNode root, int[] pre, int pleft, int pright, int[] in, int ileft, int iright) {
        int i;
        for (i = ileft; i < iright; i++) {
            if (in[i] == root.val) {//從中序序列尋找根節點的位置
                break;
            }
        }
        int t = i - ileft;//左子樹長度
        if (t > 0) {//左子樹長度爲0時不必生成子問題
            root.left = new TreeNode(pre[pleft + 1]);
            build(root.left, pre, pleft + 1, pleft + 1 + t, in, ileft, i);
        }

        if (pright - pleft - 1 - t > 0) {//右子樹長度爲0時不必生成子問題
            root.right = new TreeNode(pre[pleft + 1 + t]);
            build(root.right, pre, pleft + 1 + t, pright, in, i + 1, iright);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章