leetcode1642.可以到达的最远建筑

该博客介绍了如何利用小根堆(优先队列)解决一道算法题,题目的目标是确定在有限的砖块和梯子资源下,能够到达的最远建筑物。解题策略是优先在高度差大的地方使用梯子,以节省砖块。通过维护一个小根堆来存储梯子可覆盖的最大高度差,并结合砖块数量进行动态规划,最终找到最佳路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

给你一个整数数组 heights ,表示建筑物的高度。另有一些砖块 bricks 和梯子 ladders 。

你从建筑物 0 开始旅程,不断向后面的建筑物移动,期间可能会用到砖块或梯子。

当从建筑物 i 移动到建筑物 i+1(下标 从 0 开始 )时:

如果当前建筑物的高度 大于或等于 下一建筑物的高度,则不需要梯子或砖块
如果当前建筑的高度 小于 下一个建筑的高度,您可以使用 一架梯子 或 (h[i+1] - h[i]) 个砖块
如果以最佳方式使用给定的梯子和砖块,返回你可以到达的最远建筑物的下标(下标 从 0 开始 )。

题目用例就去看原题吧…

解题思路

如果后面的建筑物更高,则有两种选择:用一个梯子;用高度差数量的砖块;

分析题目可知,无论高度差有多少,一个梯子总是可以爬上去,因此:应该在高度差大的地方用梯子,高度差小的地方用砖头

用小根堆(大小为梯子数量)表示用梯子时的最小高度差。则若当前高度差为x,小根堆的堆顶元素为y:

  • x<=0:表示不需要梯子或者砖块就可以到达,结果直接+1即可;
  • 若x<=y:则x高度差的位置应该用砖头(这样可以将砖头的使用数量降到最低,保留更多砖头):(1)如果当前砖头的数量不足了,则无法再进行下去了,返回结果;(2)否则将砖头数量扣除高度差;
  • 若x>y:表示这里的高度差更高,高度差为y的地方使用砖头,同样根据上面的条件进行判断即可;
class Solution{
public:
    int furthestBuilding(vector<int> & heights, int bricks, int ladders){
        // 没有梯子的情况,直接算一遍就行了
        if (ladders == 0){
            return zeroLadder(heights, bricks);
        }
        // 如果梯子足够多,则全都可以走完
        if (heights.size() <= ladders){
            return heights.size() - 1;
        }
		
		// 创建梯子数量的小根堆,表示用梯子的高度差
        priority_queue<int, vector<int>, greater<int>> myqueue;
        int ans = 0, i = 1, diff = 0;
		// 初始化的时候这里可能存入了负值,后面需要判断堆顶元素的正负
        for (; i < heights.size() && myqueue.size() < ladders; ++i){
            myqueue.push(heights[i] - heights[i - 1]);
        }

        for (; i < heights.size(); ++i){
        	// 当前高度差
            diff = heights[i] - heights[i - 1];
            // 大于堆顶元素,在堆顶位置应该考虑用砖头
            if (diff >= myqueue.top()){
                int curNeed = myqueue.top();
                // 如果砖头不够了,则结束
                if (curNeed > bricks){
                    break;
                }
                myqueue.pop();
				// 如果高度差为正,则扣除一部分砖头
                if (curNeed > 0){
                    bricks -= curNeed;
                }
                ++ans;
                // 将现在的高度差加入堆中
                myqueue.push(diff);
            }
            // 当前位置考虑用砖头
            else{
                if (diff > bricks){
                    break;
                }
                if (diff > 0){
                    bricks -= diff;
                }
                ans++;
            }

        }
        return ans + ladders;
    }

    int zeroLadder(vector<int> & heights, int bricks){
        int ans = 0;
        for(int i = 1; i < heights.size(); ++i){
            if (heights[i] - heights[i - 1] <= 0){
                ++ans;
                continue;
            }
            if (heights[i] - heights[i - 1] > bricks){
                break;
            }
            ++ans;
            bricks -= (heights[i] - heights[i  -1]);
        }
        return ans;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值