Leetcode 1642 - Furthest Building You Can Reach

Subscribe Send me a message home page tags


#leetcode 

Problem

You are given an integer array heights representing the heights of buildings, some bricks, and some ladders.

You start your journey from building 0 and move to the next building by possibly using bricks or ladders.

While moving from building i to building i+1 (0-indexed),

If the current building's height is greater than or equal to the next building's height, you do not need a ladder or bricks.

If the current building's height is less than the next building's height, you can either use one ladder or (h[i+1] - h[i]) bricks.

Return the furthest building index (0-indexed) you can reach if you use the given ladders and bricks optimally.

Solution

A greedy algorithm seems to be an appropriate solution. We should use ladders to cover the largest gaps between two buildings. Therefore, we need to track the largest gaps we have seen so far when we go throught the list of buildings. A priority queue is can be used as it's the data structure desigend for this type of tasks.

Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Solution {
public:
    int furthestBuilding(vector<int>& heights, int bricks, int ladders) {
        if (heights.empty()) {return -1;}

        size_t loc = 0;

        auto comparator = [&](size_t i, size_t j) {
            auto diff_i = heights[i+1] - heights[i];
            auto diff_j = heights[j+1] - heights[j];
            return diff_j > diff_i;
        };

        std::priority_queue<size_t, std::vector<size_t>, decltype(comparator)> q_index(comparator);

        while (loc < heights.size()) {
            if (loc == heights.size() - 1) {return loc;}

            // try to move to the next building
            if (heights[loc] >= heights[loc+1]) {
                ++loc;
            } else {
                auto diff = heights[loc+1] - heights[loc];

                if (bricks >= diff) {
                    bricks -= diff;
                    q_index.push(loc);
                    ++loc;
                } else {
                    if (ladders == 0) {
                        // in this case we need to stop because we run out of both bricks and ladders;
                        return loc;
                    } else {
                        if (q_index.empty()) {
                            --ladders;
                            ++loc;
                        } else {
                            auto index = q_index.top();
                            auto refund = heights[index+1] - heights[index];
                            --ladders;
                            if (diff >= refund) {
                                // use a ladder and move forward
                                ++loc;
                            } else {
                                q_index.pop();
                                bricks += refund;
                                // We don't move to next location.
                            }
                        }
                    }
                }
            }
        }

        // We should never reach to here.
        return -1;
    }
};

----- END -----

If you have questions about this post, you could find me on Discord.
Send me a message Subscribe to blog updates

Want some fun stuff?

/static/shopping_demo.png