{x}
blog image

Pour Water

Solution Explanation for Pour Water Problem

This problem simulates the process of pouring water onto an elevation map represented by an integer array heights. The goal is to determine the final state of the elevation map after a specified volume of water is poured at a given index k.

Core Idea:

The solution uses a simulation approach. It iterates through each unit of water to be poured. For each unit, it attempts to find the lowest point it can reach by moving left and then right from the pour point (k). The water moves downhill until it encounters a point where further movement wouldn't result in a decrease in height.

Algorithm:

  1. Iteration: The outer loop iterates volume times, representing each unit of water.

  2. Leftward Flow: The inner loop first checks for downward movement to the left (d = -1). It iterates while the index is within bounds and the height at the current index is greater than or equal to the height at the next index to the left. If a lower point is found, the index j is updated to track this lowest point.

  3. Rightward Flow: If no lower point is found on the left, it checks the right (d = 1). The logic mirrors the leftward flow check.

  4. Water Placement: If a lower point is found during either leftward or rightward movement (j != k), the water is added to that position (heights[j] += 1).

  5. Default Placement: If no lower point is found in either direction, the water remains at the original pour point (heights[k] += 1).

Time and Space Complexity:

  • Time Complexity: O(V * N), where V is the volume of water and N is the length of the heights array. The nested loops dominate the runtime; in the worst case, each unit of water might traverse the entire array.

  • Space Complexity: O(1). The solution modifies the input array in-place; no additional data structures with significant size are used.

Code Examples (Python and Java):

The provided code examples efficiently implement this algorithm. Here's a breakdown of key aspects:

Python:

class Solution:
    def pourWater(self, heights: List[int], volume: int, k: int) -> List[int]:
        for _ in range(volume):
            for d in (-1, 1):
                i = j = k
                while 0 <= i + d < len(heights) and heights[i + d] <= heights[i]:
                    if heights[i + d] < heights[i]:
                        j = i + d
                    i += d
                if j != k:
                    heights[j] += 1
                    break
            else:
                heights[k] += 1
        return heights

This Python code efficiently uses a for loop and while loop to iterate through the water units and potential flow paths. The use of else with for is a concise way to handle the case where no lower point was found.

Java:

class Solution {
    public int[] pourWater(int[] heights, int volume, int k) {
        while (volume-- > 0) {
            boolean find = false;
            for (int d = -1; d < 2 && !find; d += 2) {
                int i = k, j = k;
                while (i + d >= 0 && i + d < heights.length && heights[i + d] <= heights[i]) {
                    if (heights[i + d] < heights[i]) {
                        j = i + d;
                    }
                    i += d;
                }
                if (j != k) {
                    find = true;
                    ++heights[j];
                }
            }
            if (!find) {
                ++heights[k];
            }
        }
        return heights;
    }
}

The Java code uses a similar structure, employing a while loop for the water units and a for loop to check left and right. The boolean find flag is used to track if a lower point was found, preventing unnecessary checks.

The C++, Go, and other language examples follow similar logic, adapting the syntax to their respective programming languages. The core algorithmic approach remains consistent.