Maximum area rectangle - algorithm

Given set of points (x[1]; y[1]), (x[2]; y[2]), ..., (x[n]; y[n]) . We need to find maximum area of rectangle that we can get. Rectangle's vertexes should be in points set. Also, rectangle is not necessary be axis-aligned. For example, answer for (1; 1), (2; 2), (2; 0); (3; 1) is 2.
n <= 1300; -10^9 <= x[i], y[i] <= 10^9.
Can someone help me with this problem? My solution is brute-force O(N^3), it's giving TLE. I select some three points and find fourth.

Every pair of points determines a line L, which has a slope m and an intercept c. (Ignore vertical lines for now.) Instead of considering the intercept, let's work with a different quantity that gives much the same information: The distance d(L) between the line and the origin, i.e., the length of a line segment R perpendicular to L and connecting L to the origin. Additionally, we can talk about the "displacement" of a point along L: We can say that the point p on L where it meets R has displacement 0, and the point on L that is x "above" p (has distance x from p and higher y coordinate) has displacement x, with negative displacements for points "below" p. In fact, we don't need the intercept or d(L) to define the displacement of a point with respect to a line L -- just the line's slope. Define disp(m, q) to be the displacement of point q on a line with slope m.
Suppose a, b, c, d are the vertices of a rectangle, with sides ab, bc, cd and da. Observe that the line containing ab has the same slope m as the line containing cd, and (disp(m, a), disp(m, b)) = (disp(m, d), disp(m, c)). So the only 4-tuples of vertices that we need to test are those comprised of pairs of vertex pairs like ab and cd -- vertex pairs having the same slope and displacement pairs. Furthermore, one side length (shared by ab and cd) is equal to |disp(m, b) - disp(m, a)|, and the other side length will be |d(Lab) - d(Lcd)|, where Lab and Lcd are the lines containing the line segments ab and cd, respectively.
To find these 4-tuples of vertices efficiently:
For all pairs of vertices i, j:
Let L be the line passing through i and j. Compute its slope m and distance d(L) from the origin. Also compute disp(m, i) and disp(m, j). If disp(m, i) <= disp(m, j), add the tuple (m, disp(m, i), disp(m, j), d(L)) to an array Z.
Sort Z lexicographically. This will place all point pairs lying on lines of the same slope and having equal displacements in a contiguous block, ordered by increasing d(L).
Scan through the array, looking for block boundaries -- positions k at which any of the first three tuple elements changes. Let prev be the last such k found (initially, prev = 0). For each such k:
Compute (Z[k-1][3] - Z[prev][3]) * (Z[k-1][2] - Z[k-1][1]). This is the area of the largest rectangle having a pair of sides with slope Z[k-1][0] and length (Z[k-1][2] - Z[k-1][1]). If this is greater than the maximum rectangle size found so far, update it.
This algorithm takes O(n^2 log n) time and O(n^2) space.

Related

Algorithm to test if two line segments on a 2d grid are adjacent

Given two line segments on a 2D grid (horizontal or vertical), how can I determine if they are adjacent?
Two line segments A, B are adjacent if there exists at least one pair of points (ax, ay) in A and (bx, by) in B that are adjacent.
Two points are adjacent if they are adjacent in the horizontal or vertical direction. Diagonals do not count.
It can be assumed that the line segments do not intersect and the length is >= 1.
Clearly a naive solution would be to loop through the points and check for adjacency but I'm looking for a closed form solution in constant time.
For example these line segments are adjacent:
B
AB
AB
AB
B
as are these
A
ABBB
A
but these are not (note the space)
BBB
A
A
A
A horizontal or vertical line segment on a 2d grid can be represented as a tuple (x, y, length, vertical) where vertical is a boolean indicating the length of the line. Alternatively, such a line segment could be represented as (x0, y0, x1, y1) where either x0 = x1 or y0 = y1.
We can reduce this problem to computing the Manhattan distance between two axis-aligned rectangles.
The key observation is that the dimensions are separable, specifically, the Manhattan distance is the Manhattan distance of the x intervals (in 1D) plus the Manhattan distance of the y intervals.
The Manhattan distance between 1D intervals [a, b] and [c, d] is max(max(a, c) − min(b, d), 0).
The overall test is max(max(x0, x0′) − min(x1, x1′), 0) + max(max(y0, y0′) − min(y1, y1′), 0) = 1.
For any line the line itself and its adjacent (including diagonally) points form a rectangle as e.g.:
++++++ +++
+----+ +|+
++++++ +|+
+++
For a line (x0, y0, x1, y1) this rectangle is defined by the coordinates (x0 - 1, y0 - 1, x1 + 1, y1 + 1), let's name them (X0, Y0, X1, Y1). You now just need to check if these rectangles intersect:
A:X0 <= B:X1 and B:X0 <= A:X1
and A:Y0 <= B:Y1 and B:Y0 <= A:Y1
This yet includes diagonal adjacency, though, so you need to check this case explicitly:
A:X0 == B:X1
A:X1 == B:X0
A:Y0 == B:Y1
A:Y1 == B:Y0
Just count how many of these equations apply, if exactly two of do so (more is not possible...), then the rectangles only intersect in a pair of corners, thus the lines are only diagonally adjacent.

