7
votes

Trouver les carrés dans un avion donné n points

donné n points dans un avion, combien de carrés peuvent être formés ... ??

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.

Mais cela ressemble à une approche avec une très grande complexité. Toute autre idée ... ??

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 ....

Toutes meilleures idées ???

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 ...

Si possible, donnez un exemple de code pour effectuer ce qui précède ...


2 commentaires

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?


7 Réponses :


0
votes

Cela ressemble à O (n ^ 3) pour moi. Un simple algo pourrait être quelque chose comme: xxx


10 commentaires

Comment effectuez-vous le test dans O (n) ? Looks O (n ^ 4) pour moi, sauf si vous avez un moyen intelligent pour empêcher le test d'être fait dans O (n ^ 2) .


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.



5
votes

let d [i] [j] = distances entre les points I et J . Nous sommes intéressés par une fonction comptent (i, j) qui retourne, aussi vite que possible, le nombre de carrés que nous pouvons dessiner à l'aide de points i et j .

Fondamentalement, comte (i, j) devra trouver deux points x et y tel que d [i] [j] = d [x] [y] et vérifiez si ces 4 points définissent vraiment un carré.

Vous pouvez utiliser un Table de hachage pour résoudre le problème dans O (n ^ 2) en moyenne. Laissez h [x] = liste de tous les points (p, q) qui ont d [p] [q] = x .

Maintenant, pour chaque paire de points (i, j) , comte (i, j) devra itérer h [d [i] [ j]]] et compter les points de cette liste qui forment un carré avec points i et j .

Cela devrait fonctionner très vite dans la pratique, et je ne pense pas que cela puisse jamais devenir pire que O (n ^ 3) (Je ne suis même pas sûr que cela puisse jamais obtenir ce mauvais) .


1 commentaires

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] ne garantit pas que c'est un carré. Vous devriez toujours vérifier que c'est.



0
votes

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).


0 commentaires

4
votes

Ce problème peut être résolu dans O (n ^ 1.5) temps avec O (n) espace.

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).

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 O (n ^ 1.5 journal (n)) :

  1. 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.

  2. Groupe les points de leur coordonnée x. Casser tous les groupes avec plus que SQRT (N) Points à part et regroupez ces points maintenant libres par leur coordonnée y. Ceci garantit les groupes ont au plus sqrt (n) points et garantit que pour chaque carré, il y a un groupe qui a deux des points de coin carrés.

  3. pour chaque groupe g , pour chaque paire de points p, q dans g , vérifiez si les deux autres points de Les deux carrés possibles contenant p et q sont présents. Gardez une trace de combien vous trouvez. Faites attention aux doublons (sont les deux points opposés également dans un 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 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é.


4 commentaires

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?



5
votes

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>

  1. d'abord itérer par le tableau et ajoutez chaque article dans un hashset: cette action Dupliquer et nous donner une heure d'accès O (1). Tout le processus prend o (n) temps li>
  2. Utilisation de mathématiques, disons des sommets A, B, C, D peut former un carré, AC est connu et c'est une ligne diagonale, puis le B correspondant, D est unique. Nous pourrions écrire une fonction pour calculer cela. Ce processus est O (1) heure li>
  3. Revenons maintenant à notre truc. Écrivez une boucle pour i-i-boucle et une boucle à intérieure pour j. Dites l'entrée [I] et l'entrée [J] former une ligne diagonale, trouvez sa ligne anti-diagonale dans l'ensemble ou non: si elle existe, compteur ++; Ce processus prend le temps O (N ^ 2). LI> ol>

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


3 commentaires

Comment calculez-vous les points B et D? En outre, MIDX est (A.x + c.x) / 2


qr.ae/pgi3tr - suppose que cela explique l'algo ci-dessus pour geestpints () .


NE PEUT-NOUS NOUVEZ-NOUS DOUBLE?



0
votes
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.

0 commentaires

0
votes

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

}


0 commentaires