Skip to content

Commit 5719a04

Browse files
committed
Added 1 solution, updated 1 solution
1 parent 4dd91dd commit 5719a04

File tree

4 files changed

+90
-42
lines changed

4 files changed

+90
-42
lines changed

Chp. 08 - Recursion and Dynamic Programming/_8_13_Stack_of_Boxes/Box.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ public class Box {
1111
depth = d;
1212
}
1313

14-
Box(Box other) {
15-
width = other.width;
16-
height = other.height;
17-
depth = other.depth;
18-
}
19-
2014
public boolean canBeAbove(Box other) {
2115
return (other == null) || (width < other.width && height < other.height && depth < other.depth);
2216
}

Chp. 08 - Recursion and Dynamic Programming/_8_13_Stack_of_Boxes/StackOfBoxes.java

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,64 @@
22

33
import java.util.*;
44

5+
// Based off Cracking the Coding Interview 6th Edition's Solution 1
6+
57
// Algorithm
68
//
79
// 1. Create Box class with `.canBeAbove(Box other)` function.
8-
// 2. Sort Boxes in descending height order.
10+
// 2. Sort Boxes in descending height order. This ensures we don't have to look backwards in the list
911
// - This problem uses `<` instead of `<=` for Box heights. If we have 2 Boxes of equal height,
10-
// and [width, height, depth] of [4,4,4] and [7,4,7], it doesn't matter which Box comes first
11-
// after sorting, since both `Box`es can't be in the final solution. Box 1 cannot be on top of Box 2,
12-
// and Box 2 cannot be on top of Box 1.
13-
// 3. For each Box, you have 2 choices:
14-
// 1. Use the Box
15-
// 2. Don't use the Box.
16-
// 4. Recursively try both options. Return the larger height returned from these 2 options.
17-
// 5. Use a Map<Integer, Integer> cache to save solutions to sub-problems
18-
// 1. "key" is the index `i` in the list of boxes
19-
// 2. "value" is the max height possible from that Box to the end of our list of Boxes
12+
// such as [width, height, depth] of [4,4,4] and [7,4,7], it doesn't matter which Box comes first
13+
// after sorting, since both Boxes can't be in the final solution. Box 1 cannot be on top of Box 2,
14+
// and Box 2 cannot be on top of Box 1.
15+
// 3. Experiment with each Box as a bottom and build the biggest stack possible.
16+
// 4. Use a "Map<Integer, Integer>" cache to save solutions to sub-problems
17+
// 1. "key" is the index `i` in the List of boxes
18+
// 2. "value" is the max height possible with "Box i" at the bottom
2019

2120
public class StackOfBoxes {
2221
public static int findMaxHeight(List<Box> boxes) {
2322
if (boxes == null || boxes.size() == 0) {
2423
return 0;
2524
}
2625
Collections.sort(boxes, (box1, box2) -> box2.height - box1.height); // sort in descending height order
27-
return findMaxHeight(boxes, 0, null, new HashMap<>(boxes.size()));
26+
return findMaxHeight(boxes, -1, new HashMap<Integer, Integer>());
2827
}
29-
30-
private static int findMaxHeight(List<Box> boxes, int i, Box bottom, Map<Integer, Integer> cache) {
31-
if (i >= boxes.size()) {
32-
return 0;
33-
} else if (cache.containsKey(i)) {
34-
return cache.get(i);
28+
29+
private static int findMaxHeight(List<Box> boxes, int bottomIndex, Map<Integer, Integer> cache) {
30+
if (cache.containsKey(bottomIndex)) {
31+
return cache.get(bottomIndex);
3532
}
36-
37-
// height with this Box
38-
Box newBottom = boxes.get(i);
39-
int heightWith = 0;
40-
if (newBottom.canBeAbove(bottom)) {
41-
heightWith = newBottom.height + findMaxHeight(boxes, i + 1, newBottom, cache);
33+
34+
int maxHeight = 0;
35+
Box bottom = bottomIndex == -1 ? null : boxes.get(bottomIndex);
36+
37+
for (int i = bottomIndex + 1; i < boxes.size(); i++) {
38+
if (boxes.get(i).canBeAbove(bottom)) {
39+
int height = findMaxHeight(boxes, i, cache);
40+
maxHeight = Math.max(maxHeight, height);
41+
}
4242
}
43-
44-
// height without this Box
45-
int heightWithout = findMaxHeight(boxes, i + 1, bottom, cache);
46-
47-
int max = Math.max(heightWith, heightWithout);
48-
cache.put(i, max);
49-
return max;
43+
44+
maxHeight += bottomIndex == -1 ? 0 : bottom.height;
45+
cache.put(bottomIndex, maxHeight);
46+
return maxHeight;
5047
}
5148
}
5249

53-
// Time Complexity: Without caching, the recursive part is O(2^n) since there are `n` boxes,
54-
// and 2 options for each box (use or don't use). With caching, the recursive part is just O(n).
55-
// The total time complexity is therefore O(n log n) due to sorting.
50+
// Time Complexity: O(n^2)
5651
// Space Complexity: O(n) due to recursion.
5752

58-
// - A Dynamic Programming Iterative solution (using an array instead of a HashMap)
59-
// is also possible. It will have the same Time/Space complexity as the above solution.
53+
54+
// Alternate Solution: Cracking the Coding Interview 6th Edition Solution 2
55+
//
56+
// I didn't like this alternate solution since caching was done weirdly: Function had 2 changing
57+
// parameters (Box bottom, int offset) but cache only used 1 parameter.
58+
59+
60+
// Follow-up Question - What if rotation of boxes is allowed?
61+
//
62+
// 1. For each box, rotate it to all 6 possibilities: [w h d], [w d h], [h w d] [h d w], [d w h], [d h w].
63+
// 2. Notice it's impossible to stack 2 of these 6 boxes on top of each other, so if we insert all 6 boxes
64+
// into our list, we're still ensured only 1 of them can be selected for our solution.
65+
// 3. Create `List<Box> boxes` that is 6 times as large as the original list of boxes. Solve the problem for this list.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package _17_08_Circus_Tower;
2+
3+
import java.util.*;
4+
5+
public class CircusTower {
6+
public static int findMax(int[][] persons) {
7+
if (persons == null || persons.length == 0 || persons[0].length != 2) {
8+
return 0;
9+
}
10+
Arrays.sort(persons, (a, b) -> {
11+
if (a[0] != b[0]) {
12+
return a[0] - b[0];
13+
} else {
14+
return b[1] - a[1];
15+
}
16+
});
17+
18+
int[] sortedArray = new int[persons.length];
19+
int size = 0;
20+
for (int[] person : persons) {
21+
int num = person[1];
22+
int start = 0;
23+
int end = size; // 1 element past end of our sortedArray
24+
while (start != end) {
25+
int mid = (start + end) / 2;
26+
if (sortedArray[mid] < num) {
27+
start = mid + 1;
28+
} else {
29+
end = mid;
30+
}
31+
}
32+
sortedArray[start] = num;
33+
if (start == size) {
34+
size++;
35+
}
36+
}
37+
return size;
38+
}
39+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package _17_08_Circus_Tower;
2+
3+
public class Tester {
4+
public static void main(String[] args) {
5+
System.out.println("*** Test 8.13: Stack of Boxes\n");
6+
int result = CircusTower.findMax(new int[][]{{2, 3}, {3, 3}, {4,3}, {5, 5}});
7+
System.out.println(result);
8+
}
9+
}

0 commit comments

Comments
 (0)