Ich habe dieses interessante Problem vor ein paar Wochen kennengelernt: Gegeben sei ein n-dimensionaler Raum und ein "step size" -Wert zwischen (0,1 ], erzeugen alle Punkte, die die folgenden Bedingungen erfüllen:Algorithmus zum Generieren aller Punkte in einem N-dimensionalen Raum, die eine gegebene Menge von Bedingungen erfüllen
- der Wert jeder Dimension eines Punktes ist ein Vielfaches der „Schrittweite“
- der Wert jeder Dimension eines Punktes im Bereich zwischen 0 und 1 Ein 2D-Punkt (x, y) sollte beispielsweise 0 = < x, y < = 1
- Die Summe der Werte erfüllen alle Dimensionen muss gleich 1 (aktualisiert)
Beispiel
Input:
stepsize = 0,5 und numDimensions = 3 (dh 3D-Raum)
Output:
0.0, 0.0, 1.0 0.0, 0.5, 0.5 0.0, 1.0, 0.0 0.5, 0.0, 0.5 0.5, 0.5, 0.0 1.0, 0.0, 0.0
Da wir alle möglichen Punkte finden müssen, dachte ich an eine rekursive Lösung. Hier ist mein Code:
class PointEnumeration {
static class Point {
List<Float> dimensions; //a list of float where index i is the (i+1)'th dimension
Point(Point p) {
this.dimensions = new ArrayList<>();
this.dimensions.addAll(p.dimensions);
}
Point(int size) {
this.dimensions = new ArrayList<>();
for(int i = 0; i < size; i++){
//Initialize all dimensions to 0.0f
this.dimensions.add(0.0f);
}
}
void incr(int pos, float i) {
float val = dimensions.get(pos);
dimensions.set(pos, val + i);
}
void set(int pos, float i) {
dimensions.set(pos, i);
}
float get(int pos){
return dimensions.get(pos);
}
}
static List<Point> findPoints(float stepSize, int numDim) {
if (stepSize > 1) {
return new ArrayList<>();
}
List<Point> res = new ArrayList<>();
for(float i = stepSize; i <= 1; i+=stepSize) {
findPointsHelper(i, numDim, 1.0f, 0, new Point(numDim), res);
}
return res;
}
static void findPointsHelper(float stepSize, int numDim, float sum, int start, Point curr, List<Point> res) {
if (sum == 0.0) {
res.add(new Point(curr));
return;
}
for (int i = start; i < numDim; i++) {
float temp = sum;
float val = curr.get(i);
curr.incr(i, stepSize);
findPointsHelper(stepSize, numDim, sum - stepSize, i + 1, curr, res);
curr.set(i, val);
sum = temp;
}
}
public static void main(String[] args) {
List<Point> res = findPoints(0.25f, 4); //Tried 1.0f, 3 and 0.5f, 3 as well
for (Point p : res) {
for (Float coord : p.dimensions) {
System.out.print(String.valueOf(coord) + ", ");
}
System.out.println(" ");
}
}
}
Dies scheint richtig zu funktionieren für ein paar Testfälle, die ich versuchte. Beispiel Ausgabe für (stepsize = 0,5f und numDimensions = 3):
0.5, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0,
Ich habe ein paar Fragen:
- Ist mein Ansatz dieses Problem richtig zu lösen?
- Was ist die genaue zeitliche Komplexität meiner Lösung? Ich behauptete, dass es exponentiell war, aber nicht in der Lage war, die zeitliche Komplexität in Bezug auf Anzahl der Dimensionen/Schrittgröße/Anzahl der Punkte korrekt zu artikulieren. Was wäre der beste Ansatz, um Zeitkomplexitäten für das obige Problem und für rekursive Algorithmen wie diese im Allgemeinen zu begründen?
- Wenn mein Verständnis der exponentiellen Zeitkomplexität korrekt ist, gibt es einen effizienteren Algorithmus, um dieses spezielle Problem zu lösen?
EDIT vermisste ich eine dritte Einschränkung: Summe aller Werte einer Dimension auf 1,0 summieren müssen (Entschuldigt, ich diese früher vergessen zu erwähnen).
Fragen Sie sich: wo ist Punkt '1.0, 0.5, 0.0' (und ähnlich) in der Ausgabe? – BeyelerStudios
Sie könnten alle Punkte für den 1-dimensionalen Fall generieren, S sagen, und dann das kartesische Produkt der dunklen Kopien von S. – dmuir
Wie @BeyelerStudios darauf hinweist, sind die beiden Einschränkungen, die Sie geben, falsch, oder Ihre Beispiellösung ist falsch. –