donné n points dans un avion, combien de carrés peuvent être formés ... ?? P>
J'ai essayé cela en calculant les distances entre chaque 2 points, puis triez-les et recherchez les carrés dans les points avec quatre distances égales ou plus après avoir vérifié les points et les pentes. p>
Mais cela ressemble à une approche avec une très grande complexité. Toute autre idée ... ?? p>
Je pensais que la programmation dynamique de la vérification des segments de ligne de différentes distances pourrait fonctionner ... mais ne pouvait pas avoir l'idée parfaite .... p>
Toutes meilleures idées ??? p>
P.s: Les carrés peuvent être de quelque manière que ce soit. Ils peuvent se chevaucher, avoir un côté commun, une case à l'intérieur d'une autre ... p>
Si possible, donnez un exemple de code pour effectuer ce qui précède ... p>
7 Réponses :
Cela ressemble à O (n ^ 3) pour moi. Un simple algo pourrait être quelque chose comme:
Comment effectuez-vous le test dans O (n) code>? Looks O (n ^ 4) code> pour moi, sauf si vous avez un moyen intelligent pour empêcher le test d'être fait dans O (n ^ 2) code>.
Ivlad: Il suffit de tester chacun des points N-2 pour voir s'ils coïncident avec l'un des deux sommets restants. Par conséquent, le test est O (n).
@Paul - Alors je suppose que vous supposez que vous avez les distances entre chaque paire de points précomptes, est-ce correct? Vous devriez mentionner que cela pourrait ne pas être immédiatement évident pour tout le monde.
Voici une optimisation: les points peuvent être triés par leurs coordonnées en temps linéaire par type de Radix. Le test devient alors une recherche de temps O (journal (n)). Ainsi, le temps total est O (n ^ 2 * journal (n)).
De plus, lorsque vous choisissez des paires, vous pouvez réduire de moitié le temps d'exécution en évitant de comparer la même paire deux fois. C'est toujours la même complexité, mais deux fois plus rapide néanmoins.
@IVLAD - Si vous avez 2 points, le calcul des emplacements possibles des 2 autres points peut être effectué mathématiquement. Pas besoin de précalcomputer les distances entre chaque paire de points.
@IVLAD: Non, je pense que vous manquez le point. Deux points définissent trois carrés possibles, dont les coordonnées peuvent être calculées exactement - nous recherchons simplement des points qui correspondent aux sommets, qui ne regardent pas les distances, etc.
L'autre réponse suggérée à l'aide de HASHTables. Je suppose que c'est faisable aussi. Ajoutez tous les points à une hache et effectuez votre test à travers cela. Vous serez assez proche de O (n ^ 2). Vous pourriez accéder à une o (n ^ 2) parfaite à l'aide d'un arbre de radiodes, mais c'est un peu plus complexe à mettre en œuvre.
@Vilx: Je suppose que cela dépend de savoir si vous recherchez une correspondance exacte sur les coordonnées (i.e .. Integer coordonnées uniquement) ou s'il s'agit d'un espace 2D continu et que vous disposez d'une sorte de tolérance correspondante (c'est-à-dire des coordonnées de point flottant).
@Paul r - Eh bien, l'auteur n'a pas précisé. :) Cependant, je pense que vous pouvez faire une structure de données permettant également de regarder également les valeurs à proximité. Un index pourrait le faire, peut-être un arbre de radiodes aussi.
let Fondamentalement, Vous pouvez utiliser un Table de hachage pour résoudre le problème dans Maintenant, pour chaque paire de points Cela devrait fonctionner très vite dans la pratique, et je ne pense pas que cela puisse jamais devenir pire que d [i] [j] = distances entre les points I et J code>. Nous sommes intéressés par une fonction comptent (i, j) code> qui retourne, aussi vite que possible, le nombre de carrés que nous pouvons dessiner à l'aide de points i code> et j code>. p>
comte (i, j) code> devra trouver deux points x code> et y code> tel que d [i] [j] = d [x] [y] code> et vérifiez si ces 4 points définissent vraiment un carré. P>
O (n ^ 2) code> en moyenne. Laissez h [x] = liste de tous les points (p, q) qui ont d [p] [q] = x code>. P>
(i, j) code>, comte (i, j) code> devra itérer h [d [i] [ j]]] code> et compter les points de cette liste qui forment un carré avec points i code> et j code>. p>
O (n ^ 3) code> (Je ne suis même pas sûr que cela puisse jamais obtenir ce mauvais) . p>
Notez que la condition d [i] [j] = d [x] [y] and d [i] [x] = d [j] [y] ou d [i] [y] = d [j] [y] [ ] [x] code> ne garantit pas que c'est un carré. Vous devriez toujours vérifier que c'est.
Juste une pensée: Si un sommet A est un coin d'un carré, il doit y avoir des sommets B, C, D dans les autres coins avec AB = AD et AC = SQRT (2) AB et AC doivent bisecter BD. En supposant que chaque sommet ait des coordonnées uniques, je pense que vous pouvez résoudre ce problème dans O (n ^ 2) avec une table de hachage sur (distance, angle). P>
Ce problème peut être résolu dans L'idée de base est de regrouper les points de la coordonnée X ou Y, veillez à éviter de faire des groupes trop importants. Les détails sont dans le document Rechercher des carrés et des rectangles dans ensembles de points . Le papier couvre également de nombreux autres cas (permettant des carrés tournants, permettant des rectangles et de travailler dans des dimensions plus élevées). P>
J'ai paraphrasé leur algorithme carré aligné 2D axe-aligné ci-dessous. Notez que j'ai changé leur arbre défini sur un ensemble de hachage, c'est pourquoi le temps que j'ai donné n'est pas Faites un ensemble de hachage de tous les points. Quelque chose que vous pouvez utiliser pour vérifier rapidement si un point est présent. P> li>
Groupe les points de leur coordonnée x. Casser tous les groupes avec plus que pour chaque groupe Pourquoi ça marche? Eh bien, la seule chose délicate est le regroupement. Si les colonnes gauche ou droite d'un carré sont en groupe qui ne sont pas trop grandes, le carré se retrouvera lorsque ce groupe de colonne est itéré. Sinon em> ses coins de haut à gauche et de haut à gauche sont regroupés, placés dans le groupe de la même rangée, et le carré sera trouvé lorsque ce groupe de rangée est itéré. P> O (n ^ 1.5) code> temps avec O (n) code> espace. p>
O (n ^ 1.5 journal (n)) code>: p>
SQRT (N) CODE> Points à part et regroupez ces points maintenant libres par leur coordonnée y. Ceci garantit les groupes ont au plus sqrt (n) code> points et em> garantit que pour chaque carré, il y a un groupe qui a deux des points de coin carrés. P> li>
g code>, pour chaque paire de points p, q code> dans g code>, vérifiez si les deux autres points de Les deux carrés possibles contenant p code> et q code> sont présents. Gardez une trace de combien vous trouvez. Faites attention aux doublons (sont les deux points opposés également dans un groupe?). P> Li>
ol>
Votre étape deux sonne un peu déroutant. Je ferrais le mot comme ceci: regroupez certains points par leur coordonnée X, et certains par leur coordonnée y, de sorte qu'aucun groupe ne contienne plus que les points SQRT (N).
@Yechiellabunsliy Je conviens que le libellé actuel est un peu maladroit, mais que vous omettez comment réellement atteindre le groupement. Il manque également une des conditions que les groupes doivent satisfaire: pour chaque carré, il doit y avoir l'un de ses côtés avec les deux points de coin dans le même groupe.
Votre édition semble beaucoup mieux qu'avant. Peut-être que moins de gens vont chercher le papier d'origine maintenant que votre description est meilleure
Le rapport technique de 1989 de Van Kreveld and De Berg (lié ci-dessus) a été publié ultérieurement sous la forme d'un chapitre de livre de Graphes et géométrie informatique , pp. 341-355, par Springer-Verlag (2005). Le titre est identique, mais certaines références (tous les pré-1989) sont incluses dans la version publiée (elles semblent manquantes dans le PDF lié ci-dessus). Notez que les auteurs considèrent que seulement un problème de décision, un carré (ou un rectangle) existe-t-il avec des sommets dans la partie définie?
J'ai une solution d'espace O (n ^ 2), O (n) Solution d'espace:
suppose que les points donnés sont un tableau de point d'objet, chaque point a x, y. p>
Mon code en C #: P>
public int SquareCount(Point[] input)
{
int count = 0;
HashSet<Point> set = new HashSet<Point>();
foreach (var point in input)
set.Add(point);
for (int i = 0; i < input.Length; i++)
{
for (int j = 0; j < input.Length; j++)
{
if (i == j)
continue;
//For each Point i, Point j, check if b&d exist in set.
Point[] DiagVertex = GetRestPints(input[i], input[j]);
if (set.Contains(DiagVertex[0]) && set.Contains(DiagVertex[1]))
{
count++;
}
}
}
return count;
}
public Point[] GetRestPints(Point a, Point c)
{
Point[] res = new Point[2];
int midX = (a.x + c.y) / 2;
int midY = (a.y + c.y) / 2;
int Ax = a.x - midX;
int Ay = a.y - midY;
int bX = midX - Ay;
int bY = midY + Ax;
Point b = new Point(bX,bY);
int cX = (c.x - midX);
int cY = (c.y - midY);
int dX = midX - cY;
int dY = midY + cX;
Point d = new Point(dX,dY);
res[0] = b;
res[1] = d;
return res;
}
Comment calculez-vous les points B et D? En outre, MIDX est (A.x + c.x) / 2 code>
qr.ae/pgi3tr - suppose que cela explique l'algo ci-dessus pour geestpints () code>.
NE PEUT-NOUS NOUVEZ-NOUS DOUBLE?
Runtime: O(nlog(n)^2), Space: θ(n), where n is the number of points. For each point p Add it to the existing arrays sorted in the x and y-axis respectively. For every pair of points that collide with p in the x and y-axis respectively If there exists another point on the opposite side of p, increment square count by one. The intuition is counting how many squares a new point creates. All squares are created on the creation of its fourth point. A new point creates a new square if it has any colliding points on concerned axes and there exists the "fourth" point on the opposite side that completes the square. This exhausts all the possible distinct squares.The insertion into the arrays can be done binary, and checking for the opposite point can be done by accessing a hashtable hashing the points' coordinates.This algorithm is optimal for sparse points since there will be very little collision points to check. It is pessimal for dense-squares points for the opposite of the reason for that of optimal.This algorithm can be further optimized by tracking if points in the axis array have a collision in the complementary axis.
Ceci est juste un exemple de mise en œuvre en Java - tout commentaire Bienvenue.
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
public class SweepingLine {
public static void main(String[] args) {
Point[] points = {
new Point(1,1),
new Point(1,4),
new Point(4,1),
new Point(4,4),
new Point(7,1),
new Point(7,4)
};
int max = Arrays.stream(points).mapToInt(p -> p.x).max().orElseThrow(NoSuchElementException::new);
int count = countSquares(points, max);
System.out.println(String.format("Found %d squares in %d x %d plane", count, max, max));
}
private static int countSquares(Point[] points, int max) {
int count = 0;
Map<Integer, List<Integer>> map = new HashMap<>();
for (int x=0; x<max; x++) {
for (int y=0; y<max; y++) {
for(Point p: points) {
if (p.x == x && p.y == y) {
List<Integer> ys = map.computeIfAbsent(x, _u -> new ArrayList<Integer>());
ys.add(y);
Integer ley = null;
for (Integer ey: ys) {
if (ley != null) {
int d = ey - ley;
for (Point p2: points) {
if (x + d == p2.x && p2.y == ey){
count++;
}
}
}
ley = ey;
}
}
}
}
}
return count;
}
private static class Point {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}
Les coordonnées sont-elles des entiers ou des points flottants?
Les carrés sont constitués de segments de ligne et non des points, de sorte que cette question fait du sentiment de Litte - que voulez-vous dire? Quelle est la taille d'un nombre important de ses verticaux dans l'ensemble des points? Combien de carrés contiennent un ensemble de points différents? Combien de carrés peuvent couvrir les points?