[LeetCode] Pour Water 倒水


 

We are given an elevation map, heights[i] representing the height of the terrain at that index. The width at each index is 1. After V units of water fall at index K, how much water is at each index?

Water first drops at index K and rests on top of the highest terrain or water at that index. Then, it flows according to the following rules:

  • If the droplet would eventually fall by moving left, then move left.
  • Otherwise, if the droplet would eventually fall by moving right, then move right.
  • Otherwise, rise at it's current position.

Here, "eventually fall" means that the droplet will eventually be at a lower level if it moves in that direction. Also, "level" means the height of the terrain plus any water in that column.

 

We can assume there's infinitely high terrain on the two sides out of bounds of the array. Also, there could not be partial water being spread out evenly on more than 1 grid block - each unit of water has to be in exactly one block.

 

Example 1:

Input: heights = [2,1,1,2,1,2,2], V = 4, K = 3
Output: [2,2,2,3,2,2,2]
Explanation:
#       #
#       #
##  # ###
#########
 0123456    <- index

The first drop of water lands at index K = 3:

#       #
#   w   #
##  # ###
#########
 0123456    

When moving left or right, the water can only move to the same level or a lower level.
(By level, we mean the total height of the terrain plus any water in that column.)
Since moving left will eventually make it fall, it moves left.
(A droplet "made to fall" means go to a lower height than it was at previously.)

#       #
#       #
## w# ###
#########
 0123456    

Since moving left will not make it fall, it stays in place.  The next droplet falls:

#       #
#   w   #
## w# ###
#########
 0123456  

Since the new droplet moving left will eventually make it fall, it moves left.
Notice that the droplet still preferred to move left,
even though it could move right (and moving right makes it fall quicker.)

#       #
#  w    #
## w# ###
#########
 0123456  

#       #
#       #
##ww# ###
#########
 0123456  

After those steps, the third droplet falls.
Since moving left would not eventually make it fall, it tries to move right.
Since moving right would eventually make it fall, it moves right.

#       #
#   w   #
##ww# ###
#########
 0123456  

#       #
#       #
##ww#w###
#########
 0123456  

Finally, the fourth droplet falls.
Since moving left would not eventually make it fall, it tries to move right.
Since moving right would not eventually make it fall, it stays in place:

#       #
#   w   #
##ww#w###
#########
 0123456  

The final answer is [2,2,2,3,2,2,2]:

    #    
 ####### 
 ####### 
 0123456 

 

Example 2:

Input: heights = [1,2,3,4], V = 2, K = 2
Output: [2,3,3,4]
Explanation:
The last droplet settles at index 1, since moving further left would not cause it to eventually fall to a lower height.

 

Example 3:

Input: heights = [3,1,3], V = 5, K = 1
Output: [4,4,4]

 

Note:

  1. heights will have length in [1, 100] and contain integers in [0, 99].
  2. V will be in range [0, 2000].
  3. K will be in range [0, heights.length - 1].

 

這道題說有不同高度的地面,每次都位置K有水滴落下,水滴落下后移動的方向有如下的規則:

1. 如果水滴向左移動后最終停止的位置低於落下的位置,則向左移動。

2. 否則若水滴向右移動后最終停止的位置低於落下的位置,則向右移動。

3. 否則停在原來的位置。

水滴停止后,原來的位置高度就增加1,讓我們返回最后地面的高度。我們首先來分析題目中的例子1:

#       #
#   4   #
##21#3###
#########

我們可以觀察出,如果左邊到的位置低的話,就先去左邊,即便右邊能到同樣低的位置,也還是左邊優先。但是這個例子沒能說明,如果右邊的位置更低的話,是去右邊呢,還是左邊,看下面這個例子:

 54#     #
32###   ###
1##### #####
#############

紅色表示水滴落下的位置,我們可以看到第五滴水沒有去右邊更低的地方,而是去了左邊的位置,這說明,左邊有至高優先權,只要左邊的最終位置低於水滴落下的位置,一定會去左邊。

還有就是,去一個方向最終要落到一個局部最低點,請看下面這個例子:

#
###1# #
##### #
#######

我們可以看到,水滴去了右邊第一個局部最低點,而再右邊的全局最低點是無法到達的。如果都是一樣的高度的話,落在離水滴落下起始位置最近的點,請看下下面這兩個例子:

#
###1#
#####
#1 #####
#####

第一個例子中水滴去了局部最低點,第二個例子中由於右邊的高度都相同,水滴去了最靠近起始位置的點。

那么分析到這里,我想思路應該比較明晰了吧。首先我們嘗試向左走,找到第一個局部最低點,停止條件是左邊的高度大於當前高度,但是為了防止出現大家高度都一樣而需要停止在靠近起始點位置的情況,我們來一個回滾操作,就是只要和右邊的高度一樣,就一直往右滾。同樣,在嘗試向右走,找第一個局部最低點,停止條件是右邊的高度大於當前高度,但是為了防止出現大家高度都一樣而需要停止在靠近起始點位置的情況,我們也來一個回滾操作,就是只要和左邊的高度一樣,就一直往左滾。那么此時我們來做比較,如果左邊的局部最低點小於雨滴落下位置的高度,那么左邊局部最低點高度自增1。否則如果右邊的局部最低點高度小於雨滴落下位置的高度,則右邊局部最低點高度自增1。如果左右高度都一樣,則雨滴落下位置的高度自增1,參見代碼如下:

 

class Solution {
public:
    vector<int> pourWater(vector<int>& heights, int V, int K) {
        for (int i = 0; i < V; ++i) {
            int l = K, r = K, n = heights.size();
            while (l > 0 && heights[l] >= heights[l - 1]) --l;
            while (l < K && heights[l] == heights[l + 1]) ++l;
            while (r < n - 1 && heights[r] >= heights[r + 1]) ++r;
            while (r > K && heights[r] == heights[r - 1]) --r;
            (heights[l] < heights[K]) ? ++heights[l] : ++heights[r];
        }
        return heights;
    }
};

 

類似題目:

Trapping Rain Water

 

參考資料:

https://leetcode.com/problems/pour-water/discuss/116670/My-8-Lines-C++-Solution

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM