Number Of Ships In A Rectangle

Solution For Number Of Ships In A Rectangle

Problem Statement

Given two arrays, horizontalCuts and verticalCuts, where horizontalCuts[i] represents a cut along the line y = horizontalCuts[i], and verticalCuts[j] represents a cut along the line x = verticalCuts[j], you have to find the maximum area of a rectangle formed by the cuts and count the number of such rectangles. Since the answer can be very large, you have to return the answer modulo 10^9 + 7.

Solution

In order to solve this problem, we need to find the coordinates of all the corners of the rectangles formed by the cuts. If we have the coordinates of all the corners, we can calculate the area of each rectangle and find the one with the maximum area. Additionally, we can also count the number of rectangles with the maximum area.

Step 1: Find the coordinates of all corners

To find the coordinates of all the corners, we need to sort the arrays horizontalCuts and verticalCuts in ascending order and then add 0 and the maximum value of height and width to the respective arrays. This will ensure that we have all the corners in the arrays.

For example, if we have horizontalCuts = [1,3,2] and verticalCuts = [3,1], then after sorting and adding the maximum values, the arrays become horizontalCuts = [0, 1, 2, 3, height] and verticalCuts = [0, 1, 3, width].

We can then iterate over the sorted arrays and create a list of all the corner points. For example, using the above input, the list of corner points would be [(0, 0), (1, 0), (2, 0), (3, 0), (height, 0), (0, 1), (1, 1), (2, 1), (3, 1), (height, 1), (0, 3), (1, 3), (2, 3), (3, 3), (height, 3), (0, width), (1, width), (2, width), (3, width), (height, width)]. We can store these points in a list in the format [(x1,y1), (x2,y2), …].

Step 2: Find the area of each rectangle

To find the area of each rectangle, we can iterate over the list of corner points and calculate the distance between adjacent points. We only need to consider adjacent points that have the same x-coordinate or y-coordinate, as those will form the sides of a rectangle. For example, using the above list of corner points, we can calculate the area of the first rectangle as (1-0) * (1-0) = 1 and its sides are formed by the points (0,0), (1,0), (1,1), and (0,1).

Step 3: Find the maximum area

After calculating the area of each rectangle, we can find the maximum area and the number of rectangles with the maximum area. To do this, we can iterate over the list of areas and keep track of the maximum area and the number of rectangles with that area.

Code Implementation

Here is the Python code for the solution:

“`
class Solution:
def maxArea(self, height: int, width: int, horizontalCuts: List[int], verticalCuts: List[int]) -> int:
mod = 10**9 + 7
horizontalCuts.sort()
verticalCuts.sort()
horizontalCuts.append(height)
verticalCuts.append(width)

    corners = []
    for x in horizontalCuts:
        for y in verticalCuts:
            corners.append((x, y))

    corners.append((0, 0))
    corners.sort()
    max_area = 0
    max_count = 0
    for i in range(1, len(corners)):
        x1, y1 = corners[i-1]
        x2, y2 = corners[i]
        if x1 == x2:
            width = y2 - y1
            max_area = max(max_area, width * (x1 - corners[i-2][0]))
        elif y1 == y2:
            height = x2 - x1
            max_area = max(max_area, height * (y1 - corners[i-2][1]))

    for i in range(1, len(corners)):
        x1, y1 = corners[i-1]
        x2, y2 = corners[i]
        if x1 == x2:
            width = y2 - y1
            if max_area == width * (x1 - corners[i-2][0]):
                max_count += 1
        elif y1 == y2:
            height = x2 - x1
            if max_area == height * (y1 - corners[i-2][1]):
                max_count += 1

    return max_area % mod, max_count % mod

“`

Time Complexity

The sorting of the two arrays takes O(n log n) time, where n is the length of the array. Iterating over all the corner points takes O(n^2) time, but in practice, the number of corner points is typically much smaller than the square of the length of the arrays. Therefore, we can consider the time complexity to be O(n log n).

Space Complexity

The space complexity of the solution is O(n), where n is the number of corner points. This is because we store all the corner points in a list.

Step by Step Implementation For Number Of Ships In A Rectangle

/**
 * // This is Sea's API interface.
 * // You should not implement it, or speculate about its implementation
 * interface Sea {
 *     public boolean hasShips(int[] topRight, int[] bottomLeft);
 * }
 */

