{x}
blog image

Pour Water Between Buckets to Make Water Levels Equal

Solution Explanation for Pour Water Between Buckets to Make Water Levels Equal

This problem asks to find the maximum amount of water that can be equally distributed among multiple buckets, considering water loss during the transfer. A direct approach would involve complex iterative simulations of water pouring. However, a more efficient solution leverages binary search.

Core Idea: The problem exhibits a monotonically increasing property: if a certain water level v is achievable, then any level below v is also achievable. This property makes binary search applicable.

Algorithm:

  1. Binary Search: We perform a binary search within the range [0, max(buckets)], where buckets is the input array representing water levels in each bucket. The search aims to find the largest achievable water level.

  2. Check Function: The core of the algorithm lies in the check(v) function. This function determines if a given water level v is feasible. For each bucket:

    • If the bucket's water level is greater than v, we calculate the excess water (x - v) that needs to be poured out.
    • If the bucket's water level is less than v, we calculate the water needed to fill it to level v. This amount is then adjusted to account for the water loss using the formula: (v - x) * 100 / (100 - loss).

    The function returns true if the total excess water (a) is greater than or equal to the total water needed (b), meaning we can equalize the water levels to v by pouring water between the buckets. Otherwise, it returns false.

  3. Binary Search Iteration: The binary search iteratively refines the search space. If check(mid) is true (where mid is the midpoint of the current search space), we update the lower bound (l) to mid; otherwise, we update the upper bound (r) to mid. This continues until the difference between r and l is smaller than a tolerance (e.g., 1e-5 to account for floating-point precision).

  4. Return Value: After the binary search, l will hold the maximum achievable water level, which is returned as the result.

Time and Space Complexity:

  • Time Complexity: O(N * log M), where N is the number of buckets and M is the maximum water level in a bucket. The binary search takes O(log M) time, and each check operation takes O(N) time to iterate through the buckets.
  • Space Complexity: O(1). The algorithm uses a constant amount of extra space.

Code Implementation (Python):

class Solution:
    def equalizeWater(self, buckets: List[int], loss: int) -> float:
        def check(v):
            a = b = 0
            for x in buckets:
                if x >= v:
                    a += x - v
                else:
                    b += (v - x) * 100 / (100 - loss)
            return a >= b
 
        l, r = 0, max(buckets)
        while r - l > 1e-5:
            mid = (l + r) / 2
            if check(mid):
                l = mid
            else:
                r = mid
        return l
 

The implementations in other languages (Java, C++, Go, TypeScript) follow a very similar structure, differing only in syntax and specific library functions. The core logic of binary search and the check function remains consistent across all implementations.