Best Practice Algorithmus für Berechnung von Zahlenreihenfolge

Keo

Mitglied
Ich habe ein Array von sortieren Zahlen:
int i = {1, 3, 4, 5, 7, 8, 9, 11, 13}

Diese Zahlen möchte ich in zwei unterschiedlichen Listen abspeichern:

1. Eine Liste von Zahlen, die nicht in einer Reihenfolge stehen, also
Arrays.asList(1, 11, 13);

2. Eine Liste von Zahlen, die gruppiert in einer Reihenfolge stehen, also:
List<Integer[]> test = new ArrayList<>();
test.add(new Integer[]{3,4,5});
test.add(new Integer[]{7,8,9});


Wie könnte der Code für die Berechnung der beiden Listen aussehen?
 

Thallius

Top Contributor
Ganz einfach eine Schleife die immer schaut ob die aktuelle Zahl die vorherige +1 ist. wenn ja, dann an die aktuelle Liste anhängen, wenn nein dann neue Liste erstellen und die nächsten daran anhängen
 
X

Xyz1

Gast
Ganz einfach ist es mit Sicherheit nicht, aber geb ich auch mal meine Lösung zum Besten:
Java:
    /**
     * @author DerWissende on 03/17/2016
     */
    private static List<List<Integer>> getLLI(int[] array) {
        List<List<Integer>> rueck = new LinkedList<List<Integer>>();
        rueck.add(new LinkedList<Integer>()); // isolated
        Arrays.sort(array); // zur Sicherheit

        if (array[0] + 1 < array[0 + 1]) { // vorher
            rueck.get(0).add(array[0]);
        } else {
            rueck.add(new LinkedList<Integer>());
            rueck.get(rueck.size() - 1).add(array[0]);
        }

        for (int i = 1; i < array.length - 1; i++) {
            if (array[i] - 1 > array[i - 1] && array[i] + 1 < array[i + 1]) {
                rueck.get(0).add(array[i]);
            } else {
                int j = rueck.get(rueck.size() - 1).get(rueck.get(rueck.size() - 1).size() - 1);
                if (array[i] - 1 == j) {
                    rueck.get(rueck.size() - 1).add(array[i]);
                } else {
                    rueck.add(new LinkedList<Integer>());
                    rueck.get(rueck.size() - 1).add(array[i]);
                }
            }
        }

        if (array[array.length - 1] - 1 > array[array.length - 1 - 1]) { // nachher
            rueck.get(0).add(array[array.length - 1]);
        } else {
            rueck.add(new LinkedList<Integer>());
            rueck.get(rueck.size() - 1).add(array[array.length - 1]);
        }

        return rueck;
    }

    /**
     * @author DerWissende on 03/17/2016
     */
    public static void main(String[] args) {
        System.out.println(getLLI(new int[]{1, 3, 4, 5, 7, 8, 9, 11, 13}));
    }

[[1, 11, 13], [3, 4, 5], [7, 8, 9]]

qwertqwert

Mit einem kleinen Beweis lässt sich sagen, ob sie immer funktioniert.
 

Meniskusschaden

Top Contributor
Ich denke, die Komplexität entsteht durch die Sonderfälle für die Prüfung des ersten und letzten Array-Elements. Ich würde mir deshalb einfach zwei Hilfsmethoden boolean hasLeftNeighbor(int i)undboolean hasRightNeighbor(int i) erstellen. Da ist die Prüfung der jeweiligen Array-Grenze dann ganz einfach. In der Hauptschleife muß man nur noch für jedes Element prüfen, ob es einen linken und rechten Nachbarn hat.
 

Meniskusschaden

