Supongamos que se nos dan dos números y y que queremos encontrar para l \ le i, \, j \ le r .
El algoritmo ingenuo simplemente verifica todos los pares posibles; por ejemplo en ruby tendríamos:
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
Tengo la sensación de que podemos hacerlo mejor que la cuadrática. ¿Hay un mejor algoritmo para este problema?
                    
                        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
fuente
                
                fuente

jcorreri+1..ryicorrerl...r-1para ser precisos.Respuestas:
Podemos lograr tiempo de ejecución lineal en la longitud de la representación binaria de y :norte l r 
El prefijo en la representación binaria de y , que es el mismo para ambos valores, también es el mismo para todos los valores entre ellos. Entonces estos bits siempre serán .pag l r 0 0 
Como , el bit que sigue a este prefijo será en y en . Además, los números y están en el intervalo.r > l 1 r 0 0 l p 10n - | p | - 1 p 01n - | p | - 1 
Entonces, el máximo que estamos buscando es .0 0El | p |1n - | p | 
fuente
Es posible hacerlo en tiempo .O (logr ) 
El XOR máximo posible de cualquiera de los dos enteros de un intervalo puede determinarse a partir de , suponiendo que sean enteros. Este valor es igual a , donde es el valor más pequeño de modo que es mayor que .[ l , r ] l ⊕ r l , r 2pag- 1 pag 2pag l ⊕ r 
Aquí hay una implementación en C ++
fuente
Necesitamos maximizar el xor entre 'pequeño' y 'alto'. Así que tomemos un ejemplo para entender esto.
5 xo 2 = 101 xo 010 primer caso: el bit MSB no está establecido para ambos valores en el rango. Si queremos maximizar esto, entonces lo que tenemos que hacer es mantener el MSB de 5 (100) como está y pensar maximizando los bits inferiores restantes. Como sabemos que los bits más bajos, todos serán uno para el caso cuando todo es 11, que no es más que 3, es decir, 2 ^ 2-1. Como el problema es hablar del rango entre 2 y 5, definitivamente tenemos 3 en el rango. Entonces, todo lo que tenemos que hacer es encontrar el conjunto MSB más alto en el mayor de 2 valores y agregar los 1 restantes para los bits más bajos.
segundo caso: en cuanto al caso cuando MSB está configurado para ambos valores en el rango que hace xor, definitivamente tendrá esos bits establecidos como 0 y necesitamos volver a los bits más bajos. Nuevamente para bits más bajos, necesitamos repetir la misma lógica que el primer caso. ejemplo: (10, 12) (1010, 1100) Como puede ver que ambos tienen MSB configurado como 1, entonces tenemos que volver a los bits inferiores, que son 010 y 100. Ahora este problema es el mismo que el primer caso.
Hay varias formas de codificar esto. Lo que hice fue hacer solo el xor entre 'pequeño' y 'alto' y eso eliminará el bit MSB si ambos 'pequeño' y 'alto' tienen el bit MSB establecido. En caso de que no sea así, conservará el bit MSB. Después de eso, estoy tratando de hacer que todos los bits más bajos sean 1 descubriendo la potencia máxima de 2 en la salida xored y restando de 1.
fuente
Bueno, puedes usar el XOR de l y r para encontrar la respuesta.
Supongamos que l = 4 yr = 6.
l = 100, r = 110 (equivalentes binarios de estos números)
l⊕r = 0 10
Lo que esto significa es que el valor máximo que está buscando definitivamente tendrá su primer bit (MSB) como cero. (Piénselo, ¿es posible que su valor máximo tenga un 1 en el primer bit? Si fuera 01010 y 00101, el xor habría sido = 01 111, es decir, el valor máximo entre 01010 y 00101 definitivamente tendrá un 1 en su segundo bit desde la izquierda, no es posible obtener un 1 antes del segundo bit desde la izquierda, es decir, en el primer bit desde la izquierda)
Entonces, te quedan los 2 bits restantes para encontrar el máximo. Sabemos que el valor máximo posible cuando tenemos n bits con nosotros es = 2 n −1, por lo tanto, la respuesta en este caso será 2 2 -1 = 4-1 = 3.
Del ejemplo anterior, podemos hacer un algoritmo general para esto.
Paso 1. num = número de bits requeridos para representar max ( l , r )
Paso 2. res = l ⊕ r
Paso 3. pos = Posición del primer bit que se establece desde la izquierda en res (indexación basada en 0)
Paso 4. n = num - pos
Paso 5. ans = 2 n −1
Complejidad de tiempo = O (n)
fuente
Para cada dígito binario, hay 4 posibilidades: 1_y_1, 1_y_0, 0_y_1 o 0_y_0. Los posibles dígitos más bajos no hacen ninguna diferencia o desaparecen muy poco a la salida xor de elección del siguiente dígito. El mejor algoritmo posible es ignorar todos los dígitos inferiores y solo considerar los siguientes 2 disponibles, dadas las elecciones anteriores sobre dígitos superiores. Si esto es 1_and_1 o 0_and_0, la opción es clara, pero si este dígito es 1_and_0 vs 0_and_1 (que tienen un valor igual xor pero desigual) entonces recursivamente debería ser igual al algoritmo https://en.wikipedia.org/wiki/Edit_distance , lo que significa el peor caso de log cuadrado.
fuente
Para intervalos de 32 bits, acabo de encontrar esta
O(1)solución en los editoriales de Hacker Rank. No tengo idea de cómo funciona, pero funciona. (Quizás alguien pueda explicar por qué funciona).Fuente: https://www.hackerrank.com/challenges/maximizing-xor/editorial
fuente