Searching for K minimum distances between points in 3D

I have two disjoint-sets of points in 3D. I need to find the k pair of points with the minimum distances. Each point has (x, y, z) coordinates.
Constaints: The solution has to be a serial optimal solution. No multithreading please. Approaches such as divide and conquer/dynamic programming can be used.
My current approach is:
listOfPairs = []
for all points a in setA
for all points b in setB
distance = calcDistance(a, b)
listOfPairs.append((a, b, distance))
sortByDistance(distance) // using the built in sort method
PrintPointsAndDistances(listOfPairs, k) // print the first k elements
Thanks.
This can be done with a priority queue. As you have done
priorityQueue = PriorityQueue(k) // of size k
for all points a in setA
for all points b in setB
distance = calcDistance(a, b)
priorityQueue.push_with_priority((a, b), distance)
What you are left are the k shortest distance pairs, and the algorithm will run in Θ(N*log(k))

Algorithm to find if triangles formed by set of points contains origin or not and give total count as well?

Input: S = {p1, . . . , pn}, n points on 2D plane each point is given by its x and y-coordinate.
For simplicity, we assume:
The origin (0, 0) is NOT in S.
Any line L passing through (0, 0) contains at most one point in S.
No three points in S lie on the same line.
If we pick any three points from S, we can form a triangle. So the total number of triangles that can be formed this way is Θ(n^3).
Some of these triangles contain (0, 0), some do not.
Problem: Calculate the number of triangles that contain (0, 0).
You may assume we have an O(1) time function Test(pi, pj , pk) that, given three points pi, pj , pk in S, returns 1, if the triangle formed by {pi, pj , pk} contains (0, 0), and returns 0 otherwise. It’s trivial to solve the problem in Θ(n^3) time (just enumerate and test all triangles).
Describe an algorithm for solving this problem with O(n log n) run time.
My analysis of the above problem leads to the following conclusion
There are 4 coordinates ( + ,+ ) , ( + ,- ) , ( -, - ), ( -, + ) { x and y coordinate > 0 or not }.
Let
s1 = coordinate x < 0 and y > 0
s2 = x > 0 , y > 0
s3 = x < 0 , y < 0
s4 = x > 0 , y < 0
Now we need to do the testing of points in between sets of the following combinations only
S1 S2 S3
S1 S1 S4
S2 S2 S3
S3 S3 S2
S1 S4 S4
S1 S3 S4
S1 S2 S4
S2 S3 S4
I now need to test the points in the above combination of sets only ( e.g. one point from s1 , one point from s2 and one point from s3 < first combinaton > ) and see the points contain (0,0) by calling Test function ( which is assumed as constant time function here) .
Can someone guide me on this ?
Image added below for clarification on why only some subsets (s1,s2 , s4 ) can contain (0,0) and some ( s1,s1,s3) cannot.
I'm guessing we're in the same class (based on the strange wording of the question), so now that the due date is past, I feel alright giving out my solution. I managed to find the n log n algorithm, which, as the question stated, is more a matter of cleverly transforming the problem, and less of a Dynamic Programming / DaC solution.
Note: This is not an exhaustive proof, I leave that to you.
First, some visual observations. Take some triangle that obviously contains the origin.
Then, convert the points to vectors.
Convince yourself that any selection of three points, one from each vector, describes a triangle that also contains the origin.
It also follows that, if you perform the above steps on a triangle that doesn't enclose the origin, any combination of points along those vectors will also not contain the origin.
The main point to get from this is, the magnitude of the vector does not matter, only the direction. Additionally, a hint to the question says that "any line crossing (0,0) only contains one point in S", from which we can extrapolate that the direction of each vector is unique.
So, if only the angle matters, it would follow that there is some logic that determines what range of points, given two points, could possibly form a triangle that encloses the origin. For simplicity, we'll assume we've taken all the points in S and converted them to vectors, then normalized them, effectively making all points lie on the unit circle.
So, take two points along this circle.
Then, draw a line from each point through the origin and to the opposite side of the circle.
It follows that, given the two points, any point that lies along the red arc can form a triangle.
So our algorithm should do the following:
Take each point in S. Make a secondary array A, and for each point, add the angle along the unit circle (atan2(x,y)) to A (0 ≤ Ai ≤ 2π). Let's assume this is O(n)
Sort A by increasing. O(n log n), assuming we use Merge Sort.
Count the number of triangles possible for each pair (Ai,Aj). This means that we count the number of Ai + π ≤ Ak ≤ Aj + π. Since the array is sorted, we can use a Binary Search to find the indices of Ai + π and Aj + π, which is O(2 log n) = O(log n)
However, we run into a problem, there are n^2 points, and if we have to do an O(log n) search for each, we have O(n^2 log n). So, we need to make one more observation.
Given some Ai < Aj, we'll say Tij describes the number of triangles possible, as calculated by the above method. Then, given a third Ak > Aj, we know that Tij ≤ Tik, as the number of points between Ai + π and Ak + π must be at least as many as there are betwen Ai + π and Aj + π. In fact, it is exactly the count between Ai + π and Aj + π, plus the count between Aj + π and Ak + π. Since we already know the count between Ai + π and Aj + π, we don't need to recalculate it - we only need to calculate the number between Aj + π and Ak + π, then add the previous count. It follows that:
A(n) = count(A(n),A(n-1)) + count(A(n-1),A(n-2)) + ... + count(A(1),A(0))
And this means we don't need to check all n^2 pairs, we only need to check consecutive pairs - so, only n-1.
So, all the above can give us the following psuedocode solution.
int triangleCount(point P[],int n)
int A[n], C[n], totalCount = 0;
for(i=0...n)
A[i] = atan2(P[i].x,P[i].y);
mergeSort(A);
int midPoint = binarySearch(A,π);
for(i=0...midPoint-1)
int left = A[i] + π, right = A[i+1] + π;
C[i] = binarySearch(a,right) - binarySearch(a,left);
for(j=0...i)
totalCount += C[j]
return totalCount;
It seems that in the worst case there are Θ(n3) triangles containing the origin, and since you need them all, the answer is no, there is no better algorithm.
For a worst case consider a regular polygon of an odd degree n, centered at the origin.
Here is an outline of the calculations. A chord connecting two vertices which are k < n/2 vertices apart is a base for Θ(k) triangles. Fix a vertex; its contribution is a sum over all chords coming from it, yielding Θ(n2), and a total (a contribution of all n vertices) is Θ(n3) (each triangle is counted 3 times, which doesn't affect the asymptotic).

Finding the largest interval using Dynamic programming

http://www.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/05-dynprog.pdf
I was doing these questions for practice where I came across one that stumped me.
7.(a) Suppose we are given a set L of n line segments in the plane, where each segment has one endpoint on the line y = 0 and one endpoint
on the line y = 1, and all 2n endpoints are distinct. Describe and
analyze an algorithm to compute the largest subset of L in which no
pair of segments intersects.
(b) Suppose we are given a set L of n line segments in the plane,
where the endpoints of each segment lie on the unit circle x 2 + y 2 =
1, and all 2n endpoints are distinct. Describe and analyze an
algorithm to compute the largest subset of L in which no pair of
segments intersects.
I figured out how to do 7a, (the question is a disguised problem to find the largest subset of increasing numbers), in O(n log n) time. Im almost close to giving up on 7b, as I cant figure out a way to do it.
However, is there a way to convert 7b's premise to something more like 7a's? I feel like that's the right way of approaching the problem, and any help in figuring this out would be much appreciated.
I couldn't come up with an O(n*log(n)) algorithm, but here is an O(n2) one.
The idea is that we build a directed graph with vertices representing segments from the given set and edges representing the "lies to the right of" relation.
Let L be the list of segments: {(a1, b1), (a2, b2), ..., (an, bn)}, where ak and bk are k-th segment's endpoints.
Let L' be the list of segments: {(a1, b1), (b1, a1), (a2, b2), (b2, a2), ..., (an, bn), (bn, an)}.
Let the vertices of the graph have indices from 1 to 2*n, each index k representing the segment L'[k], i.e. (ak/2, bk/2) if k is odd, and (bk/2, ak/2) if k is even.
A segment (a1, b1) is said to lie to the right of a segment (a2, b2) when the points a1, a2, b2, b1 are placed in a clockwise order on the unit circle.
Note that 1) If one segment lies to the right of another, they don't intersect; 2) If two segments from L don't intersect, two of the four corresponding segments from L' necessarily lie one to the right of another; 3) Any set of non-intersecting segments from L is defined by a series of segments of L', each lying to the right of the previous one.
Outline of the algorithm:
for every k1 from 1 to 2*n:
for every k2 from 1 to 2*n:
if (L'[k1].a, L'[k1].b) lies to the right of (L'[k2].a, L'[k2].b):
add a directed edge (k1, k2) to the graph
Find the longest path in the graph: (k1, k2, ..., km).
The answer to the problem is: (k1/2, k2/2, ..., km/2).
Here is an O(n2) algorithm.
We have 2n endpoints on the circle. Pick any point and start labeling the points in increasing order starting from 1 in clockwise direction. So, we have points labeled from 1 to 2n. Thus, any line segment l can be represented as (i,j) where i and j are endpoints of l and 1≤i<j≤2n.
Let Li,j be a subset of L such that l=(a,b) ∈ Li,j if i ≤ a < b ≤ j. Also, define D[i,j] for 1 ≤ i ≤ j ≤ 2n as the maximum number of non-intersecting lines in Li,j. We need to find D[1,2n].
We use dynamic programming here. Initialize D[i,i] as 0 and D[i,i+1] as 1 if (i,i+1) is a line segment, otherwise set it as 0. We can build D using the following:
if (i,j) is a line segment :
D[i,j] = D[i+1,j-1]+1
else if (i,k) is a line segment and i<k<j :
D[i,j] = max(D[i,j] , D[i+1,k-1]+D[k+1,j]+1)
else if (k,j) is a line segment and i<k<j :
D[i,j] = max(D[i,j] , D[i,k-1]+D[k+1,j-1]+1)
else :
D[i,j] = max(D[i,j] , D[i+1,j-1])
Since D occupies O(n2) space and we compute each cell of D in constant time the time complexity of the algorithm is O(n2).
Reference:
http://www.cs.toronto.edu/~robere/csc373h/files/A2-sol.pdf
Look under the heading Line Intersections (Redux)
Create two lists. The first list has the ordering created by sweeping counter-clockwise around the circle starting at (1,0). The first endpoint of a segment you hit is marked. The second list is ordered the same, but go clockwise around the circle. In this manner, you now have two lists where the segment endpoints show an ordering for intersection. For example, if the first point in the first list doesn't have its corresponding endpoint first in the second list, then it will intersect with all of the segments which appear before it in the second list. (You need to be careful here in that both points for a line can be before the end of your segment. A simple check eliminates this.) You can then just run the list. The total complexity of this approach seems to be O(n log n) for each list creation and O(n) for running the list.

