Solução 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;}
Nova solução. 19 bytes são incluídos paraimport java.math.*;
-8 bytes graças a @Nevay
r->{int z,i=0;for(BigInteger c=BigInteger.ZERO;c.min(c=c.setBit(z=r[i++]))!=c;);return z;}
Experimente online!
Editar
O algoritmo no meu programa original estava bom, mas o tamanho estático do tipo de dados usado significava que ele quebrou rapidamente quando o tamanho ficou acima de um certo limite.
Alterei o tipo de dados usado no cálculo para aumentar o limite de memória do programa para acomodar isso (usando BigInteger
precisão arbitrária em vez de int
ou long
). No entanto, isso torna discutível se isso conta ou não como O(1)
complexidade de espaço.
Deixarei intacta minha explicação abaixo, mas desejo acrescentar que agora acredito que é impossível alcançar a O(1)
complexidade do espaço sem fazer algumas suposições.
Prova
Defina N
como um número inteiro tal que 2 <= N
.
Let S
Ser uma lista representando uma série de números inteiros aleatórios [x{1}, ..., x{N}]
, onde x{i}
tem a restrição 1 <= x{i} <= N
.
A complexidade do tempo (na notação Big-O) necessária para percorrer esta lista exatamente uma vez por elemento é O(n)
O desafio dado é encontrar o primeiro valor duplicado na lista. Mais especificamente, estamos pesquisando o primeiro valor em S
que é uma duplicata de um item anterior na lista.
Seja p
e q
seja a posição de dois elementos na lista, tais que p < q
e x{p} == x{q}
. Nosso desafio passa a ser encontrar o menor q
que satisfaça essas condições.
A abordagem óbvia para esse problema é iterar através de S e verificar se x{i}
existe em outra lista T
: se x{i}
não existir T
, armazenamos T
. Se x{i}
existe T
, é o primeiro valor duplicado e, portanto, o menor q
, e, como tal, o retornamos. Essa eficiência de espaço é O(n)
.
Para alcançar a O(1)
complexidade do espaço e, ao mesmo O(n)
tempo, manter a complexidade do tempo, precisamos armazenar informações exclusivas sobre cada objeto da lista em uma quantidade finita de espaço. Por esse motivo, a única maneira de qualquer algoritmo executar emO(1)
a complexidade do espaço é se: 1. N recebe um limite superior correspondente à memória necessária para armazenar o número máximo de valores possíveis para um tipo de dados finito específico. 2. A reatribuição de uma única variável imutável não é contada de acordo com a complexidade, apenas o número de variáveis (uma lista sendo várias variáveis). 3. (Com base em outras respostas) A lista é (ou pelo menos os elementos da lista são) mutáveis e o tipo de dados da lista é predefinido como um número inteiro assinado, permitindo que alterações sejam feitas nos elementos adicionais da lista sem usar memória adicional.
1 e 3 exigem suposições e especificações sobre o tipo de dados, enquanto 2 exige que apenas o número de variáveis seja considerado para o cálculo da complexidade do espaço, em vez do tamanho dessas variáveis. Se nenhuma dessas suposições for aceita, seria impossível obter O(n)
complexidade de tempo e O(1)
complexidade de espaço.
Explicação
Uau, rapaz, este levou um tempo embaraçosamente longo para pensar um pouco no poder do cérebro.
Então, pegar o bônus é difícil. Precisamos operar sobre a lista inteira exatamente uma vez e rastrear quais valores já foram repetidos sem complexidade adicional de espaço.
A manipulação de bits resolve esses problemas. Inicializamos nosso O(1)
'armazenamento', um par de números inteiros, depois percorremos a lista, OU inserindo o i-ésimo bit em nosso primeiro número inteiro e armazenando o resultado no segundo.
Por exemplo, se temos 1101
e realizamos uma operação OR 10
, obtemos 1111
. Se fizermos outra sala de cirurgia 10
, ainda temos 1101
.
Logo, quando realizamos a operação OR e terminamos com o mesmo número, encontramos nossa duplicata. Nenhuma duplicata na matriz faz com que o programa atropele e lance uma exceção.