【问题标题】:Cracking the Coding Interview 5th Ed., 9.10破解编码面试第 5 版,9.10
【发布时间】:2015-12-12 12:04:03
【问题描述】:

在破解编码面试(第 5 版)中,提出了以下问题:

你有一叠 n 个宽度为 w(i)、h(i) 和 d(i) 的盒子。如果堆叠中的每个盒子在宽度、高度和深度上都严格大于其上方的盒子,则盒子不能旋转,只能堆叠在一起。实现一种方法来构建可能的最高堆栈,其中堆栈的高度是每个框的高度之和。

我想出了以下不涉及任何动态编程的递归解决方案:

 public static List<Box> stackBoxes(List<Box> boxes){
    if(boxes.size() <= 1){
        return boxes;
    }

    List<Box> temp = new ArrayList<Box>();
    temp = stackBoxes(boxes.subList(1, boxes.size()));
    Box currentBox = new Box(0, 0, 0);
    currentBox = boxes.get(0);

    for(int i = 0; i < temp.size(); i++){
        Box nextBox = new Box(0,0,0);
        nextBox = temp.get(i);
        if(nextBox.x >= currentBox.x && nextBox.y >= currentBox.y 
                && nextBox.z >= currentBox.z){

            List<Box> half1 = new ArrayList<Box>(temp.subList(0, i));
            half1.add(currentBox);

            List<Box> half2 = new ArrayList<Box>(temp.subList(i,  
            temp.size()));

            half1.addAll(half2);
            return half1;
        }
    }

    List<Box> newStack = new ArrayList<Box>();
    newStack.addAll(temp);
    newStack.add(currentBox);
    return newStack;

}

框类(x-width、y-height、z-depth):

public class Box {
    public int x;
    public int y;
    public int z;

    public Box(int x, int y, int z){
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

在我看来,盒子的最佳堆叠似乎总是只有一个,因为在堆叠中任何给定位置的任何盒子在宽度、高度和深度上都将等于或大于其上方的盒子。所以本质上,最佳堆叠将是一个有序列表,其中每个框

谢谢!

【问题讨论】:

  • 只有一个“最高”的堆栈满足要求,但可以有多个组合满足基本约束同时更短。

标签: java oop recursion dynamic-programming


【解决方案1】:

考虑只有三个框(在 WxDxH 中)1x7x2、1x6x2 和 7x1x5 的情况。这些盒子没有严格的顺序,因为前两个都不适合第三个。然而,正确的解决方案是第三个盒子本身(5 > 2+2)。如果我了解您的算法,它将无法应对这种情况。该问题的解决方案需要支持多个堆栈,并将每个框添加到可以包含它的所有堆栈中。

【讨论】:

  • 啊。我想我现在明白了。我没有正确理解问题的原始前提。在您的示例中,1x7x2 和 7x1x5 不能以任一顺序相互堆叠,因为两者都不完全大于另一个(1 1、2
【解决方案2】:

您的解决方案似乎不正确。它总是以某种顺序报告包含所有框的列表。如果你有 3 个盒子 [w10, h10, d10], [w5, h5, d5], [w1, h1, d20] 那么只有前两个构成最高的堆栈。

如果您尝试找到递归解决方案,您会发现它需要指数级的时间。动态编程是这里最好的解决方案。它只需要二次时间。

这个想法并不难。您只需使用顶点中的框制作有向图并在两个顶点之间添加边,前提是目标顶点中的框可以放在源顶点中的框顶部。每个顶点的权重是其中盒子的高度。然后最佳堆栈对应于该图中具有最大顶点权重总和的路径。这里的关键是访问的顶点。所有顶点的开头都应该有“尚未访问”的标记。每个顶点中的第二个必要字段是聚合的最佳堆栈高度,以该顶点的一个框结尾。第三个属性是对最佳先前顶点的反向引用。算法从没有传入边的顶点开始。您只需将它们的高度用作最佳高度并将它们标记为已访问。在接下来的每个步骤中,您只能访问所有传入边都带有已访问源顶点的顶点。当您访问某个顶点时,您会选择最佳传入边(具有最高聚合高度)。您将当前顶点的高度添加到聚合高度并存储在此顶点中。您还可以将此顶点的反向引用存储到最佳路径来自的前一个顶点。最后,您应该从没有出边的顶点集中选择最佳顶点。沿着反向参考从最佳最终顶点返回,您可以重建最佳路径,从而为您提供最佳堆栈。

【讨论】:

  • 谢谢,我相信我明白我的误解是从哪里来的了。您的解决方案与书中的方法不同,因此感谢您详细说明,以便我可以看看解决此问题的另一种方法。
猜你喜欢
  • 2012-09-24
  • 2015-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 2018-11-21
  • 2013-09-05
  • 1970-01-01
相关资源
最近更新 更多