Top Contributor
Es ist doch noch etwas komplizierte als ich erst dachte, weil ich übersehen habe, dass die zweite Liste nicht nur einfach die gruppierten Zahlen enthalten soll, sondern Listen mit den Zahlengruppen. Ich würde es der Lesbarkeit halber trotzdem mit Hilfsmethoden machen:
Java:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Reihenfolge {
    static int[] zahlen = {1, 3, 4, 5, 7, 8, 9, 11, 13};
    static List<Integer> einzelZahlen = new ArrayList<Integer>();
    static List<List<Integer>> gruppenListe = new ArrayList<List<Integer>>();

    public static void main(String[] args) {
        erzeugeGruppen();
        System.out.println(Arrays.toString(zahlen));
        System.out.println(einzelZahlen);
        System.out.println(gruppenListe);
    }

    private static void erzeugeGruppen() {
        List<Integer> gruppe = new ArrayList<Integer>();
        for (int i=0; i<zahlen.length; i++) {
            if (!hasLeftNeighbor(i) && !hasRightNeighbor(i)) {
                einzelZahlen.add(zahlen[i]);
                continue;
            }
            if (!hasLeftNeighbor(i) && hasRightNeighbor(i)) {
                gruppe = new ArrayList<Integer>();
                gruppenListe.add(gruppe);
            }
            if (hasLeftNeighbor(i) || hasRightNeighbor(i)) {
                gruppe.add(zahlen[i]);  
            }
        }
    }

    private static boolean hasLeftNeighbor(int i) {
        if (i==0) {
            return false;
        }
        return zahlen[i]-zahlen[i-1]==1;
    }
  
    private static boolean hasRightNeighbor(int i) {
        if (i==zahlen.length-1) {
            return false;
        }
        return zahlen[i+1]-zahlen[i]==1;
    }
}
 
X

Xyz1

Gast
Auch ne gute Lösung. Weil bei mir aber wieder nicht auf Danke geklickt wurde, werde ich das auch bei dir nicht tun.

Das continue; aber sehr vermeiden, mir würde dann sofort Spaghetti vorgeworfen werden...
 

Meniskusschaden

Top Contributor
Das continue; aber sehr vermeiden, mir würde dann sofort Spaghetti vorgeworfen werden...
Das continue kann hier ersatzlos gestrichen werden. Funktioniert trotzdem. Falls man es drin lässt kann man die dritte if-Bedingung entfernen, weil sie aufgrund der ersten if-Bedingung ohnehin immer zutrifft:
Java:
//    if (hasLeftNeighbor(i) || hasRightNeighbor(i)) {
        gruppe.add(zahlen[i]);  
//    }
 

Meniskusschaden

Top Contributor
Das continue; aber sehr vermeiden, mir würde dann sofort Spaghetti vorgeworfen werden...
Ich bin übrigens kein strikter Gegner von break und continue. Es kann durchaus zur Lesbarkeit beitragen, wenn man sofort sieht, dass man die Schleife an einer bestimmten Stelle verlässt bzw. die nächste Iteration startet. Bei verschachtelten Schleifen und in Verbindung mit Labels finde ich es allerdings auch grausam.
 

Keo

Mitglied
danke, ich habe noch eine Abfrage eingebaut, falls int[] zahlen nur ein Element beinhaltet.

Kennt jmd. noch schickere Lösungen? Vielleicht irgendwelche vorhanden Hilfsklassen, die mir die Arbeit erleichtert.
 
X

Xyz1

Gast
Okay, ich hab vergessen zu erwähnen, das(s) sich für sowas hervorragend eigentlich eine Deque eignet. Aber ich dachte, dieser Kommentar wird bestimmt sowieso kommen. :rolleyes:
 
X

Xyz1

Gast
Ich hab es noch mal refactoret, um die Lesbarkeit maximal zu erhöhen:
Java:
    private static List<Integer> getFirst(List<List<Integer>> rueck) {
        return rueck.get(0);
    }
    
    private static List<Integer> getLast(List<List<Integer>> rueck) {
        return rueck.get(rueck.size() - 1);
    }
    
    private static Integer getLastElem(List<List<Integer>> rueck) {
        List<Integer> li = getLast(rueck);
        return li.get(li.size() - 1);
    }
    
    private static void addFirst(List<List<Integer>> rueck, int a) {
        getFirst(rueck).add(a);
    }
    
    private static void addLast(List<List<Integer>> rueck, int a) {
        getLast(rueck).add(a);
    }
    
    private static void addLastNew(List<List<Integer>> rueck, int a) {
        rueck.add(new LinkedList<Integer>());
        getLast(rueck).add(a);
    }
    
    private static List<List<Integer>> getLLI(int[] array) {
        List<List<Integer>> rueck = new LinkedList<List<Integer>>();
        rueck.add(new LinkedList<Integer>());                                   // isolated
        Arrays.sort(array);                                                     // zur Sicherheit

        if (array[0] + 1 < array[0 + 1]) {                                      // vorher
            addFirst(rueck, array[0]);
        } else {
            addLastNew(rueck, array[0]);
        }
        
        for (int i = 1; i < array.length - 1; i++) {
            if (array[i] - 1 > array[i - 1] && array[i] + 1 < array[i + 1]) {
                addFirst(rueck, array[i]);
            } else {
                if (array[i] - 1 == getLastElem(rueck)) {
                    addLast(rueck, array[i]);
                } else {
                    addLastNew(rueck, array[i]);
                }
            }
        }
        
        if (array[array.length - 1] - 1 > array[array.length - 2]) {            // nachher
            addFirst(rueck, array[array.length - 1]);
        } else {
            addLastNew(rueck, array[array.length - 1]);
        }
        
        return rueck;
    }

    /**
     * @author DerWissende on 03/17/2016
     */
    public static void main(String[] args) {
        System.out.println(getLLI(new int[]{1, 3, 4, 5, 7, 8, 9, 11, 13}));
    }

