Solución anterior de 65 bytes:
r->{for(int a,b=0,z,i=0;;b=a)if((a=b|1<<(z=r[i++]))==b)return z;}
Nueva solución Se incluyen 19 bytes paraimport java.math.*;
-8 bytes gracias a @Nevay
r->{int z,i=0;for(BigInteger c=BigInteger.ZERO;c.min(c=c.setBit(z=r[i++]))!=c;);return z;}
Pruébalo en línea!
Editar
El algoritmo en mi programa original estaba bien, pero el tamaño estático del tipo de datos utilizado significaba que se rompió bastante rápido una vez que el tamaño superó un cierto umbral.
He cambiado el tipo de datos utilizado en el cálculo para aumentar el límite de memoria del programa para acomodar esto (utilizando BigInteger
precisión arbitraria en lugar de int
o long
). Sin embargo, esto hace discutible si esto cuenta o no como O(1)
complejidad espacial.
Dejaré mi explicación a continuación intacta, pero deseo agregar que ahora creo que es imposible lograr O(1)
la complejidad del espacio sin hacer algunas suposiciones.
Prueba
Definir N
como un entero tal que 2 <= N
.
Deje S
ser una lista que representa una serie de enteros aleatorios [x{1}, ..., x{N}]
, donde x{i}
tiene la restricción 1 <= x{i} <= N
.
La complejidad de tiempo (en notación Big-O) requerida para recorrer esta lista exactamente una vez por elemento es O(n)
El desafío dado es encontrar el primer valor duplicado en la lista. Más específicamente, estamos buscando el primer valor S
que es un duplicado de un elemento anterior en la lista.
Dejar p
y q
ser las posiciones de dos elementos en la lista de tal manera que p < q
y x{p} == x{q}
. Nuestro desafío es encontrar el más pequeño q
que satisfaga esas condiciones.
El enfoque obvio para este problema es recorrer en iteración S y verificar si x{i}
existe en otra lista T
: si x{i}
no existe en T
, la almacenamos T
. Si x{i}
existe en T
, es el primer valor duplicado y, por lo tanto, el más pequeño q
, y como tal lo devolvemos. Esta eficiencia espacial es O(n)
.
Para lograr O(1)
la complejidad del espacio mientras se mantiene la O(n)
complejidad del tiempo, tenemos que almacenar información única sobre cada objeto en la lista en una cantidad finita de espacio. Debido a esto, la única forma en que cualquier algoritmo podría funcionar enO(1)
la complejidad del espacio es si: 1. A N se le asigna un límite superior correspondiente a la memoria requerida para almacenar el número máximo de valores posibles para un tipo de datos finito en particular. 2. La reasignación de una sola variable inmutable no se cuenta en función de la complejidad, solo el número de variables (una lista son múltiples variables). 3. (Basado en otras respuestas) La lista es (o al menos, los elementos de la lista son) mutables, y el tipo de datos de la lista está preestablecido como un entero con signo, lo que permite que se realicen cambios en los elementos más adelante en la lista sin usar memoria adicional.
1 y 3 requieren supuestos y especificaciones sobre el tipo de datos, mientras que 2 requiere que solo se considere el número de variables para el cálculo de la complejidad del espacio, en lugar del tamaño de esas variables. Si no se acepta ninguno de estos supuestos, sería imposible lograr la O(n)
complejidad del tiempo y O(1)
la complejidad del espacio.
Explicación
Whoo boy, este tomó un tiempo vergonzosamente largo para pensar un poco de poder mental.
Entonces, ir por la bonificación es difícil. Necesitamos ambos para operar sobre la lista completa exactamente una vez y rastrear qué valores ya hemos iterado sin complejidad de espacio adicional.
La manipulación de bits resuelve esos problemas. Inicializamos nuestro O(1)
'almacenamiento', un par de enteros, luego iteramos a través de la lista, OR-on el bit i en nuestro primer entero y almacenamos ese resultado en el segundo.
Por ejemplo, si tenemos 1101
, y realizamos una operación OR con 10
, obtenemos 1111
. Si hacemos otro OR con 10
, todavía tenemos 1101
.
Ergo, una vez que realizamos la operación OR y terminamos con el mismo número, encontramos nuestro duplicado. Ningún duplicado en la matriz hace que el programa se ejecute y arroje una excepción.