《程序员面试金典》(第六版)习题:仅为记录一下以加强印象,不为商业用途,如有侵权请联系删除。以下源码和解释参考了书中源码以及解释。
假设一共有
b
o
x
1
,
b
o
x
2
,
.
.
.
,
b
o
x
n
box_1, box_2, ..., box_n
box1,box2,...,boxnn个箱子。首先找到以箱子
b
o
x
1
box_1
box1、
b
o
x
2
box_2
box2、…、
b
o
x
n
box_n
boxn为底的可以堆出的最高箱高,然后求这n个值得最大值即为所求。在求以单个箱子为底的最高箱堆对法的过程中使用了递归思想。
//算法一
int max(int a,int b)
{
if (a > b)
return a;
else
return b;
}
class Box
{
public:
int width;
int height;
int depth;
Box(int w, int h, int d)
{
width = w;
height = h;
depth = d;
}
bool canBeUnder(Box b)
{
if (width > b.width && height > b.height && depth > b.depth)
{
return true;
}
return false;
}
bool canBeAbove(Box b)
{
if (width < b.width && height < b.height && depth < b.depth)
{
return true;
}
return false;
}
string toBoxString()
{
return "Box(" + to_string(width) + "," + to_string(height) + "," + to_string(depth) + ")";
}
};
int createStack(vector<Box> boxes, int bottomIndex)
{
Box bottom = boxes[bottomIndex];
int maxHeight = 0;
for (int i = bottomIndex + 1; i < boxes.size(); i++)
{
if (boxes[i].canBeAbove(bottom))
{
int height = createStack(boxes, i);
maxHeight = max(maxHeight, height);
}
}
maxHeight += bottom.height;
return maxHeight;
}
int createStack(vector<Box> boxes)
{
Box tempBox(0,0,0);
for (int i = boxes.size() - 1; i >0 ; i--)
{
for (int j = 0; j < i; j++)
{
if (boxes[j].height < boxes[j + 1].height)
{
tempBox = boxes[j];
boxes[j] = boxes[j + 1];
boxes[j+1] = tempBox;
}
}
}
int maxHeight = 0;
for (int i = 0; i < boxes.size(); i++)
{
int height= createStack(boxes, i);
maxHeight = max(maxHeight, height);
}
return maxHeight;
}
算法二是对算法一的改进。算法二存储了已经得到的一些结果,避免了一些不必要的重复调用。
//算法二
int createStack(vector<Box> boxes, int bottomIndex,int * stackMap)
{
if (bottomIndex < boxes.size() && stackMap[bottomIndex]>0)
return stackMap[bottomIndex];
Box bottom = boxes[bottomIndex];
int maxHeight = 0;
for (int i = bottomIndex + 1; i < boxes.size(); i++)
{
if (boxes[i].canBeAbove(bottom))
{
int height = createStack(boxes, i, stackMap);
maxHeight = max(maxHeight, height);
}
}
maxHeight += bottom.height;
stackMap[bottomIndex]= maxHeight;
return maxHeight;
}
int createStack(vector<Box> boxes)
{
Box tempBox(0,0,0);
for (int i = boxes.size() - 1; i >0 ; i--)
{
for (int j = 0; j < i; j++)
{
if (boxes[j].height < boxes[j + 1].height)
{
tempBox = boxes[j];
boxes[j] = boxes[j + 1];
boxes[j+1] = tempBox;
}
}
}
int maxHeight = 0;
int* stackMap = new int[boxes.size()];
for (int i = 0; i < boxes.size(); i++)
{
int height= createStack(boxes, i, stackMap);
maxHeight = max(maxHeight, height);
}
return maxHeight;
}
当对原有的箱子集合按照高度值降序排列后,算法三分为两条递归路径来计算可能的最高堆高度值。一条递归路径以以箱子boexes[offSet]为底,另一条递归路径不以箱子boexes[offSet]为底(堆中排出箱子boexes[offSet])。算法三也使用额外的空间来存储了已经得到的一些结果,避免了一些不必要的重复调用。文章最后有一个简单的测试程序以及对应算法三的递归调用图。
//算法三
int createStack(vector<Box> boxes,Box* bottom, int offSet, vector<int> &stackMap)
{
if (offSet >= boxes.size())
return 0;
Box newBottom = boxes[offSet];
int heightWithBottom = 0;
//以下IF语句计算以箱子boexes[offSet]为底的可能堆出的最高堆高度值
if ((bottom==nullptr)||newBottom.canBeAbove(*bottom))
{
if (stackMap[offSet] == 0)
{
stackMap[offSet] = createStack(boxes, &newBottom, offSet+1, stackMap);
stackMap[offSet] += newBottom.height;
}
heightWithBottom = stackMap[offSet];
}
//以下函数调用计算不以箱子boexes[offSet]为底的可能堆出的最高堆高度值(堆中排出箱子boexes[offSet])
int heightWithoutBottom= createStack(boxes, bottom, offSet + 1, stackMap);
return max(heightWithBottom, heightWithoutBottom);
}
int createStack(vector<Box> boxes)
{
Box tempBox(0,0,0);
//对原有的所有的箱子按高度值降序排列
for (int i = boxes.size() - 1; i >0 ; i--)
{
for (int j = 0; j < i; j++)
{
if (boxes[j].height < boxes[j + 1].height)
{
tempBox = boxes[j];
boxes[j] = boxes[j + 1];
boxes[j+1] = tempBox;
}
}
}
vector<int> stackMap(3,0);
return createStack(boxes, nullptr, 0, stackMap);
}
//测试程序
int main()
{
Box one(1, 1, 1);
Box two(2,2,2);
Box three(3, 3, 3);
vector<Box> boxes = { one,two,three };
cout << createStack(boxes);
}