Ein "Gefällt mir" ist gerne willkommen.
 

Flown

Administrator
Mitarbeiter
Also basierend auf StuartMarks und meiner Idee gab es schon einen Post auf StackOverflow: HIER

Das kann man mit Geschick und Streams lösen. Erst muss man die Indizes der Gruppen im Array ermitteln. Wenn man die hat kopiert man anhand von den berechneten Indizes die Arrays in kleine Junks. Die Ergebnisse partitionieren und alle "Gruppen" mit Länge 1 in eine Liste zusammenfassen.
Dann kommt sowas raus:
Java:
public class Test {

  public static void main(String... args) {
    System.out.println(findGroupings(new int[] { 1, 3, 4, 5, 7, 8, 9, 11, 13 }));
  }

  public static ArrayRangeResult findGroupings(int[] arr) {
    if (arr == null || arr.length == 0) {
      return new ArrayRangeResult(arr, Collections.emptyList(), Collections.emptyList());
    }
    int[] x = IntStream.rangeClosed(0, arr.length).filter(i -> i == 0 || i == arr.length || arr[i - 1] + 1 != arr[i]).toArray();
    Map<Boolean, List<int[]>> collect = IntStream.range(0, x.length - 1).mapToObj(i -> Arrays.copyOfRange(arr, x[i], x[i + 1])).collect(Collectors.partitioningBy(i -> i.length > 1));
    return new ArrayRangeResult(arr, collect.get(true), collect.get(false).stream().flatMap(i -> Arrays.stream(i).boxed()).collect(Collectors.toList()));
  }
}

class ArrayRangeResult {
  private final int[] origin;
  private final List<int[]> groupings;
  private final List<Integer> delimiters;

  public ArrayRangeResult(int[] origin, List<int[]> groupings, List<Integer> delimiters) {
    this.origin = origin;
    this.groupings = groupings;
    this.delimiters = delimiters;
  }

  public int[] getOrigin() {
    return origin.clone();
  }

  public List<int[]> getGroupings() {
    return groupings.stream().map(g -> g.clone()).collect(Collectors.toList());
  }

  public List<Integer> getDelimiters() {
    return new ArrayList<>(delimiters);
  }

