barrett@ruth:~$ /algorithms

Two Pointers

technique overview

Sometimes, the mathematical solution is the simplest.

The area of a container bounded by the ground and its columns at positions \((l, r)\) is: \[ \text{area} = \text{width} \cdot \text{length} = (r - l) \cdot \min\{height[l], height[r]\} \]

At its core, this is a maximization problem: maximize the contained area. \[ \max\{(r - l) \cdot \min\{height[l], height[r]\}\} \]

Given a new column position \(l_0 < l\) or \(r_0 < r\), the contained area can only increase if the height of the corresponding column increases.

The following correct solution surveys all containers, initialized with the widest columns positions, that are valid candidates for a potentially new largest area. A running maximizum, the answer, is maintained.

def maxArea(height: list[int]) -> int:
    ans = 0
    l, r = 0, len(height) - 1

    while l < r:
        width, min_height = r - l, min(height[l], height[r])
        ans = max(ans, width * min_height)

        while l < r and height[l] <= min_height:
            l += 1
        while l < r and height[r] <= min_height:
            r -= 1

    return ans

Usually, the metaphorical problem description is a distraction. However, I find that thinking within the confines of "boats" and "people" yields an intuitive solution in this case.

Since only two people can fit in a boat at a time, pairing up lightest and heaviest individuals will result in the least amount of boats being used.

However, the weights are given in random order. Efficiently pairing up the lightest and heaviest individuals, then, requires the most common two-pointers prepreocessing step: sorting.

Finally, flesh out any remaining aspects of the implementation:

  1. If one person remains, give them a boat.
  2. If both people don't fit, use the heavier person—the lighter could maybe fit with someone else.
def minimum_rescue_boats(people: list[int], limit: int) -> int:
    ans = 0
    l, r = 0, len(people) - 1

    people.sort()

    while l <= r:
        if l == r:
            ans += 1
            break
        elif people[l] + people[r] <= limit:
            ans += 1
            l += 1
            r -= 1
        else:
            ans += 1
            r -= 1

    return ans