繁体   English   中英

破解编码面试第5版,9.10

[英]Cracking the Coding Interview 5th Ed., 9.10

在“破解编码面试”(第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宽度,y高度,z深度):

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;
    }
}

在我看来,盒子总是只有一个最佳的堆叠方式,因为堆叠中任何给定位置的任何盒子的宽度,高度和深度都等于或大于其上方的盒子。 因此,从本质上讲,最佳堆叠将是一个有序列表,其中每个框小于等于其下的框。 但是基于本书中的解决方案和一些在线解决方案,我认为我对该问题有误解,而且这是不正确的,因此我希望获得一些帮助。 你们谁能解释为什么解决这个问题的方法需要寻找盒子的每种可能的组合,而不仅仅是生成盒子的有序列表?

谢谢!

考虑这样一种情况,其中只有三个框(在WxDxH中)分别为1x7x2、1x6x2和7x1x5。 这些框没有严格的排序,因为前两个框都不适合第三个框。 正确的解决方法是单独使用第三个方框(5> 2 + 2)。 如果我了解您的算法,将无法解决这种情况。 解决该问题的方法需要支持多个堆栈,并将每个框添加到可以包含在其中的所有堆栈中。

您的解决方案似乎不正确。 它总是报告以一定顺序包含所有框的列表。 如果您有3个盒子[w10,h10,d10],[w5,h5,d5],[w1,h1,d20],则只有前两个形成最高的纸叠。

如果您尝试找到递归解决方案,您将意识到它花费了指数时间。 动态编程是最好的解决方案。 只需要二次时间。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM