The blog for Design Patterns, Linux, HA and Myself!
This document presents the solution to the problem Filling Bookcase Shelves - Leetcode.
Note: Make sure to go through the code comments as well. It’ll help you understand the concept better.
We have a sequence of books: the i-th book has thickness books[i][0] and height books[i][1].
We want to place these books in order onto bookcase shelves that have total width shelf_width.
We choose some of the books to place on this shelf (such that the sum of their
thickness is <= shelf_width), then build another level of shelf of the bookcase so that the total
height of the bookcase has increased by the maximum height of the books we just put down.
We repeat this process until there are no more books to place.
Note again that at each step of the above process, the order of the books we place is the same
order as the given sequence of books. For example, if we have an ordered list of 5 books, we
might place the first and second book onto the first shelf, the third book on the second shelf,
and the fourth and fifth book on the last shelf.
Return the minimum possible height that the total bookshelf can be after placing shelves in
this manner.
This problem has two arguments, books and width.
The 1st argument, books, is an array of dimensions n x 2
, here n
is the number of books. books[i][0]
is the
width and, books[i][1]
is the height of the book at index i
.
We’ve to arrange the books in the bookcase, and the bookcase is divided into shelves. The second argument, width is the width of each of the shelves.
This problem requires us to create an arrangement of the books in the shelves such that the height of the bookcase is minimum. One important point to keep in mind is that we’ve to keep the books in the same order in which they are present in the array.
Now, let’s proceed to solve this problem.
We’ll be using this testcase for out approach:
books = {
{1, 1},
{2, 3},
{2, 3}
}
width = 4
Let’s start from the first book. So, How many arrangements can me made with the first book?
A single book can only take one place. This book’s height is 1, so, total height of the bookcase will be 1. It’ll be kept on the first shelf and, the total number of shelves is also 1.
Such arrangements can be represented using:
type arrangement struct {
ShelfNo int
Width int
CurrentShelfHeight int
TotalHeight int
}
Width
contains total width occupied by the books in the current shelf.CurrentShelfHeight
is the height of the current shelf.TotalHeight
is the height of the bookcase.ShelfNo
.So, the arrangement after adding 1 book to the bookcase is:
arrangement{
ShelfNo: 1,
Width: books[0][0],
CurrentShelfHeight: books[0][1],
TotalHeight: books[0][1],
}
i.e.,
arrangement{
ShelfNo: 1,
Width: 1,
CurrentShelfHeight: 1,
TotalHeight: 1,
}
The second book has the height of 3 units and the width of 2 units. There are two possibilities in which this book can be arranged:
arrangement{
ShelfNo: 1,
Width: 1 + 2,
CurrentShelfHeight: 3,
TotalHeight: 3,
}
arrangement{
ShelfNo: 2,
Width: 2,
CurrentShelfHeight: 3,
TotalHeight: 1 + 3,
}
The minimum height of the bookcase will be 3, if we had to store just these two books.
The third book also has the height of 3 units and the with of 2 units. After adding the previous two books, we’re already having two arrangement in which this 3rd book can be added.
arrangement{
ShelfNo: 2,
Width: 2,
CurrentShelfHeight: 3,
TotalHeight: 6,
}
arrangement{
ShelfNo: 2,
Width: 4,
CurrentShelfHeight: 3,
TotalHeight: 4,
}
arrangement{
ShelfNo: 2,
Width: 4,
CurrentShelfHeight: 3,
TotalHeight: 4,
}
So, the minimum total height will be 4, out of 6, 4, 4.
You should also create new test cases as well and follow these steps to find the minimum height of the bookshelf.
Using this process we’re finding the minimum height after adding each of the book. The final solution depends upon the optimal solutions that we’ve found in the previous steps.
Following is the program for the solution, it is based on the these steps:
type arrangement struct {
ShelfNo int
Width int
CurrentShelfHeight int
TotalHeight int
}
func minHeightShelves(books [][]int, shelf_width int) int {
var shelf []arrangement
var minShelfHeights []int
// create arrangement for the first book
shelf = append(shelf, arrangement{
ShelfNo: 1,
Width: books[0][0],
CurrentShelfHeight: books[0][1],
TotalHeight: books[0][1],
})
minShelfHeights = append(minShelfHeights, books[0][1])
for i := 1; i < len(books); i++ {
currentBook := books[i]
var shelfWithCurrentBook []arrangement
for _, elem := range shelf {
if elem.Width+currentBook[0] <= shelf_width {
// this block is executed if the current book can be
// accommodated in the shelf
newElem := arrangement{
ShelfNo: elem.ShelfNo,
Width: elem.Width + currentBook[0],
CurrentShelfHeight: elem.CurrentShelfHeight,
TotalHeight: elem.TotalHeight,
}
if currentBook[1] > elem.CurrentShelfHeight {
newElem.CurrentShelfHeight = currentBook[1]
newElem.TotalHeight = newElem.TotalHeight + currentBook[1] - elem.CurrentShelfHeight
}
shelfWithCurrentBook = append(shelfWithCurrentBook, newElem)
} else {
// this block is executed if the current book cannot be
// accommodated in the current shelf and a new shelf is created
// for the current book
newElem := arrangement{
ShelfNo: elem.ShelfNo + 1,
Width: currentBook[0],
CurrentShelfHeight: currentBook[1],
TotalHeight: elem.TotalHeight + currentBook[1],
}
shelfWithCurrentBook = append(shelfWithCurrentBook, newElem)
}
}
// a new shelf is also on the minimum height found in the previous
// step
newElem := arrangement{
ShelfNo: shelf[len(shelf)-1].ShelfNo + 1,
Width: currentBook[0],
CurrentShelfHeight: currentBook[1],
TotalHeight: minShelfHeights[i - 1] + currentBook[1],
}
shelfWithCurrentBook = append(shelfWithCurrentBook, newElem)
// here we find the minimum height from all the possible
// arrangements
minShelfHeight := math.MaxInt32
for j := 0; j < len(shelfWithCurrentBook); j++ {
if shelfWithCurrentBook[j].TotalHeight < minShelfHeight {
minShelfHeight = shelfWithCurrentBook[j].TotalHeight
}
}
minShelfHeights = append(minShelfHeights, minShelfHeight)
shelf = shelfWithCurrentBook
}
return minShelfHeights[len(minShelfHeights)-1]
}