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; } }