Nehmen wir an, wir haben zwei Zahlen und und wollen für l \ le i, \, j \ le r finden .max ( i ⊕ j ) l ≤ i ,
Der naive Algorithmus überprüft einfach alle möglichen Paare; Zum Beispiel in Ruby hätten wir:
def max_xor(l, r)
max = 0
(l..r).each do |i|
(i..r).each do |j|
if (i ^ j > max)
max = i ^ j
end
end
end
max
end
Ich spüre, dass wir es besser als quadratisch machen können. Gibt es einen besseren Algorithmus für dieses Problem?
algorithms
algorithms
machine-learning
statistics
testing
terminology
asymptotics
landau-notation
reference-request
optimization
scheduling
complexity-theory
time-complexity
lower-bounds
communication-complexity
computational-geometry
computer-architecture
cpu-cache
cpu-pipelines
operating-systems
multi-tasking
algorithms
algorithm-analysis
education
correctness-proof
didactics
algorithms
data-structures
time-complexity
computational-geometry
algorithms
combinatorics
efficiency
partitions
complexity-theory
satisfiability
artificial-intelligence
operating-systems
performance
terminology
computer-architecture
Jacopo Notarstefano
quelle
quelle
j
laufeni+1..r
undi
laufen lassenl...r-1
, um genau zu sein.Antworten:
Wir können eine lineare Laufzeit in der Länge der binären Darstellung von l und r erreichen :n l r
Das Präfix in der Binärdarstellung von l und r , das für beide Werte gleich ist, ist auch für alle Werte zwischen ihnen gleich. Diese Bits werden also immer 0 sein .p l r 0
Da , ist das diesem Präfix folgende Bit 1 in r und 0 in l . Weiterhin sind die Zahlen p 10 n - | p | - 1 und p 01 n - | p | - 1 sind beide in der Pause.r>l 1 r 0 l p10n−|p|−1 p01n−|p|−1
Das gesuchte Maximum ist also .0|p|1n−|p|
quelle
Es ist möglich, dies in Zeit zu tun .O(logr)
Das maximal mögliche XOR von zwei beliebigen ganzen Zahlen aus einem Intervall kann aus l ⊕ r unter der Annahme bestimmt werden , dass l , r ganze Zahlen sind. Dieser Wert ist gleich 2 p - 1 , wobei p der kleinste Wert ist, so dass 2 p größer als l ⊕ r ist .[l,r] l⊕r l,r 2p−1 p 2p l⊕r
Hier ist eine Implementierung in C ++
quelle
Wir müssen das xor zwischen "klein" und "hoch" maximieren. Nehmen wir also ein Beispiel, um dies zu verstehen.
5 xor 2 = 101 xor 010 erster Fall: MSB-Bit ist nicht für beide Werte im Bereich gesetzt. Wenn dies maximiert werden soll, müssen wir das MSB von 5 (100) so belassen, wie es ist, und darüber nachdenken Maximieren der verbleibenden unteren Bits. Wie wir wissen, sind niedrigere Bits alle eins für den Fall, dass alles 11 ist, was nichts anderes als 3 ist, dh 2 ^ 2-1. Da es sich bei dem Problem um einen Bereich zwischen 2 und 5 handelt, haben wir definitiv 3 im Bereich. Wir müssen also nur den höchsten MSB-Satz im größeren von 2 Werten herausfinden und die verbleibenden Einsen für die unteren Bits hinzufügen.
Zweiter Fall: Wie für den Fall, dass MSB für beide Werte in dem Bereich gesetzt ist, in dem xor ausgeführt wird, werden diese Bits auf jeden Fall auf 0 gesetzt, und wir müssen zu niedrigeren Bits zurückkehren. Auch für niedrigere Bits müssen wir die gleiche Logik wie im ersten Fall wiederholen. Beispiel: (10, 12) (1010, 1100) Wie Sie sehen können, haben beide MSB auf 1 gesetzt, dann müssen wir zu niedrigeren Bits zurückkehren, nämlich 010 und 100. Jetzt ist dieses Problem dasselbe wie im ersten Fall.
Es gibt verschiedene Möglichkeiten, dies zu codieren. Was ich getan habe, ist, nur das xor zwischen "klein" und "hoch" zu machen, und das wird das MSB-Bit entfernen, wenn sowohl "klein" als auch "hoch" das MSB-Bit gesetzt haben. Ist dies nicht der Fall, wird das MSB-Bit beibehalten. Danach versuche ich, alle niedrigeren Bits zu 1 zu machen, indem ich die maximale Potenz von 2 in der xored Ausgabe herausfinde und von 1 subtrahiere.
quelle
Nun, Sie können das XOR von l und r verwenden , um die Antwort zu finden.
Angenommen, l = 4 und r = 6.
l = 100, r = 110 (binäre Äquivalente dieser Zahlen)
l⊕r = 0 10
Dies bedeutet, dass für den gesuchten Maximalwert das erste Bit (MSB) definitiv Null ist. (Denken Sie darüber nach, ist es sogar möglich, dass Ihr Maximalwert stattdessen eine 1 im ersten Bit hat? Wenn es 01010 und 00101 waren, wäre das xor = 01 111 gewesen, dh der Maximalwert zwischen 01010 und 00101 wird definitiv sein eine 1 in ihrem zweiten Bit von links, es ist nicht möglich, eine 1 vor dem zweiten Bit von links zu bekommen, dh im ersten Bit von links)
Sie haben also die verbleibenden 2 Bits, um das Maximum zu finden. Wir wissen, dass der maximal mögliche Wert, wenn wir n Bits bei uns haben, = 2 n −1 ist, daher lautet die Antwort in diesem Fall 2 2 -1 = 4-1 = 3.
Aus dem obigen Beispiel können wir einen allgemeinen Algorithmus dafür erstellen.
Schritt 1. num = Anzahl der zur Darstellung von max ( l , r ) erforderlichen Bits
Schritt 2. res = l ⊕ r
Schritt 3. pos = Position des ersten Bits, das in res von links gesetzt wird (0-basierte Indizierung)
Schritt 4. n = num - pos
Schritt 5. ans = 2 n −1
Zeitkomplexität = O (n)
quelle
Für jede Binärzahl gibt es 4 Möglichkeiten: 1_und_1, 1_und_0, 0_und_1 oder 0_und_0. Die möglichen niedrigeren Stellen machen keinen oder nur einen geringfügigen Unterschied zu der von Ihnen gewählten xor-Ausgabe der nächsten Stelle. Der bestmögliche Algorithmus besteht darin, alle niedrigeren Stellen zu ignorieren und nur die nächsten 2 verfügbaren Stellen zu berücksichtigen, vorausgesetzt, Sie haben zuvor eine Auswahl über höhere Stellen getroffen. Wenn dies 1_und_1 oder 0_und_0 ist, ist die Wahl klar, aber wenn diese Ziffer 1_und_0 gegen 0_und_1 ist (die das gleiche x oder aber einen ungleichen Wert haben), sollte sie rekursiv dem https://en.wikipedia.org/wiki/Edit_distance-Algorithmus entsprechen . was bedeutet, schlimmsten Fall von Log im Quadrat.
quelle
Für 32-Bit-Intervalle bin ich gerade auf diese
O(1)
Lösung in Hacker Rank-Editorials gestoßen. Ich habe keine Ahnung, wie es funktioniert, aber es funktioniert. (Vielleicht kann jemand erklären, warum es funktioniert.)Quelle: https://www.hackerrank.com/challenges/maximizing-xor/editorial
quelle