2016-04-04 10 views
1

I wurde Code für this problem Schreiben:Python - Reduzieren Zeitverbrauch

ein Array mit N Elementen A angegeben. Finde die Gesamtzahl der Paare (i, j), so dass j < i und Aj = Ai.

Dies ist mein Code:

raw_input() 

l = list(map(int, raw_input().split())) 

count = 0 

for a in range(len(l)): 
    count = count + l[a+1:].count(l[a]) 

print(count) 

Aber leider ist der Code eine Menge Zeit. Haben Sie Vorschläge, wie ich den Zeitaufwand reduzieren könnte? Ich meine, wie reduziere ich die Zeit in der for Schleife verbraucht. Ich finde, dass die Methode list.count viel Zeit braucht, also haben Sie irgendwelche Ideen, durch die ich es ersetzen könnte.

+1

Ja, 'list.coun t() 'muss über die * ganze Liste iterieren, um die Anzahl der Vorkommen zu zählen. –

+2

Versuchen Sie, an andere Möglichkeiten zu denken, die Liste nur * einmal * zu durchlaufen. Vielleicht können Sie verfolgen, ob Sie bereits eine Nummer gesehen haben? –

+0

@MartijnPieters Ich hatte die Liste früher irrtümlich "sortiert" und als ich davon erfuhr, wurde mir klar, dass sie keine Auswirkung auf die Antworten hatte, die sie berechnen konnte. –

Antwort

-1

Dies ist wahrscheinlich schneller, weil die Verwendung Generator und Schneiden:

l = [1, 2, 1, 3] 

count = 0 
for idx, value in enumerate(l): 
    count += sum(1 for v in l[:idx] if v == value) 

print(count) 
assert count == 1 
+0

Glauben Sie nicht, dass Sie 'v

+0

Ich glaube, ich habe die Herausforderung falsch verstanden. EDIT: behoben. Sollte jetzt funktionieren. – aluriak

+0

'v' ist der Wert des Artikels. Es muss nicht weniger als "Wert" sein. Es muss gleich sein. –

1

Sie können es beschleunigen, indem Sie eine schnellere Möglichkeit zur Überprüfung der Mitgliedschaft als .count() verwenden. Zum Beispiel ist ein dict Lookup extrem schnell:

from collections import defaultdict 

raw_input() 

l = list(map(int, raw_input().split())) 

keys = defaultdict(list) 

for i, v in enumerate(l): 
    keys[v].append(i) 

for value, keys in keys.items(): 
    print("Value %d appears at indices %s." % (k, ", ".join(keys))) 

Dann brauchen Sie nur die Anzahl der Paare zu zählen.

+0

... das ist nur eine (len (keys [k]) über 2) Berechnung für jedes len (keys [k])> 1. Sie können auch nur die Länge berechnen, keinen Punkt bei der Speicherung aller Indizes. –

1

Ich bekam endlich die Antwort. Es hat den Zeitaufwand auf einen sehr geringen Betrag reduziert. Entschuldigung für Störungen verursacht.

raw_input() 

l = list(map(int, raw_input().split())) 

dictionary = {} 

for value in l: 
    if value in dictionary: 
     dictionary[value] += 1 
    else: 
     dictionary[value] = 0 

def sum_till_n(iterable): 
    return [x*(x+1)/2 for x in iterable] 

print(sum(sum_till_n(dictionary.values()))) 

Ich hoffe, Sie verstehen, was der Code tut. Ich habe das Problem mathematisch betrachtet. Das Wörterbuch dictionary speichert die Nummer value nach der ersten value. Die sum_till_n Funktion ist eine Funktion, die die Summe der Zahlen bis n findet. Wie für n=3 gibt es 1+2+3 zurück.

+0

Werfen Sie einen Blick auf ['collections.defaultdict'] (https://docs.python.org/3.5/library/collections.html#collections.defaultdict), speziell' defaultdict (int) ', um das' if' aufzuräumen/'else' Code. – RoadieRich

+0

Wenn Sie auf Python 2 sind, ist 'if Wert in dictionary.keys():' unglaublich ineffizient; es erstellt eine "liste" kopie der diktasten und sucht sie dann linear. Verwenden Sie einfach 'if value in dictionary:', das eine 'O (1)' Suche im 'dict' selbst durchführt, ohne Kopien. Im Allgemeinen sind '.keys' /' .items'/'.values' alle schlechte Ideen in Python 2; Verwenden Sie ihre View-basierten Äquivalente, wenn Sie sie benötigen ('viewkeys' /' viewitems'/'viewvalues'), um Kopien zu vermeiden, aber normalerweise vermeiden Sie' viewkeys' gänzlich, es sei denn, Sie benötigen 'set'ähnliche Operationen (das' dict') selbst verhält sich sonst wie 'viewkeys'. – ShadowRanger

+0

Nicht sicher, warum dies abgelehnt wurde; Das OP hat das selbst gelöst, sie haben auch das Recht, eine Antwort zu schreiben. Und diese Antwort verwendet zufällig den richtigen Ansatz (obwohl ich mich frage, ob Sie 'x <2 'in' sum_till_n() 'überspringen sollten). –

0

Nehmen wir uns eine Minute das Problem und nicht Ihre Implementierung!

Die Aufgabe ist:

ein Array mit N Elementen A angegeben. Finde die Gesamtzahl der Paare (i, j) , so dass j < i und Aj = Ai.

Das ist das gleiche wie alle Duplikate in Ihrem Array zu finden!

Das Auffinden aller Duplikate ist eine sehr häufige Aufgabe.

Eine Lösung kann ich schnell denken:

  • Art Array von Tupeln (Wert, Index) (O (N) = N * log (N))
  • Querungs das Array einmal in Folge zu finden Duplikate

Hier ein Beispiel ist, wie die resultierenden Daten aussehen würde:

input = [2.0, 1.0, 3.0, 1.0] 
# create and sort tuples (I will leave this task to you) 
sorted_tuples = [(1.0, 1), (1.0, 3), (2.0, 0), (3.0, 2)] 
# find consecutive duplicates (I will leave this task to you) 
solution = [(3, 1)] 
+0

Es wird nicht nur alle Duplikate gefunden. Sie finden die * Anzahl der Paare *, die Sie aus diesen Duplikaten erstellen können (die Anzahl der Kombinationen). Es kann in O (N) Zeit erreicht werden, keine Notwendigkeit zu sortieren, nur um Paare zu finden. –

+0

Ich war ein bisschen ungenau. Es geht um das Finden der Indexpaare. Sobald Sie alle Objekte mit dem gleichen Wert gefunden haben, ist der Aufbau aller Indexpaare trivial (und kompletter Unsinn). Die naive Lösung ist O (N^2) wie Blasensorte. @Martijn Pieters Ich bezweifle, dass es einen Algorithmus mit O (N) gibt, aber bitte beweise mich falsch. – Markus

+0

Siehe SomeName-Lösung. Es iteriert einmal über die Eingabeelemente (O (N)) und erstellt ein Zählwörterverzeichnis. Dann eine weitere O (K) -Schleife über die Zählungen (wobei K

Verwandte Themen