erhalten Effizientes sortierten Summen einer sortierten Liste

stimmen
17

Sie haben eine aufsteigende Liste von Zahlen, was ist die effizienteste Algorithmus Sie erhalten die aufsteigende Liste von Summen von jeweils zwei Zahlen in dieser Liste denken. Dubletten in der Ergebnisliste sind irrelevant, Sie können sie sie entfernen oder vermeiden, wenn Sie möchten.

Um es klar, ich bin in dem Algorithmus interessiert. Fühlen Sie sich frei Code in jeder beliebigen Sprache und Paradigma zu schreiben, die Sie mögen.

Veröffentlicht am 03/08/2008 um 22:08
quelle vom benutzer
In anderen Sprachen...                            


8 antworten

stimmen
12

Bearbeiten, wie 2018: Sie sollten wahrscheinlich aufhören diese zu lesen. (Aber ich kann es nicht gelöscht werden, wie es angenommen wird.)

Wenn Sie die Beträge wie folgt schreiben:

1 4  5  6  8  9
---------------
2 5  6  7  9 10
  8  9 10 12 13
    10 11 13 14
       12 14 15
          16 17
             18

Sie werden bemerken, dass, da M [i, j] <= M [i, j + 1] und M [i, j] <= M [i + 1, j], dann müssen Sie nur die obere linke Ecke "prüfen, Ecken“und die niedrigste auszuwählen.

z.B

  • nur 1 linke obere Ecke, Pick 2
  • nur 1, Pick 5
  • 6 oder 8, Pick 6
  • 7 oder 8, Pick 7
  • 9 oder 8, 8 Pick
  • 9 oder 9, Pick beide :)
  • 10 oder 10 oder 10, Pick all
  • 12 oder 11, Pick 11
  • 12 bzw. 12, nehmen sowohl
  • 13 oder 13, Pick sowohl
  • 14 oder 14, Pick sowohl
  • 15 oder 16, Pick 15
  • nur 1, Pick 16
  • nur 1, Pick 17
  • nur 1, Pick 18

Natürlich, wenn Sie haben viel von oben links Ecken dann zufällt diese Lösung.

Ich bin mir ziemlich sicher, dass dieses Problem ist Ω (n²), da Sie die Summen für jeden M zu berechnen haben [i, j] - es sei denn, jemand einen besseren Algorithmus für die Summierung hat :)

Beantwortet am 18/09/2008 um 22:41
quelle vom benutzer

stimmen
4

Anstatt diese Codierung aus, Figur, die ich mir Pseudo-Code werde es in den Schritten und meine Logik zu erklären, so dass ein besserer Programmierer Löcher in meiner Logik, wenn nötig stecken kann.

Im ersten Schritt starten wir mit einer Liste von Zahlen Länge n aus. Für jede Zahl brauchen wir eine Liste der Länge n-1 schaffen becuase wir nicht eine Nummer selbst hinzufügen. Am Ende haben wir eine Liste von etwa n sortierten Listen, die in O (n ^ 2) Zeit erzeugt wurden.

step 1 (startinglist) 
for each number num1 in startinglist
   for each number num2 in startinglist
      add num1 plus num2 into templist
   add templist to sumlist
return sumlist 

In Schritt 2, weil die Listen nach Design (fügen Sie eine Nummer, die jedes Element in einer sortierten Liste und die Liste wird noch sortiert werden) wir einfach durch die Zusammenlegung jede Liste eine mergesort tun sortiert wurden, können zusammen anstatt mergesorting die gesamte Partie. Am Ende soll diese O (n ^ 2) Zeit in Anspruch nehmen.

step 2 (sumlist) 
create an empty list mergedlist
for each list templist in sumlist
   set mergelist equal to: merge(mergedlist,templist)
return mergedlist

Das Merge-Verfahren wäre dann der normale merge Schritt mit einer Überprüfung, um sicherzustellen, dass es keine doppelten Summen. Ich werde diese aus nicht schreiben, weil jemand mergesort nachschlagen kann.

So gibt es meine Lösung. Der gesamte Algorithmus ist O (n ^ 2) Zeit. Fühlen Sie sich frei, alle Fehler oder Verbesserungen aufzuzeigen.

Beantwortet am 04/08/2008 um 00:06
quelle vom benutzer

stimmen
2

Sie können dies in Python in zwei Linien tun mit

allSums = set(a+b for a in X for b in X)
allSums = sorted(allSums)

Die Kosten hierfür ist n ^ 2 (vielleicht ein zusätzliches Protokoll Faktor für den Satz?) Für die Iteration und s * log (n) für die Sortierung, wo s die Größe des Satzes ist.

Die Größe des Satzes könnte so groß wie n * (n-1) / 2, wenn beispielsweise X = [1,2,4, ..., 2 ^ n] sein. Also, wenn Sie diese Liste erstellt werden sollen es n mindestens nehmen ^ 2/2 im schlimmsten Fall, da dies die Größe des Ausgangs.

Allerdings , wenn Sie die ersten k Elemente des Ergebnisses auswählen möchten Sie dies in O tun können (kn) für eine Auswahl - Algorithmus sortierten X + Y - Matrizen von Frederickson und Johnson ( siehe hier für blutige Details) . Obwohl dies wahrscheinlich sie online geändert werden , zu erzeugen , indem die Berechnung der Wiederverwendung und einen effizienten Generator für diesen Satz zu erhalten.

