简体   繁体   中英

Most efficient way to find all combinations of two elements in lists

So I have three classes. On the one hand there is the Point class:

public class Point {
    public float x;
    public float y;

    // Every point has a list of connections to other points indicated
    // by their position in the list of points in the main class.
    public List<Integer> connections = new ArrayList<>();

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }
}

On the other hand there is the Line class:

public class Line {
    public Point start;
    public Point end;

    public Line(Point start, Point end) {
        this.start = start;
        this.end = end;
    }
}

And the Combination class:

public class Combination {
    public Line a;
    public Line b;

    public Combination(Line a, Line b) {
        this.a = a;
        this.b = b;
    }
}

I want one method to return a list of all possible combinations based on lines which are generated from the given points. My current approach is the following:

public static List<Combination> findCombinations(List<Point> points) {
    List<Combination> combinations = new ArrayList<>();
    List<Line> lines = new ArrayList<>();

    for (Point a : points) {
        for (int p : a.connections) {
            lines.add(new Line(a, points.get(p)));
        }
    }

    for (Line a : lines) {
        for (Line b : lines) {
            if (a == b) continue;
            combinations.add(new Combination(a, b));
        }
    }

    return combinations;
}

I have a base class containing a list of points. For every instance of that class I call the method above once only. However, a lot of instances are created and this method slows down the process.

I need to find the combinations in order to test if there is a intersection for the two lines (segments) in each Combination instance. I basically want to find all combinations of lines that intersect. To achieve this I need to get the combinations and then check where the intersection is.

The calculation of the intersecting point is not the problem.

I such graphs, formed by points and lines (often called nodes and edges) the desired combinations are usually iterated on the fly. So usually one should not genereate an explicit list containing all such combinations.

And if you insist in creating all combinations, there is no faster way than iterating through all combinations. ( Update: If your task is to find all line intersections there are much faster well known algorithms. This field is called Compuational geometry)

You can speed up a bit if the graph is fixed, so it does not change anymore after creation.
In that case you can replace the

 public List<Integer> connections = new ArrayList<>();

with the faster array of int, which uses a quarter of the memory, too:

public int[] connections.

This optimization usually needs two steps. Build up your graph with ArrayList, then after it is ready, convert all to an static graph using the int[]

Further you are mentioning "efficency". Especially here, one have to decide between memory effciency (eg as used an embedded navigation system) or calculation speed (as used when having much memory).

Your solution, and my answer are related to calculation speed.

If the intent is to combine the newly created line with all other lines, you can get away from the second structure by incorporating the creation of the Combination from the new Line and all previous ones. I'm not sure how much faster this would be (if at all), but I feel it's a bit better in terms of code organization.

public static List<Combination> findCombinations(final List<Line> lines, final List<Point> points) {
    final List<Combination> combinations = new ArrayList<>();

    for (Point a : points) {
        for (int p : a.connections) {
            Line l = new Line(a, points.get(p));
            for(int i=0; i<lines.size(); i++){
                combinations.add(new Combination(lines.get(i),l));
            }
            lines.add(l);
        }
    }

    return combinations;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM