|
30 | 30 | - actually, what I do will be slightly different for the two possible cases, because I'll need to compare the rest-of-bookshelf height between the two options to choose the optimal one:
|
31 | 31 | - if placing the next book on a new shelf, the rest-of-bookshelf height will be the current shelf's height plus the returned height
|
32 | 32 | - if placing the next book on the current shelf, the rest-of-bookshelf height will be the larger of the current shelf's height and the book's height, plus the returned height
|
33 |
| - |
34 |
| -<!-- - okay my initial thought is that a potential algorithm could go something like this: |
35 |
| - - first, find an initial "naïve" total height and then see if it's possible to optimize from there. The initial total height is the bookshelf height we get if we fill each shelf with as many books as possible without exceeding `shelfWidth`. |
36 |
| - - to see if we can do better than this inital height, move the last book we placed on the first shelf to the second shelf, the last book on the second shelf to the third shelf, and so on. Repeat until there's only one book left on the first shelf. |
37 |
| - - Then --> |
| 33 | + - and then I'll need to compare those two heights and return the smaller one |
| 34 | + - so I think I'll need to set the function up to take as arguments (at least): |
| 35 | + - the index of the current book |
| 36 | + - the height of the current shelf |
| 37 | + - the remaining width on the current shelf |
| 38 | + - possibly the cache object and `books` list, unless I make them available in scope some other way |
| 39 | + - and then I can format the book index and remaining shelf width as a string to use as a key in the cache dict |
| 40 | +- okay it's possible there are some additional details I haven't thought of yet, but I'm gonna try this |
38 | 41 |
|
39 | 42 | ## Refining the problem, round 2 thoughts
|
40 | 43 |
|
|
43 | 46 | ```python
|
44 | 47 | class Solution:
|
45 | 48 | def minHeightShelves(self, books: List[List[int]], shelfWidth: int) -> int:
|
| 49 | + return self._recurse_books(books, 0, shelfWidth, shelfWidth, 0, {}) |
| 50 | + |
| 51 | + def _recurse_books( |
| 52 | + self, |
| 53 | + books, |
| 54 | + curr_ix, |
| 55 | + full_shelf_width, |
| 56 | + shelf_width_left, |
| 57 | + curr_shelf_height, |
| 58 | + call_cache |
| 59 | + ): |
| 60 | + # base case (no books left): |
| 61 | + if curr_ix == len(books): |
| 62 | + return curr_shelf_height |
| 63 | + |
| 64 | + cache_key = f'{curr_ix}-{shelf_width_left}' |
| 65 | + if cache_key in call_cache: |
| 66 | + return call_cache[cache_key] |
| 67 | + |
| 68 | + # test placing book on new shelf |
| 69 | + total_height_new_shelf = curr_shelf_height + self._recurse_books( |
| 70 | + books, |
| 71 | + curr_ix + 1, |
| 72 | + full_shelf_width, |
| 73 | + full_shelf_width - books[curr_ix][0], |
| 74 | + books[curr_ix][1], |
| 75 | + call_cache |
| 76 | + ) |
| 77 | + |
| 78 | + # if book can fit on current shelf, also test placing it there |
| 79 | + if books[curr_ix][0] <= shelf_width_left: |
| 80 | + # check if current book is new tallest book on shelf |
| 81 | + if books[curr_ix][1] > curr_shelf_height: |
| 82 | + curr_shelf_height = books[curr_ix][1] |
| 83 | + |
| 84 | + total_height_curr_shelf = self._recurse_books( |
| 85 | + books, |
| 86 | + curr_ix + 1, |
| 87 | + full_shelf_width, |
| 88 | + shelf_width_left - books[curr_ix][0], |
| 89 | + curr_shelf_height, |
| 90 | + call_cache |
| 91 | + ) |
| 92 | + if total_height_curr_shelf < total_height_new_shelf: |
| 93 | + call_cache[cache_key] = total_height_curr_shelf |
| 94 | + return total_height_curr_shelf |
| 95 | + else: |
| 96 | + call_cache[cache_key] = total_height_new_shelf |
| 97 | + return total_height_new_shelf |
| 98 | + |
| 99 | + call_cache[cache_key] = total_height_new_shelf |
| 100 | + return total_height_new_shelf |
46 | 101 |
|
47 | 102 | ```
|
| 103 | + |
| 104 | + |
0 commit comments