The "Pour Water" problem asks you to simulate the process of pouring water droplets onto a landscape represented by an array of integers. Each value in the heights
array represents the elevation at that position. You are given:
heights
: An array of integers representing the terrain elevation.volume
: The number of water droplets to pour.k
: The index where each droplet is poured.For each droplet, you must simulate its movement:
k
to the lowest possible position (with ties going to the leftmost).k
to the lowest possible position (with ties going to the rightmost).k
.heights
array.
Constraints:
heights
array is not modified until a droplet settles.k
.At first glance, the problem seems to require simulating gravity and water flow, which could be complex. However, the rules are specific and deterministic, so we can approach it step by step:
k
.heights
array before pouring the next droplet.k
to find the appropriate location. This is acceptable given the constraints, but we can think about optimizations later.
The key is to simulate each droplet independently, always starting from k
, and updating the terrain after each pour.
Let's break down the algorithm step-by-step:
volume
times):
k
.k-1
to 0
, move as long as the next position is lower than the current.heights[pos] += 1
), then continue to the next droplet.k+1
to n-1
, move as long as the next position is lower than the current.heights[pos] += 1
), then continue.k
(heights[k] += 1
).heights
array.
We use simple loops for left and right searches. There are possible optimizations using stacks or caching, but the above is efficient enough for typical constraints.
Example:
heights = [2,1,1,2,1,2,2]
, volume = 4
, k = 3
heights = [2,1,2,2,1,2,2]
heights = [2,1,2,2,2,2,2]
heights = [2,1,2,3,2,2,2]
heights = [2,2,2,3,2,2,2]
Final answer: [2,2,2,3,2,2,2]
Brute-force Approach:
volume
), we may scan the entire heights
array left and right from k
.O(volume * n)
, where n
is the length of heights
.O(1)
extra space (in-place modification).In summary, the Pour Water problem is a simulation task where each droplet is poured at a specified index and moves to the lowest adjacent position, preferring the leftmost or rightmost in case of ties. The key insight is to simulate each droplet independently, always updating the terrain after each pour. The step-by-step search left and right ensures correctness and is efficient for typical input sizes. This approach is clear, robust, and easy to implement.
class Solution:
def pourWater(self, heights, volume, k):
n = len(heights)
for _ in range(volume):
pos = k
# Try to move left
for i in range(k-1, -1, -1):
if heights[i] < heights[pos]:
pos = i
elif heights[i] > heights[pos]:
break
if pos != k:
heights[pos] += 1
continue
# Try to move right
pos = k
for i in range(k+1, n):
if heights[i] < heights[pos]:
pos = i
elif heights[i] > heights[pos]:
break
if pos != k:
heights[pos] += 1
continue
# Stay at k
heights[k] += 1
return heights
class Solution {
public:
vector<int> pourWater(vector<int>& heights, int volume, int k) {
int n = heights.size();
for (int v = 0; v < volume; ++v) {
int pos = k;
// Move left
for (int i = k - 1; i >= 0; --i) {
if (heights[i] < heights[pos])
pos = i;
else if (heights[i] > heights[pos])
break;
}
if (pos != k) {
heights[pos]++;
continue;
}
// Move right
pos = k;
for (int i = k + 1; i < n; ++i) {
if (heights[i] < heights[pos])
pos = i;
else if (heights[i] > heights[pos])
break;
}
if (pos != k) {
heights[pos]++;
continue;
}
// Stay at k
heights[k]++;
}
return heights;
}
};
class Solution {
public int[] pourWater(int[] heights, int volume, int k) {
int n = heights.length;
for (int v = 0; v < volume; ++v) {
int pos = k;
// Move left
for (int i = k - 1; i >= 0; --i) {
if (heights[i] < heights[pos])
pos = i;
else if (heights[i] > heights[pos])
break;
}
if (pos != k) {
heights[pos]++;
continue;
}
// Move right
pos = k;
for (int i = k + 1; i < n; ++i) {
if (heights[i] < heights[pos])
pos = i;
else if (heights[i] > heights[pos])
break;
}
if (pos != k) {
heights[pos]++;
continue;
}
// Stay at k
heights[k]++;
}
return heights;
}
}
var pourWater = function(heights, volume, k) {
const n = heights.length;
for (let v = 0; v < volume; ++v) {
let pos = k;
// Move left
for (let i = k - 1; i >= 0; --i) {
if (heights[i] < heights[pos])
pos = i;
else if (heights[i] > heights[pos])
break;
}
if (pos !== k) {
heights[pos]++;
continue;
}
// Move right
pos = k;
for (let i = k + 1; i < n; ++i) {
if (heights[i] < heights[pos])
pos = i;
else if (heights[i] > heights[pos])
break;
}
if (pos !== k) {
heights[pos]++;
continue;
}
// Stay at k
heights[k]++;
}
return heights;
};