class Solution {
    public int countShips(Sea sea, int[] topRight, int[] bottomLeft) {
        // check if the area is valid
        if (topRight[0] < bottomLeft[0] || topRight[1] < bottomLeft[1]) {
            return 0;
        }
        // base case - when the area is 1x1
        if (topRight[0] == bottomLeft[0] && topRight[1] == bottomLeft[1]) {
            return sea.hasShips(topRight, bottomLeft) ? 1 : 0;
        }
        // recursive case - divide the area into 4 smaller areas
        int midX = (topRight[0] + bottomLeft[0]) / 2;
        int midY = (topRight[1] + bottomLeft[1]) / 2;
        return countShips(sea, new int[] {midX, midY}, bottomLeft) + // bottom left
               countShips(sea, topRight, new int[] {midX + 1, midY + 1}) + // top right
               countShips(sea, new int[] {midX, topRight[1]}, new int[] {bottomLeft[0], midY + 1}) + // top left
               countShips(sea, new int[] {topRight[0], midY}, new int[] {midX, bottomLeft[1]}); // bottom right
    }
}
def countShips(sea, topRight, bottomLeft):
    # Base case
    if topRight[0] < bottomLeft[0] or topRight[1] < bottomLeft[1]:
        return 0

    # If only one cell
    if topRight[0] == bottomLeft[0] and topRight[1] == bottomLeft[1]:
        return sea[topRight[0]][topRight[1]]

    # Divide the current rectangle into 4 smaller rectangles
    rowMid = (topRight[0] + bottomLeft[0]) // 2
    colMid = (topRight[1] + bottomLeft[1]) // 2

    # Recurse on each of the smaller rectangles
    # The 4 rectangles are:
    #  topLeft     topRight
    #  bottomLeft  bottomRight
    topLeft = countShips(sea, [rowMid, colMid], bottomLeft)
    topRight = countShips(sea, topRight, [rowMid + 1, colMid])
    bottomLeft = countShips(sea, [rowMid, colMid + 1], bottomLeft)
    bottomRight = countShips(sea, topRight, [rowMid + 1, colMid + 1])

    # Return the sum of ships in the 4 rectangles
    return topLeft + topRight + bottomLeft + bottomRight
/**
 * @param {Sea} sea
 * @param {Point} topRight
 * @param {Point} bottomLeft
 * @return {number}
 */
const countShips = function(sea, topRight, bottomLeft) {
    // check if topRight and bottomLeft are valid points
    if (!isValidPoint(topRight) || !isValidPoint(bottomLeft)) {
        return 0;
    }
    
    // check if topRight and bottomLeft have the same x or y coordinate
    if (topRight.x === bottomLeft.x || topRight.y === bottomLeft.y) {
        return 1;
    }
    
    // find the midpoint between topRight and bottomLeft
    const midX = Math.floor((topRight.x + bottomLeft.x) / 2);
    const midY = Math.floor((topRight.y + bottomLeft.y) / 2);
    
    // create a point for the midpoint
    const midPoint = new Point(midX, midY);
    
    // find the number of ships in each quadrant and add them together
    const topRightShips = countShips(sea, topRight, midPoint);
    const bottomLeftShips = countShips(sea, midPoint, bottomLeft);
    const topLeftShips = countShips(sea, new Point(midX, topRight.y), new Point(bottomLeft.x, midY));
    const bottomRightShips = countShips(sea, new Point(topRight.x, midY), new Point(midX, bottomLeft.y));
    
    return topRightShips + bottomLeftShips + topLeftShips + bottomRightShips;
};
int countShips(Sea sea, int top, int right, int bottom, int left) 
{ 
    // Base case 
    if (sea.isEmpty() || top > bottom || right < left) 
        return 0; 
  
    // If there is only one row or column 
    if (top == bottom) 
    { 
        // If there is only one column 
        if (right == left) 
        { 
            // If (top, left) is 1 
            if (sea.hasShip(top, left)) 
                return 1; 
            else
                return 0; 
        } 
  
        // If there are more than one columns 
        int count = 0; 
        for (int i = left; i <= right; i++) 
            if (sea.hasShip(top, i)) 
                count++; 
        return count; 
    } 
  
    // If there are more than one rows 
    if (right == left) 
    { 
        // If there are more than one rows 
        int count = 0; 
        for (int i = top; i <= bottom; i++) 
            if (sea.hasShip(i, left)) 
                count++; 
        return count; 
    } 
  
    // If there are more than one rows and columns 
    int midRow = top + (bottom - top)/2; 
    int midCol = left + (right - left)/2; 
  
    // Check top-left, top-right, bottom-left and bottom-right 
    // quadrants separately 
    return countShips(sea, top, midCol, midRow, left) + 
           countShips(sea, top, right, midRow, midCol+1) + 
           countShips(sea, midRow+1, midCol, bottom, left) + 
           countShips(sea, midRow+1, right, bottom, midCol+1); 
}
using System; 