@deuseldorf, Peter Es gibt einige Verwirrung über (n!) Ich ernsthaft Zweifel deuseldorf gemeint „n Fakultät“, sondern einfach „n, (sehr aufgeregt)!“

Beantwortet am 11/08/2008 um 15:47
quelle vom benutzer

stimmen
1

Egal, was Sie tun, ohne zusätzliche Einschränkungen für die Eingabewerte, können Sie nicht besser als O (n ^ 2), nur weil Sie durch alle Paare von Zahlen iterieren haben. Die Iteration wird dominieren Sortierung (die Sie in O tun können (n log n) oder schneller).

Beantwortet am 18/09/2008 um 23:15
quelle vom benutzer

stimmen
1

Diese Frage wurde wracking mein Gehirn für etwa einen Tag jetzt. Genial.

Wie auch immer, man kann nicht weg von der n ^ 2 Natur es leicht, aber man kann mit der Zusammenführung etwas besser tun, da Sie den Bereich gebunden ist, können in jedes Element einzufügen.

Wenn Sie die alle Listen sehen Sie erzeugen, haben sie die folgende Form:

(a[i], a[j]) | j>=i

Wenn Sie es um 90 Grad drehen, erhalten Sie:

(a[i], a[j]) | i<=j

Nun sollte der Mergeprozesses zwei Listen nehmen iund i+1(die Listen entsprechen , in denen das erste Element immer a[i]und a[i+1]) können Sie verpflichtet , den Bereich Element einfügen (a[i + 1], a[j])in die Liste idurch die Lage (a[i], a[j])und die Lage der (a[i + 1], a[j + 1]).

Dies bedeutet , dass Sie in umgekehrter Richtung in Bezug auf verschmelzen sollten j. Ich weiß (noch) nicht , wenn Sie diese über nutzen können , jwie gut, aber es scheint möglich.

Beantwortet am 21/08/2008 um 19:16
quelle vom benutzer

stimmen
1

In SQL:

create table numbers(n int not null)
insert into numbers(n) values(1),(1), (2), (2), (3), (4)


select distinct num1.n+num2.n sum2n
from numbers num1
inner join numbers num2 
    on num1.n<>num2.n
order by sum2n

C # LINQ:

List<int> num = new List<int>{ 1, 1, 2, 2, 3, 4};
var uNum = num.Distinct().ToList();
var sums=(from num1 in uNum
        from num2 in uNum 
        where num1!=num2
        select num1+num2).Distinct();
foreach (var s in sums)
{
    Console.WriteLine(s);
}
Beantwortet am 09/08/2008 um 00:05
quelle vom benutzer

stimmen
1

Das Beste, was ich tun konnte, ist eine Matrix von Summen von jedem Paar zu erzeugen, und dann verschmelzen die Zeilen zusammen, a-la Mergesort. Ich fühle mich wie ein paar einfache Einsicht fehlt bin, die eine viel effizientere Lösung offenbaren wird.

Mein Algorithmus, in Haskell:

matrixOfSums list = [[a+b | b <- list, b >= a] | a <- list]

sortedSums = foldl merge [] matrixOfSums

--A normal merge, save that we remove duplicates
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = case compare x y of
    LT -> x:(merge xs (y:ys))
    EQ -> x:(merge xs (dropWhile (==x) ys))
    GT -> y:(merge (x:xs) ys)

Ich fand eine kleine Verbesserung, eine, die leichter zugänglich zu faul Stream-basierten Kodierung ist. Stattdessen werden die Spalten paarweise zu verschmelzen, fusionieren auf einmal von ihnen. Der Vorteil ist, dass Sie sofort bekommen Elemente der Liste zu starten.

-- wide-merge does a standard merge (ala merge-sort) across an arbitrary number of lists
-- wideNubMerge does this while eliminating duplicates
wideNubMerge :: Ord a => `a` -> [a]
wideNubMerge ls = wideNubMerge1 $ filter (/= []) ls
wideNubMerge1 [] = []
wideNubMerge1 ls = mini:(wideNubMerge rest)
    where mini = minimum $ map head ls
          rest = map (dropWhile (== mini)) ls

betterSortedSums = wideNubMerge matrixOfSums

Allerdings, wenn Sie wissen , dass Sie alle Summen verwenden, und es gibt keinen Vorteil zu früher einige von ihnen bekommen, gehen Sie mit ‚ foldl merge []‘, da es schneller ist.

Beantwortet am 03/08/2008 um 22:36
quelle vom benutzer

stimmen
-4

Wenn Sie für eine wirklich sprachunabhängig Lösung suchen, dann werden Sie meiner Meinung nach sehr enttäuscht sein, weil Sie für Schleife mit einem stecken werde und einige conditionals. Allerdings, wenn Sie es zu funktionalen Sprachen oder funktionale Sprache Funktionen geöffnet (Ich bin auf Sie LINQ suchen), dann hier meine Kollegen diese Seite mit eleganten Beispiele in Ruby füllen kann, Lisp, Erlang und andere.

Beantwortet am 03/08/2008 um 22:24
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more