簡體   English   中英

Java / C / C ++:在不重建樹的情況下找到二叉樹最短路徑的葉子(幫助進行遞歸)

[英]Java/C/C++:find leaf of the shortest path of a binary tree without reconstructing tree (help with recursion)

我有一個二進制樹(不是BSD)的以下2個序列:
訂單中:3 2 1 4 5 7 6
后期訂購:3 1 2 5 6 7 4

我們知道postOrder中的最后一個元素是根,因此我們將根定位在inOrder序列上,然后像這樣細分:
-根左側的所有元素都進入左側子樹
-根右邊的所有元素都將移到右邊的子樹。此外,它們在樹中出現的順序由postOrder給出。

對於此示例:4 =根

左子樹(按順序):3 2 1右子樹(按順序):5 7 6
左子樹(后置):3 1 2右子樹(后置):5 6 7

我們以遞歸方式進行同樣的操作,因此...我認為重建的樹是:

              4
         2         7
      3     1    5   6

我只想返回通向最短路徑(和)的葉子; 我不需要重建樹然后遍歷它並做一條最短的路徑。 我只需要使我達到最低金額的葉子即可。 在這種情況下,我有4種可能的路徑:4 + 2 + 3 = 9 || 4 + 2 + 1 = 7 || 4 + 7 + 5 = 16 || 4 + 7 + 6 = 17,因為7越小,我必須返回葉子1。

我認為算法非常簡單,但是我很難為其編寫遞歸代碼...

有人可以幫助菜鳥嗎? C,Java,C ++或Python ...我不在乎

如果您對普通的二叉樹有序遍歷和后序遍歷,那么如果您可以有重復的值,它們甚至都不會唯一地定義樹,例如,兩個后序遍歷的序列[1,1,1] order和in-order可以是以下樹之一:

    1      1
   1 1      1
             1

最小和路徑在左邊為2,右邊為3。

因此,假設所有值都是不同的。

假設您有一個后置遍歷列表[x1,x2,...,xn]和有序遍歷列表[y1,...,yk,...,yn],以便xn == yk。 因為xn是樹的根,所以現在您知道[y1,...,yk-1]是左子樹,[yk + 1,...,yn]是右子樹。 然后,左子樹也用[x1,...,xk-1]表示,因為左子樹的大小顯然是恆定的,因此您也可以在xk-1和xk之間划分后遍歷列表。

例如,這是一個沒有任何特定順序的非平衡二叉樹:

     5
   3   6
  9 2   1
       4

順序遍歷為[9,3,2,5,6,4,1],后順序為[9,2,3,4,1,6,5]。

該樹將以如下方式遞歸構造:取后遍歷的最后一個元素(5); 按順序划分為[9,3,2]和[6,4,1](在元素5的位置划分); 因此,僅根據子樹的已知大小,將后遍歷列表分為[9,2,3]和[4,1,6]。 然后遞歸繼續; 讓我們看一下[6,4,1]樹,因為它不平衡:

根是6; 在順序[6,4,1]中,左子樹為空,右側為[4,1],因此從后順序列表[4,1,6]中,您將[]設為左側-子樹,[4,1]作為右子樹; 從那里得到根節點1,然后發現[4]是左邊的子樹。 從中得到形狀

  6
   1
  4

如預期的。

現在,由於樹沒有排序,沒有平衡等,您可以嘗試編寫遞歸代碼來處理查詢。 在C ++中:

const int size = 7; /* Size of the tree */

/* Given arrays */
int post_order[size] = { 3 , 1 , 2 , 5 , 6 , 7 , 4 };
int in_order[size] = { 3 , 2 , 1 , 4 , 5 , 7 , 6 };

/* Variables updated during recursion */
int min_sum = 99999999; /* not initialized */
int best_leaf = -1; /* not initialized */

/* Recursive descent */
/* prb = post-order range begin, irb = in-order range begin, etc. */
void min_sum_leaf(int acc, int prb, int irb, int len) {
  if (len == 0) return; /* empty subtree */
  if (len == 1) { /* leaf */
    int sum = acc + in_order[irb];
    if (sum<min_sum) { min_sum = sum; best_leaf = in_order[irb]; }
    return;
  }
  /* non-leaf */
  int subtree_root = post_order[prb + len - 1];
  /* find the size of the left subtree */
  int i;
  for (i=0;i<len;i++) {
    if (in_order[irb + i] == subtree_root) break;
  }
  /* Now i is the length of the left subtree, len - i - 1 of the right */
  min_sum_leaf(acc + subtree_root, prb, irb, i);
  min_sum_leaf(acc + subtree_root, prb + i, irb + i + 1, len - i - 1);
}

/* Driver */
int find_min_sum_leaf() {
  min_sum = 99999999; best_leaf = -1;
  min_sum_leaf(0, 0, 0, size);
  return best_leaf;
}

注意:我尚未編譯或運行算法,但是邏輯應該存在!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM