簡體   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