leetcode-構造二叉樹(分析與實現)

題型一:105. 從前序與中序遍歷序列構造二叉樹

根據一棵樹的前序遍歷與中序遍歷構造二叉樹。

注意:
你可以假設樹中沒有重複的元素。

例如,給出

前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]
返回如下的二叉樹:

    3
   / \
  9  20
    /  \
   15   7

思路分析:

1、從前序遍歷結果中找到樹根節點的值: pretorder[index];

2、在中序遍歷結果中找到根節點的位置rootIndex,將中序遍歷分成兩部分:

①左子樹的節點數據範圍:[ left ,rootIndex )

②左子樹的節點數據範圍:[rootIndex+1,right )

3、創建根節點:

①遞歸創建根的左子樹;

②遞歸創建根的右子樹;

實現代碼:

class Solution {
    // preorder:前序遍歷結果
    // inorder:中序遍歷結果
    // [left,right):標記在中序遍歷中節點的位置範圍

    int index = 0;
    private TreeNode reBuildTree(int[] preorder, int[] inorder, int left, int right){
        if(index >= preorder.length || left>=right){
            return null;
        }
        //前序找根節點 preorder[index]
       
       //在中序遍歷中找根的位置
       //確認左右子樹的區間
       int rootindex = left;
       while(rootindex<right){
           if(inorder[rootindex]==preorder[index]){
               break;  //如果找到了,直接退出
           }   
           rootindex++; //如果沒找到,往後繼續走
       }

        //創建根節點
       TreeNode root = new TreeNode(preorder[index]);

         ++index;//根的位置還包括左子樹/右子樹的根 所以需要移動

        //遞歸調用左子樹[left,rootindex):
        root.left = reBuildTree(preorder,inorder,left,rootindex);
        //遞歸調用右子樹[rootindex+1,right):
        root.right = reBuildTree(preorder,inorder,rootindex+1,right);
        return root;
    }
    public TreeNode buildTree(int[] preorder, int[] inorder) {
      return reBuildTree(preorder, inorder,0,inorder.length);
    }
}

【注意】:
關於前序裏找根節點(index)的一個知識點:

在不斷遞歸的過程中,index的值實際會發生變化,需要再遞歸中對index的改變帶出到上一層遞歸中,但是參數index是按照int的方式傳遞的,在裏層的遞歸中對index是按照int的方式傳遞的,在裏層對Index所做的修改並不能夠體現到外層遞歸中。

<解決辦法>

1、參數int直接使用Integer方式傳遞 ------錯誤
Integer 中的內容是無法修改的,如果修改,實際虛擬機會重新創建一個index。

2、將index重新封裝一種新的類型------正確(沒有意義)

3、將index作爲類的成員變量------正確(如上代碼: int index = 0)
在這裏插入圖片描述

題型二:106. 從中序與後序遍歷序列構造二叉樹

根據一棵樹的中序遍歷與後序遍歷構造二叉樹。

注意:
你可以假設樹中沒有重複的元素。

例如,給出

中序遍歷 inorder = [9,3,15,20,7]
後序遍歷 postorder = [9,15,7,20,3]
返回如下的二叉樹:

    3
   / \
  9  20
    /  \
   15   7

思路分析:

1、從後序遍歷結果中找到樹根節點的值: postorder[index];

2、在中序遍歷結果中找到根節點的位置rootIndex,將中序遍歷分成兩部分:

①左子樹的節點數據範圍:[ left ,rootIndex )

②左子樹的節點數據範圍:[rootIndex+1,right )

3、創建根節點:

①遞歸創建根的右子樹;

②遞歸創建根的左子樹;

實現代碼:

class Solution {
     int index = 0 ; 
     private TreeNode buildTree(int[] inorder, int[] postorder,int left, int right) {
      if(index<0 || left>=right){
          return null;
      }
      int rootIndex = left;
      while(rootIndex<right){
          if(inorder[rootIndex]==postorder[index]){
              break;
          }
          rootIndex++;//沒找到 繼續往後找
      }
      TreeNode root = new TreeNode(postorder[index]);
      --index;//後序遍歷根節點在最後 所以需要向前

      //遞歸右子樹
       root.right=buildTree(inorder,postorder,rootIndex+1,right);

      //遞歸左子樹
       root.left=buildTree(inorder,postorder,left,rootIndex);
      return root;
    }

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        index=postorder.length-1;
        return buildTree(inorder,postorder,0,postorder.length);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章