I wanted to know an efficient algorithm to match (partition into n/2 distinct pairs) n=2k points in general position in the plane in such way that segments joining the matched points do not cross. Any idea would help out immmensely.
Mr. SRKV there is a simpler way of doing it.
Sort all the points based on the x-coordinate.
Now pair the left most point with the next left most one.
Remove the two points that we just paired.
Continue from Step 2 till there are no points left.
In case two points have the same x-coordinate. The following is the tie breaking rule.
Join the point with the lower y-coordinate to the point with the 2nd lowest y-coordinate.
If there are an odd number of points with the same x-coordinate, then we join the lone remaining point (topmost y) with the next x-coordinate(if multiple then the lowest one).
Total complexity O(nlogn) to sort and O(n) to traverse so asymptotically it is O(nlogn).
Find the convex hull.
Working your way around the hull (let's say clockwise), take adjacent pairs of vertices and add them to your set of pairs. Delete each pair from the graph as you do so. If the hull contains an even number of points, then all of them will be deleted, otherwise 1 will be left over.
If the graph still contains points, goto 1.
If each hull contains an even number of points, then it's clear that every pair of line segments found by this algorithm either came from the same hull, or from different hulls -- and either way, they will not intersect. I'm convinced it will work even when some hulls have an odd number of points.
Related
Going through a text book on Data structures and algorithms(Steven Skiena), I came across convex hull problem.
So, objective is to find convex hull for a given set of points.
Books says:
Once you have the points sorted by x-coordinate, the points can be inserted from left to
right into the hull. Since the right-most point is always on the boundary, we know that
it must appear in the hull. Adding this new right-most point may cause others to
deleted, but we can quickly identify these points because they lie inside the polygon
formed by adding the new point....
These points will be neighbors of the previous point we inserted, so they will be easy
to find and delete. The total time is linear after the sorting has been done.
I am not able to understand how is this a linear time solution after sorting is done?
Every time we add a new point, we need to check for all exiting points whether they are inside polygon or not, which goes as 1,2,3,4,5...n operations. Adding these number of operations gives O(N*N).
Am I missing something here?
Since you're constructing a polygon, you don't just have a set of points as your output, you also know which points are neighbours of which other points. There are two key things to note:
Each point can only be deleted from the hull once,
When you find a neighbour that you don't delete, you don't have to search further in that direction.
So each time you insert a point, you (possibly) remove some other points and you check at most two points that don't get removed. The total number of checks is therefore at most n for the points you delete, plus at most 2n for the neighbours you don't delete.
So you do O(n) convexity checks, and each check takes O(1) time since you only need to consider three points; hence, except for the initial sorting, the rest of the algorithm takes linear time.
Given a set of points in the plane, I want to find the smallest polygon containing all the points. More precisely, the vertices of this polygon must be a subset of the original set of points.
The easiest approach would be to find the convex hull, which can be computed in O(N log(N)) time using Graham's scanning algorithm, but I would ideally like to drop the requirement that the polygon be convex. Are there any standard approaches to this? I imagine this problem is a fair bit harder because it seems to me there is not guaranteed to be a unique solution.
Do you need the absolutely smallest area solution or just a 'fairly good' solution. If the latter then one possible algorithm would be:
1) calculate the convex hull of all your points - all these points must be vertexes of your final solution.
2) calculate the convex hull of the remaining points - repeat this process until you have no points left. You will end up with n non-intersecting convex hulls.
3) Determine (possibly by greedy algorithm), where to join these hulls to form a single contiguous path between all the points by adding pairs of lines between neighboring points in neighboring hulls and removing lines in the hulls.
This might not be the minimal area but should be a fairly good solution.
Added comment: Greedy removal from the outermost hull to the next inner one should be by removing the largest area region separating the two. Greedy removal from the second hull to the next inner one should be by 'removing' (which is actually retaining) the smallest area separating the hulls...and so on inwards swapping between largest and smallest areas...
Picture added to explain better than my 100 words.
I am currently working on implementing the closest pair of points algorithm in C++. That is, given a list of points (x, y) find the pair of points that has the smallest Euclidean distance. I have done research into this and my understanding of the algorithm is the following (please correct me if I'm wrong):
Split the array of points down the middle
Recursively find the pair of points with the minimum distance for the left and right halves.
Sort the left and right halves by y-coordinate, and compare each point on the left to its 6 closest neighbors (by y-coordinate) on the right. There is some theoretical stuff behind this, but this is my understanding of what needs to be done).
I've gotten the recursion part of the algorithm to work, but am struggling to find an efficient way to find the 6 closest neighbors on the right for each point on the left. In other words, given two sorted arrays, I need to find the 6 closest numbers in Array B for each point in array A. I assume something similar to merge sort is required here, but haven't been able to figure it out. Any help would be much appreciated.
Sounds like you want a quad tree.
Let dist = min(dist_L, dist_R) where dist_L, dist_R are the minimum distances found in the left and right sets, respectively.
Now to find the minimum distance where one point is on the left half and the other on the right half, you only need to consider points whose x-coordinates are in the interval [x_m - dist, x_m+dist].
The idea now is to consider the 6 closest points in this interval. So sort the points by y-coordinate for each point, look forward at the next 6. This will result in an O(nlog^2(n)) running time.
You can further improve upon this to O(nlogn) by speeding up the sorting process. To do this, have each recursive call also return a sorted list of the points. Then to sort the entire list, you just have to merge the two sorted lists. An observant reader would notice that this is precisely merge sort.
I'm looking for an algorithm to solve this problem:
Given N rectangles on the Cartesian coordinate, find out if the intersection of those rectangles is empty or not. Each rectangle can lie in any direction (not necessary to have its edges parallel to Ox and Oy)
Do you have any suggestion to solve this problem? :) I can think of testing the intersection of each rectangle pair. However, it's O(N*N) and quite slow :(
Abstract
Either use a sorting algorithm according to smallest X value of the rectangle, or store your rectangles in an R-tree and search it.
Straight-forward approach (with sorting)
Let us denote low_x() - the smallest (leftmost) X value of a rectangle, and high_x() - the highest (rightmost) X value of a rectangle.
Algorithm:
Sort the rectangles according to low_x(). # O(n log n)
For each rectangle in sorted array: # O(n)
Finds its highest X point. # O(1)
Compare it with all rectangles whose low_x() is smaller # O(log n)
than this.high(x)
Complexity analysis
This should work on O(n log n) on uniformly distributed rectangles.
The worst case would be O(n^2), for example when the rectangles don't overlap but are one above another. In this case, generalize the algorithm to have low_y() and high_y() too.
Data-structure approach: R-Trees
R-trees (a spatial generalization of B-trees) are one of the best ways to store geospatial data, and can be useful in this problem. Simply store your rectangles in an R-tree, and you can spot intersections with a straightforward O(n log n) complexity. (n searches, log n time for each).
Observation 1: given a polygon A and a rectangle B, the intersection A ∩ B can be computed by 4 intersection with half-planes corresponding to each edge of B.
Observation 2: cutting a half plane from a convex polygon gives you a convex polygon. The first rectangle is a convex polygon. This operation increases the number of vertices at most per 1.
Observation 3: the signed distance of the vertices of a convex polygon to a straight line is a unimodal function.
Here is a sketch of the algorithm:
Maintain the current partial intersection D in a balanced binary tree in a CCW order.
When cutting a half-plane defined by a line L, find the two edges in D that intersect L. This can be done in logarithmic time through some clever binary or ternary search exploiting the unimodality of the signed distance to L. (This is the part I don't exactly remember.) Remove all the vertices on the one side of L from D, and insert the intersection points to D.
Repeat for all edges L of all rectangles.
This seems like a good application of Klee's measure. Basically, if you read http://en.wikipedia.org/wiki/Klee%27s_measure_problem there are lower bounds on the runtime of the best algorithms that can be found for rectilinear intersections at O(n log n).
I think you should use something like the sweep line algorithm: finding intersections is one of its applications. Also, have a look at answers to this questions
Since the rectangles must not be parallel to the axis, it is easier to transform the problem to an already solved one: compute the intersections of the borders of the rectangles.
build a set S which contains all borders, together with the rectangle they're belonging to; you get a set of tuples of the form ((x_start,y_start), (x_end,y_end), r_n), where r_n is of course the ID of the corresponding rectangle
now use a sweep line algorithm to find the intersections of those lines
The sweep line stops at every x-coordinate in S, i.e. all start values and all end values. For every new start coordinate, put the corresponding line in a temporary set I. For each new end-coordinate, remove the corresponding line from I.
Additionally to adding new lines to I, you can check for each new line whether it intersects with one of the lines currently in I. If they do, the corresponding rectangles do, too.
You can find a detailed explanation of this algorithm here.
The runtime is O(n*log(n) + c*log(n)), where c is the number of intersection points of the lines in I.
Pick the smallest rectangle from the set (or any rectangle), and go over each point within it. If one of it's point also exists in all other rectangles, the intersection is not empty. If all points are free from ALL other rectangles, the intersection is empty.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How to find largest triangle in convex hull aside from brute force search
I have a set of random points from which i want to find the largest triangle by area who's verticies are each on one of those points.
So far I have figured out that the largest triangle's verticies will only lie on the outside points of the cloud of points (or the convex hull) so i have programmed a function to do just that (using Graham scan in nlogn time).
However that's where I'm stuck. The only way I can figure out how to find the largest triangle from these points is to use brute force at n^3 time which is still acceptable in an average case as the convex hull algorithm usually kicks out the vast majority of points. However in a worst case scenario where points are on a circle, this method would fail miserably.
Dose anyone know an algorithm to do this more efficiently?
Note: I know that CGAL has this algorithm there but they do not go into any details on how its done. I don't want to use libraries, i want to learn this and program it myself (and also allow me to tweak it to exactly the way i want it to operate, just like the graham scan in which other implementations pick up collinear points that i don't want).
Don't know if this help, but if you choose two points from the convex hull and rotate all points of the hull so that the connecting line of the two points is parallel to the x-Axis, either the point with the maximum or the one with the minimum y-coordinate forms the triangle with the largest area together with the two points chosen first.
Of course once you have tested one point for all possible base lines, you can remove it from the list.
Here's a thought on how to get it down to O(n2 log n). I don't really know anything about computational geometry, so I'll mark it community wiki; please feel free to improve on this.
Preprocess the convex hull by finding for each point the range of slopes of lines through that point such that the set lies completely on one side of the line. Then invert this relationship: construct an interval tree for slopes with points in leaf nodes, such that when querying with a slope you find the points such that there is a tangent through those points.
If there are no sets of three or more collinear points on the convex hull, there are at most four points for each slope (two on each side), but in case of collinear points we can just ignore the intermediate points.
Now, iterate through all pairs of points (P,Q) on the convex hull. We want to find the point R such that triangle PQR has maximum area. Taking PQ as the base of the triangle, we want to maximize the height by finding R as far away from the line PQ as possible. The line through R parallel to PQ must be such that all points lie on one side of the line, so we can find a bounded number of candidates in time O(log n) using the preconstructed interval tree.
To improve this further in practice, do branch-and-bound in the set of pairs of points: find an upper bound for the height of any triangle (e.g. the maximum distance between two points), and discard any pair of points whose distance multiplied by this upper bound is less than the largest triangle found so far.
I think the rotating calipers method may apply here.
Off the top of my head, perhaps you could do something involving gridding/splitting the collection of points up into groups? Maybe... separating the points into three groups (not sure what the best way to do that in this case would be, though), doing something to discard those points in each group that are closer to the other two groups than other points in the same group, and then using the remaining points to find the largest triangle that can be made having one vertex in each group? This would actually make the case of all points being on a circle a lot simpler, because you'd just focus on the points that are near the center of the arcs contained within each group, as those would be the ones in each group furthest from the other two groups.
I'm not sure if this would give you the proper result for certain triangles/distributions of points, though. There may be situations where the resultant triangle isn't of optimal area, either because the grouping and/or the vertex choosing aren't/isn't optimal. Something like that.
Anyway, those are my thoughts on the problem. I hope I've at least been able to give you ideas for how to work on it.
How about dropping a point at a time from the convex hull? Starting with the convex hull, calculate the area of the triangle formed by each triple of adjacent points (p1p2p3, p2p3p4, etc.). Find the triangle with minimum area, then drop the middle of the three points that formed that triangle. (In other words, if the smallest area triangle is p3p4p5, drop P4.) Now you have a convex polygon with N-1 points. Repeat the same procedure until you are left with three points. This should take O(N^2) time.
I would not be at all surprised if there is some pathological case where this doesn't work, but I expect that it would work for the majority of cases. (In other words, I haven't proven this, and I have no source to cite.)