[英]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.