Computational Geometry set of points algorithm

I have to design an algorithm with running time O(nlogn) for the following problem:
Given a set P of n points, determine a value A > 0 such that the shear transformation (x,y) -> (x+Ay,y) does not change the order (in x direction) of points with unequal x-coordinates.
I am having a lot of difficulty even figuring out where to begin.
Any help with this would be greatly appreciated!
Thank you!
I think y = 0.
When x = 0, A > 0
(x,y) -> (x+Ay,y)
-> (0+(A*0),0) = (0,0)
When x = 1, A > 0
(x,y) -> (x+Ay,y)
-> (1+(A*0),0) = (1,0)
with unequal x-coordinates, (2,0), (3,0), (4,0)...
So, I think that the begin point may be (0,0), x=0.
Suppose all x,y coordinates are positive numbers. (Without loss of generality, one can add offsets.) In time O(n log n), sort a list L of the points, primarily in ascending order by x coordinates and secondarily in ascending order by y coordinates. In time O(n), process point pairs (in L order) as follows. Let p, q be any two consecutive points in L, and let px, qx, py, qy denote their x and y coordinate values. From there you just need to consider several cases and it should be obvious what to do: If px=qx, do nothing. Else, if py<=qy, do nothing. Else (px>qx, py>qy) require that px + A*py < qx + A*qy, i.e. (px-qx)/(py-qy) > A.
So: Go through L in order, and find the largest A' that is satisfied for all point pairs where px>qx and py>qy. Then choose a value of A that's a little less than A', for example, A'/2. (Or, if the object of the problem is to find the largest such A, just report the A' value.)
Ok, here's a rough stab at a method.
Sort the list of points by x order. (This gives the O(nlogn)--all the following steps are O(n).)
Generate a new list of dx_i = x_(i+1) - x_i, the differences between the x coordinates. As the x_i are ordered, all of these dx_i >= 0.
Now for some A, the transformed dx_i(A) will be x_(i+1) -x_i + A * ( y_(i+1) - y_i). There will be an order change if this is negative or zero (x_(i+1)(A) < x_i(A).
So for each dx_i, find the value of A that would make dx_i(A) zero, namely
A_i = - (x_(i+1) - x_i)/(y_(i+1) - y_i). You now have a list of coefficients that would 'cause' an order swap between a consecutive (in x-order) pair of points. Watch for division by zero, but that's the case where two points have the same y, these points will not change order. Some of the A_i will be negative, discard these as you want A>0. (Negative A_i will also induce an order swap, so the A>0 requirement is a little arbitrary.)
Find the smallest A_i > 0 in the list. So any A with 0 < A < A_i(min) will be a shear that does not change the order of your points. Pick A_i(min) as that will bring two points to the same x, but not past each other.

Resources