Problem Description
Given a rectangular region defined by its bottom left and top right coordinates, determine the number of ships located within that rectangle. You can only use the provided API function Sea.hasShips(topRight, bottomLeft) which returns whether there is at least one ship in the given rectangle. Note that each ship is at an integer coordinate and at most 10 ships are present in the overall region. The challenge is to efficiently count ships using at most 400 API calls.
Key Insights
- Use a divide-and-conquer approach by recursively partitioning the search area into smaller subrectangles.
- If the API call Sea.hasShips returns false for a given rectangle, that entire region can be skipped.
- When the rectangle is reduced to a single point (bottomLeft equals topRight) and a ship exists there, count it as 1.
- Careful partitioning minimizes the number of API calls, keeping the solution within the call limit.
- The constraint of at most 10 ships guarantees that deep recursion happens only along branches that actually contain a ship.
Space and Time Complexity
Time Complexity: O(4^(min(log(range width), log(range height)))) in the worst-case scenario, but practically it is much lower due to pruning from the hasShips API and the small number of ships. Space Complexity: O(log(max(range width, range height))) due to recursion stack depth.
Solution
We solve the problem using a recursive, divide-and-conquer algorithm. At each step, we check if the rectangle (defined by bottomLeft and topRight) contains any ships using the Sea.hasShips API. If not, we return 0. If the rectangle is a single point and a ship exists there, we return 1. Otherwise, we split the rectangle into four smaller subrectangles by calculating the midpoints along the x- and y-axes.
The four subrectangles (if valid) are:
- Bottom-left quadrant: from bottomLeft to (midX, midY)
- Top-right quadrant: from (midX+1, midY+1) to topRight
- Top-left quadrant: from (bottomLeft.x, midY+1) to (midX, topRight.y)
- Bottom-right quadrant: from (midX+1, bottomLeft.y) to (topRight.x, midY)
The recursive calls are only made on subrectangles that are valid (i.e. the bottom left coordinates are not greater than the top right ones). This minimization of searches ensures we do not exceed the allowed API calls.