  @Override
  public String toString() {
    String result = "Array: " + Arrays.toString(origin) + "\n";
    result += "Groupings: " + groupings.stream().map(Arrays::toString).collect(Collectors.joining(",")) + "\n";
    result += "Delimiters: " + delimiters;
    return result;
  }
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
N Algorithmus für Berechnung einer Quersumme Java Basics - Anfänger-Themen 9
C negamax-Algorithmus für Tic-Tac-Toe spielt manchmal falsch Java Basics - Anfänger-Themen 10
M Minimax-Algorithmus für Vier gewinnt Java Basics - Anfänger-Themen 11
M monte carlo Algorithmus für 4 gewinnt Java Basics - Anfänger-Themen 12
izoards Sortier Algorithmus für Bounding Box Elememte Links nach Rechts und von Oben nach Unten Java Basics - Anfänger-Themen 33
T Algorithmus für Index mit min-Wert Java Basics - Anfänger-Themen 2
A Datenstruktur für Savings Algorithmus und Planung von kleinen Programmierprojekten Java Basics - Anfänger-Themen 1
J Algorithmus für eine Reihe implementieren Java Basics - Anfänger-Themen 2
D Algorithmus für Punkte auf einem Kreis Java Basics - Anfänger-Themen 0
C Ideen für einen Algorithmus Java Basics - Anfänger-Themen 1
R Rekursionsformel für Laufzeit von Algorithmus Java Basics - Anfänger-Themen 3
E Algorithmus für kart. Produkt: als int [] Feld repräsentiert Java Basics - Anfänger-Themen 10
S Algorithmus für Spielbaum Java Basics - Anfänger-Themen 5
A double and add algorithmus für elliptische kurven/ integer binär darstellen Java Basics - Anfänger-Themen 14
Binary.Coder Welcher Datentyp für den Simplex Algorithmus Java Basics - Anfänger-Themen 3
W Algorithmus für Primzahlberechnung Java Basics - Anfänger-Themen 4
A MiniMax- Algorithmus für 4-Gewinnt Java Basics - Anfänger-Themen 3
K Algorithmus entwickeln Java Basics - Anfänger-Themen 1
laxla123 Eigenschaften eines Algorithmus (determiniert vs.. deterministisch) Java Basics - Anfänger-Themen 2
C Gewinnspiel erstellen mit Algorithmus Java Basics - Anfänger-Themen 3
H Minimax Algorithmus in Tic Tac Toe Java Basics - Anfänger-Themen 3
ohneInformatik; Trockentest Algorithmus, mathematischen Zusammenhang angeben Java Basics - Anfänger-Themen 3
M Minimax-Algorithmus Java Basics - Anfänger-Themen 17
mervanpolat Binary Search Algorithmus ausführen Java Basics - Anfänger-Themen 1
J Rekursiver Algorithmus Java Basics - Anfänger-Themen 9
S Algorithmus entwicklen, der zu einem gegebenen Datum die Jahreszeit ermittelt Java Basics - Anfänger-Themen 13
rosima26 Merge-Algorithmus Java Basics - Anfänger-Themen 53
C Ein Algorithmus soll schneller werden Java Basics - Anfänger-Themen 24
D Dijkstra Algorithmus Hilfe!! Java Basics - Anfänger-Themen 9
U Den Kuchen aufteilen - aber wie? (Rebalancing-Algorithmus) Java Basics - Anfänger-Themen 14
s_1895 Pseudocode Naiver Algorithmus Java Basics - Anfänger-Themen 17
H String verschlüsseln - eigener Algorithmus Java Basics - Anfänger-Themen 104
Düsseldorf2002 Testen meines Algorithmus Java Basics - Anfänger-Themen 1
D Primzahlen Rechner nach Eratostenes von Kyrene Algorithmus Java Basics - Anfänger-Themen 2
KogoroMori21 Frage zum Euklidischen Algorithmus Java Basics - Anfänger-Themen 11
S Algorithmus java searchAll IKey Java Basics - Anfänger-Themen 4
S Algorithmus Datensätze einfügen wenn... Java Basics - Anfänger-Themen 26
KogoroMori21 MergeSort Algorithmus Java Basics - Anfänger-Themen 2
KogoroMori21 Textdatei einlesen im Array (Selection Sort Algorithmus) Java Basics - Anfänger-Themen 3
fendix Compiler-Fehler Algorithmus zur Bestimmung von Primzahlen Java Basics - Anfänger-Themen 7
S Algorithmus (reelle Zahl <65536 von dezimal zu dual) max. 10 Nachkommastellen Java Basics - Anfänger-Themen 4
G Algorithmus Graphen Java Basics - Anfänger-Themen 10
D Input/Output fehlerhafter Algorithmus zum Ersetzen von Array-Werten nach logischem Schema Java Basics - Anfänger-Themen 1
N Selection Algorithmus: Methode wird nicht erkannt (BlueJ) Java Basics - Anfänger-Themen 3
U Meinung zum Dijkstra Algorithmus Java Basics - Anfänger-Themen 6
U Dijkstra Algorithmus Laufzeit Java Basics - Anfänger-Themen 3
L Math.exp also eigenen Algorithmus Java Basics - Anfänger-Themen 2
Kirby.exe Algorithmus entwickeln Java Basics - Anfänger-Themen 37
M Algorithmus Max-Heap? Java Basics - Anfänger-Themen 3
I Labyrinth auf der Basis eines rekursiven Algorithmus Java Basics - Anfänger-Themen 27
CptK Best Practice Algorithmus nach jedem Schritt zum Visualisieren pausieren Java Basics - Anfänger-Themen 3
A Algorithmus effizienter machen Java Basics - Anfänger-Themen 1
V Algorithmus zur fortlaufenden Berechnung des duechscjnt Java Basics - Anfänger-Themen 1
M Dijkstra Algorithmus in Graphen auf mehrere verschiedene Knoten anwenden lassen Java Basics - Anfänger-Themen 11
O Labyrinth Algorithmus Java Basics - Anfänger-Themen 3
G Quicksort Algorithmus Java Basics - Anfänger-Themen 12
S Binäre-Suche Algorithmus Java Basics - Anfänger-Themen 1
D Algorithmus in Pseudocode mit log2(n) Operationen erstellen Java Basics - Anfänger-Themen 3
C Laufzeit eines Sortier-Algorithmus ermitteln Java Basics - Anfänger-Themen 4
H aufgabe java luhn algorithmus Java Basics - Anfänger-Themen 10
S Dijkstra Algorithmus funktioniert nicht Java Basics - Anfänger-Themen 4
N Denksportaufgabe durch Algorithmus lösen Java Basics - Anfänger-Themen 2
S Problem mit einem rekursivem FloodFill Algorithmus Java Basics - Anfänger-Themen 62
B Algorithmus Square und Multiply Java Basics - Anfänger-Themen 3
J Algorithmus - Strings auf eigene Reihenfolge miteinander vergleichen Java Basics - Anfänger-Themen 4
D Frage Boyer-Moore Algorithmus Java Basics - Anfänger-Themen 7
M Komplexität Algorithmus Java Basics - Anfänger-Themen 8
H Zeichen im algorithmus Java Basics - Anfänger-Themen 4
B Code Verständnisfragen - FLoyd Warshall Algorithmus Java Basics - Anfänger-Themen 1
B Algorithmus zum entmischen einer Zahlenfolge Java Basics - Anfänger-Themen 15
X Minimax-Algorithmus über alle Kanten möglich? - Kanten darstellen Java Basics - Anfänger-Themen 1
T Algorithmus zur Überprüfung eines binären Suchbaums Java Basics - Anfänger-Themen 2
M Simpler Algorithmus läuft extrem langsam. Java Basics - Anfänger-Themen 3
K Erste Schritte Brute Force Algorithmus Java Basics - Anfänger-Themen 2
L Frage zu BubbleSort Algorithmus Java Basics - Anfänger-Themen 2
B gibt es ein Stundenplan-Algorithmus? Java Basics - Anfänger-Themen 11
O Algorithmus-Problem Java Basics - Anfänger-Themen 5
P Euklidischer Algorithmus Java Basics - Anfänger-Themen 9
L Greates Commong Dividend - euklidischer Algorithmus, modulos not positive Java Basics - Anfänger-Themen 5
J Euklidischer Algorithmus Java Basics - Anfänger-Themen 1
S Quicksort Algorithmus Java Basics - Anfänger-Themen 2
S GraphNode --- Dijkstra Algorithmus : NullPointerException Java Basics - Anfänger-Themen 1
B Rekursive Algorithmus schreiben Java Basics - Anfänger-Themen 8
V Algorithmus in einer Methode ausführen Java Basics - Anfänger-Themen 3
M Implementierung des Knuth-Morris-Pratt-Algorithmus Java Basics - Anfänger-Themen 0
M Dijkstras Algorithmus Java Basics - Anfänger-Themen 5
S Zusammenhang Datenstruktur/Algorithmus Java Basics - Anfänger-Themen 1
M Simulation - Algorithmus Java Basics - Anfänger-Themen 3
F Erste Schritte Hilfe beim Algorithmus finden Java Basics - Anfänger-Themen 8
D Algorithmus zu gegebener Laufzeit implementieren Java Basics - Anfänger-Themen 1
B Doppelte Werte aus Array entfernen ohne Import - Algorithmus Java Basics - Anfänger-Themen 5
F Best Practice Algorithmus optimieren - Binaeruhr Java Basics - Anfänger-Themen 2
S Euklid Algorithmus zur Berechnung des GGTs Java Basics - Anfänger-Themen 2
L Welcher Algorithmus ist das ? Java Basics - Anfänger-Themen 9
J Rekursiver Horner-Schema-Algorithmus - Verstehe ich ihn richtig? Java Basics - Anfänger-Themen 2
O Java Zufalls-Verteil-Algorithmus Java Basics - Anfänger-Themen 3
P ganz simpler algorithmus Java Basics - Anfänger-Themen 3
C Sortieren ohne Algorithmus Java Basics - Anfänger-Themen 8
J Algorithmus: Grad von floating zu Grad/Minute/Sekunde Java Basics - Anfänger-Themen 3
A Text Verschriebung/Algorithmus(?) Java Basics - Anfänger-Themen 8

Ähnliche Java Themen

Neue Themen


Oben