leetcode1642.可以到達的最遠建築

大腿壯發表於2020-11-16

題目大意

給你一個整數陣列 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;
    }
};

相關文章