namespace LeetCode 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            Console.WriteLine("Hello World!"); 
        } 
    } 
} 

//This is a C# solution for the leetcode problem "Number of Ships in a Rectangle"

/*

We have a number of ships, each ship has a start point (x, y) and an end point (x, y).

We need to find the number of ships that are in a given rectangle.

The rectangle is defined as follows:

x1 <= x <= x2 and y1 <= y <= y2

where (x1, y1) are the coordinates of the bottom-left corner of the rectangle and (x2, y2) are the coordinates of the top-right corner of the rectangle.

Note that the rectangle may be rotated, so the coordinates of the bottom-left corner and the top-right corner may be swapped.

Example 1:

Input: ships = [[1,1],[2,2],[3,3],[5,5]], topRight = [4,4], bottomLeft = [0,0]
Output: 3
Explanation: From the top-left to the bottom-right, we have 3 ships.
Example 2:

Input: ships = [[1,1],[2,2],[3,3],[5,5]], topRight = [2,2], bottomLeft = [1,1]
Output: 1
Explanation: We only have one ship.
Example 3:

Input: ships = [[1,1],[2,2],[3,3],[5,5]], topRight = [5,5], bottomLeft = [0,0]
Output: 4
Explanation: All 4 ships are in the rectangle.

*/

public class Solution {
    public int CountShips(Sea sea, Point topRight, Point bottomLeft) {
        
        //if the rectangle contains no ships, return 0
        if(!sea.hasShips(topRight, bottomLeft))
            return 0;
        
        //if the rectangle contains only one ship, return 1
        if(topRight.x == bottomLeft.x && topRight.y == bottomLeft.y)
            return 1;
        
        //if the rectangle is not rotated and contains more than one ship
        //divide the rectangle into 4 smaller rectangles and recurse
        if(topRight.x > bottomLeft.x && topRight.y > bottomLeft.y){
            int xmid = bottomLeft.x + (topRight.x - bottomLeft.x)/2;
            int ymid = bottomLeft.y + (topRight.y - bottomLeft.y)/2;
            
            return CountShips(sea, new Point(xmid, ymid), bottomLeft) +
                   CountShips(sea, topRight, new Point(xmid+1, ymid+1)) +
                   CountShips(sea, new Point(xmid, topRight.y), new Point(xmid+1, ymid+1)) +
                   CountShips(sea, new Point(bottomLeft.x, ymid), new Point(xmid, ymid+1));
        }
        
        //if the rectangle is rotated and contains more than one ship
        //divide the rectangle into 4 smaller rectangles and recurse
        if(topRight.x < bottomLeft.x && topRight.y > bottomLeft.y){
            int xmid = bottomLeft.x + (topRight.x - bottomLeft.x)/2;
            int ymid = bottomLeft.y + (topRight.y - bottomLeft.y)/2;
            
            return CountShips(sea, new Point(xmid, ymid), new Point(bottomLeft.x, bottomLeft.y)) +
                   CountShips(sea, new Point(topRight.x, topRight.y), new Point(xmid+1, ymid+1)) +
                   CountShips(sea, new Point(xmid, topRight.y), new Point(bottomLeft.x, ymid+1)) +
                   CountShips(sea, new Point(topRight.x, ymid), new Point(xmid+1, bottomLeft.y));
        }
        
        //if the rectangle is not rotated and contains more than one ship
        //divide the rectangle into 2 smaller rectangles (vertically or horizontally) and recurse
        if(topRight.x > bottomLeft.x && topRight.y < bottomLeft.y){
            int xmid = bottomLeft.x + (topRight.x - bottomLeft.x)/2;
            
            return CountShips(sea, new Point(xmid, topRight.y), bottomLeft) +
                   CountShips(sea, topRight, new Point(xmid+1, bottomLeft.y));
        }
        
        //if the rectangle is rotated and contains more than one ship
        //divide the rectangle into 2 smaller rectangles (vertically or horizontally) and recurse
        if(topRight.x < bottomLeft.x && topRight.y < bottomLeft.y){
            int ymid = bottomLeft.y + (topRight.y - bottomLeft.y)/2;
            
            return CountShips(sea, new Point(topRight.x, ymid), new Point(bottomLeft.x, bottomLeft.y)) +
                   CountShips(sea, new Point(topRight.x, topRight.y), new Point(bottomLeft.x, ymid+1));
        }
        
        return 0;
    }
}


Scroll to Top
[gravityforms id="5" description="false" titla="false" ajax="true"]