Gegeben eine Menge S, finde alle maximalen Teilmengen, deren Summe = k ist

8

Dies ist eine Facebook-Interviewfrage, auf die ich in einem Online-Portal gestoßen bin.

Gegeben eine Menge S, finde alle maximalen Teilmengen, deren Summe & lt; = k. Zum Beispiel, wenn S = {1, 2, 3, 4, 5} und k = 7 Ausgabe ist: {1, 2, 3} {1, 2, 4} {1, 5} {2, 5} {3, 4}

Hinweise:

  • Ausgabe enthält keine Menge, die eine Untermenge von anderen ist.
  • Wenn X = {1, 2, 3} eine der Lösungen ist, dann werden alle Teilmengen von X {1} {2} {3} {1, 2} {1, 3} {2, 3} weggelassen .
  • Lexikographische Ordnung kann verwendet werden, um es zu lösen.

Irgendwelche Ideen wie könnte das gelöst werden?

    
Raman Bhatia 10.03.2012, 17:39
quelle

6 Antworten

5

Ich habe eine Idee - Sie brauchen einen Baum.

Wenn Sie {1, 2, 3, 4, 5} eingegeben haben und nach maximalen Teilmengen suchen, sollten Sie einen Baum ausgehend von den größten Zahlen erstellen und immer while sum <= k erweitern (also nicht bei 4-2 aufhören, aber gehe zu 1, um 4-2-1 zu erhalten.)

Also wären Knoten beginnend mit 5: 5-1 / 5-2 - nur diese 2 haben die Summe & lt; = 7

beginnend mit 4: 4-3 / 4-2-1 / 4-1 (Teilmenge der vorherigen)

beginnend mit 3: 3-2-1 / 3-1 (Teilmenge der vorherigen)

beginnend mit 2: 2-1 (Teilmenge von 3-2-1)

beginnend mit 1: 1 (Teilmenge von 2-1)

Dann können Sie gültige Ausgaben sortieren und erhalten {1, 2, 3} {1, 2, 4} {1, 5} {2, 5} {3, 4}

    
dantuch 11.03.2012 09:37
quelle
2

Ich weiß, es ist zu spät, um zu antworten, aber ich denke, ich habe eine einfache Lösung für dieses Problem gefunden. Wir zählen Teilmengen von S in lexikographischer Reihenfolge mit Backtracking und prüfen die sum der bisher generierten Teilmenge.

Wenn die sum k überschreitet, kommt der interessante Teil: wir müssen überprüfen, ob die generierte subset eine richtige Teilmenge der zuvor gemeldeten Elemente ist.

Eine Lösung besteht darin, alle gemeldeten Teilmengen zu behalten und auf Inklusion zu prüfen, aber es ist verschwenderisch.

Stattdessen berechnen wir die Differenz zwischen k und sum . Wenn es ein Element e in S so gibt, dass e not in subset und e <= (k - sum) , dann ist die von uns erzeugte Menge eine richtige Teilmenge einer zuvor berichteten Teilmenge und wir können sie sicher überspringen.

Hier ist das komplette Arbeitsprogramm im einfachen alten C ++, das die Idee demonstriert:

%Vor%

Die Ausgabe sind alle maximalen Teilmengen in lexikographischer Reihenfolge, eine pro Zeile:

%Vor%     
roman-kashitsyn 26.11.2014 08:20
quelle
1

Dies ist ein Powerset-Problem. Kürzlich fand ich diese Webseite über Algorithmen und es hat meine Vorstellungskraft gemalt: daher folgt die Powerset / Kombinationslösung. Sie können das Programm einfach kopieren, einfügen und ausführen.

%Vor%     
kasavbere 12.03.2012 02:57
quelle
1

Eine alte Frage, aber immer noch eine interessante Frage.

Hier ist eine rekursive Java-8-Lösung mit einem "permutativen" Ansatz.

Optimiert für saubereren und kürzeren Code anstelle von Leistung - zum Beispiel müsste das Sortieren und Beschneiden nur einmal stattfinden.

%Vor%

Um es zu testen:

%Vor%     
Heikki Salokanto 17.01.2015 00:16
quelle
1

Algorithmus ist der folgende:

  • Ausgehend von einem leeren Subset.
  • Durchläuft das ursprüngliche Array von Anfang an (vorausgesetzt Array ist bereits in aufsteigender Reihenfolge sortiert), bis currentSum kleiner oder gleich der Zielsumme ist.
  • Wenn das zu currentSum hinzugefügte aktuelle Element kleiner als die Zielsumme ist, wird das aktuelle Element zum aktuellen subSet hinzugefügt und die Rekursion beginnend mit dem nächsten Element ausgeführt.
  • Brechen des aktuellen Zyklus, wenn die aktuelle Summe targetSum überschreitet.
  • Wenn wir nicht mehr Elemente in das aktuelle Subset einfügen können, prüfen wir, ob es maximal ist und drucken es in diesem Fall.
  • Um die maximalen subSets zu bestimmen, können wir das ursprüngliche Array und das aktuelle subSet Element für Element vergleichen und nach der ersten Nichtübereinstimmung suchen. Wenn der Element-in-First-Mismatch-Index größer als der Unterschied zwischen currentSum und targetSum ist, ist subSet maximal und sollte gedruckt werden.

Arbeitslösung für Java ist unten:

%Vor%     
HitOdessit 17.01.2015 21:17
quelle
0

Es tut mir leid, dass ich so spät abgesprungen bin. Aber wie wäre es damit?

1) Erstellen Sie eine MIN-HEAP-Struktur aus dem angegebenen Array / Set

2) durchqueren Sie die Struktur von der Wurzel und subtrahieren Sie den Wert an dem Knoten, den Sie besuchen. Sobald Sie die erforderliche Summe (curr_sum & gt; k) überschritten haben, geben Sie diesen Pfad aus, gehen Sie zum übergeordneten Objekt zurück und nehmen Sie einen anderen Pfad (dies kann rekursiv erfolgen).

3) Wenn Sie mit Backtracking zum ursprünglichen Knoten zurückkehren, von dem Sie gestartet haben, implementieren Sie den gesamten Algorithmus rekursiv vom linken Knoten root- & gt ;.

4) Machen Sie die gleichen zwei Schritte (2) und (3) oben, aber jetzt mit einem MAX-HEAP.

Ich bin neu in Algorithmen und Datenstrukturen und habe erst begonnen, Intro zu Algos-Cormen zu lesen. Dies könnte eine fehlerhafte Lösung sein, aber ich wäre mehr als glücklich, wenn jemand mir die Schuld aufzeigen würde :)

    
Nishant Kelkar 26.01.2013 22:36
quelle