这是递归的经典示例!
调用者调用递归函数,传入根节点并询问“叶子最便宜的成本是多少?”。调用树底部的根节点 (0) 响应:“我还不确定。等一下,我让我的每个孩子看看哪个孩子的成本最低”。然而,目前还没有一个孩子回答这个问题,所以他们问每个孩子完全相同的问题,依此类推。
最终,到达leaf node(例如,您的示例中的 4)并说“我知道!从我到叶节点的最便宜的成本是 我自己的价值,4!我’我要告诉我的父母。”这称为base case。基本情况是迄今为止第一个提供明确答案的函数调用,在这种情况下是针对一个非常小的子问题,其中的信息将用于构建更大问题的解决方案。将太大而无法立即解决的问题分解为易于解决的小问题的过程称为divide and conquer。
节点 4 的父节点,节点 5,现在知道从自己到叶子(4,它的唯一子节点)的最便宜的成本是 5 + 4 = 9,并告诉它的父节点,即根节点 0。根节点现在已武装从它最左边的孩子那里得到一个确定的价值(从根到叶的路径成本,9,比无穷大便宜,所以它被存储为迄今为止最好的),但仍然需要向其他孩子询问他们的成本,它确实.最终,所有孩子都会报告他们各自的费用,0->3->2->1->1 证明是最便宜的。
该算法使用depth-first search,在探索其他分支之前先完全探索一个分支。也就是说,0->5->4 在0->3->2->1->1 之前被完全探索过了。
示例 1
考虑一个具有唯一成本的小节点树示例:
0
/ \
4 1
/
5
我们预计0->1 是成本为 1 的最便宜路径。让我们在这棵树上运行带有详细对话输出的算法。每当进行递归调用时,打印都会缩进。括号是指一个特定的节点。看看你是否可以追踪执行:
(0), what's your min cost?
(0) says: Hang on, I need to ask my children...
(0) says: I'm asking (4) for its min cost...
(4), what's your min cost?
(4) says: Hang on, I need to ask my children...
(4) says: I'm asking (5) for its min cost...
(5), what's your min cost?
(5) says: I'm a leaf! My min cost is 5
(4) says: I got the cost 5 from (5), a new best!
(4) says: I checked my children and I know my min cost is 9
(0) says: I got the cost 9 from (4), a new best!
(0) says: I'm asking (1) for its min cost...
(1), what's your min cost?
(1) says: I'm a leaf! My min cost is 1
(0) says: I got the cost 1 from (1), a new best!
(0) says: I checked my children and I know my min cost is 1
示例 2
这是另一棵更大的树,同样具有唯一节点:
0
/ | \
4 1 7
/ / \
5 6 2
\
3
我们预计0->1->2->3 是成本为 6 的最便宜路径。让我们看看详细输出。再次尝试跟踪执行。
(0), what's your min cost?
(0) says: Hang on, I need to ask my children...
(0) says: I'm asking (4) for its min cost...
(4), what's your min cost?
(4) says: Hang on, I need to ask my children...
(4) says: I'm asking (5) for its min cost...
(5), what's your min cost?
(5) says: I'm a leaf! My min cost is 5
(4) says: I got the cost 5 from (5), a new best!
(4) says: I checked my children and I know my min cost is 9
(0) says: I got the cost 9 from (4), a new best!
(0) says: I'm asking (1) for its min cost...
(1), what's your min cost?
(1) says: Hang on, I need to ask my children...
(1) says: I'm asking (6) for its min cost...
(6), what's your min cost?
(6) says: I'm a leaf! My min cost is 6
(1) says: I got the cost 6 from (6), a new best!
(1) says: I'm asking (2) for its min cost...
(2), what's your min cost?
(2) says: Hang on, I need to ask my children...
(2) says: I'm asking (3) for its min cost...
(3), what's your min cost?
(3) says: I'm a leaf! My min cost is 3
(2) says: I got the cost 3 from (3), a new best!
(2) says: I checked my children and I know my min cost is 5
(1) says: I got the cost 5 from (2), a new best!
(1) says: I checked my children and I know my min cost is 6
(0) says: I got the cost 6 from (1), a new best!
(0) says: I'm asking (7) for its min cost...
(7), what's your min cost?
(7) says: I'm a leaf! My min cost is 7
(0) says: I got the cost 7 from (7) but it's not the best
(0) says: I checked my children and I know my min cost is 6
这是产生上述输出的代码:
static void say(String message, int depth) {
for (int i = 0; i < depth; i++) {
System.out.print(" ");
}
System.out.println(message);
}
static int getCheapestCostRecursion(Node node, int depth) {
say("(" + node.cost + "), what's your min cost?", depth);
if (node.children.length == 0) {
say(
"(" + node.cost +
") says: I'm a leaf! My min cost is " +
node.cost, depth
);
return node.cost;
}
say(
"(" + node.cost +
") says: Hang on, I need to ask my children...",
depth
);
int cheapestCost = Integer.MAX_VALUE;
for (Node child : node.children) {
say(
"(" + node.cost +
") says: I'm asking (" + child.cost +
") for its min cost...", depth
);
int childCost = getCheapestCostRecursion(child, depth + 6);
say(
"(" + node.cost +
") says: I got the cost " + childCost +
" from (" + child.cost + ")", depth
);
if (childCost < cheapestCost) {
say(
"(" + node.cost +
") says: I got the cost " + childCost +
" from (" + child.cost + "), a new best",
depth
);
cheapestCost = childCost;
}
else {
say(
"(" + node.cost +
") says: I got the cost " + childCost +
" from (" + child.cost +
"), but it's not the best", depth
);
}
}
say(
"(" + node.cost +
") says: I checked my children and I know " +
"my min cost is " + (cheapestCost + node.cost),
depth
);
return cheapestCost + node.cost;
}
Try it!