Recentemente, tive uma entrevista, onde me fizeram uma pergunta " investigativa ".
A questão era:
Assuma que existe uma matriz de números inteiros (positivos), dos quais cada elemento é ou
+1
ou-1
em relação aos seus elementos adjacentes.Exemplo:
array = [4,5,6,5,4,3,2,3,4,5,6,7,8];
Agora procure
7
e retorne sua posição.
Eu dei esta resposta:
Armazene os valores em uma matriz temporária, classifique-os e aplique a pesquisa binária.
Se o elemento for encontrado, retorne sua posição na matriz temporária.
(Se o número estiver ocorrendo duas vezes, retorne a primeira ocorrência)
Mas eles não pareciam satisfeitos com esta resposta.
Qual é a resposta certa?
Respostas:
Você pode fazer uma pesquisa linear com etapas que geralmente são maiores do que 1. A observação crucial é que, se eg
array[i] == 4
e 7 ainda não apareceram, o próximo candidato para 7 está no índicei+3
. Use um loop while que repetidamente vai diretamente para o próximo candidato viável.Aqui está uma implementação, ligeiramente generalizada. Encontra a primeira ocorrência de
k
na matriz (sujeito à restrição + = 1) ou-1
se não ocorrer:resultado:
fonte
O(N)
, mas não acho que haja uma maneira mais rápida de fazer isso.Sua abordagem é muito complicada. Você não precisa examinar todos os elementos da matriz. O primeiro valor é
4
, portanto7
está, pelo menos,7-4
elementos ausentes, e você pode pular esses.Resultado do programa:
Editar: melhorado após comentários de @Raphael Miedl e @Martin Zabel.
fonte
if ((skip = 7 - array[i]) < 1) skip = 1;
parece complicar demais e pessimá-lo na minha opinião. Searray[i] == 200
você obtiver-193
e apenas pular 1 a cada vez, embora possa pular todos os 193. Por que não apenasi += abs(7 - array[i])
?skip
a diferença absoluta entre 7 earray[i]
.200
, você teria passado7
.+1
/-1
uns dos outros. Então pode ser apenasarray[0] == 200
e os outros são em sua maioria-1
.Uma variação da pesquisa linear convencional pode ser um bom caminho a percorrer. Vamos escolher um elemento, digamos
array[i] = 2
. Agora,array[i + 1]
será 1 ou 3 (ímpar),array[i + 2]
será (somente números inteiros positivos) 2 ou 4 (número par).Ao continuar assim, um padrão é observável -
array[i + 2*n]
manterá números pares e, portanto, todos esses índices podem ser ignorados.Além disso, podemos ver que
portanto, o índice
i + 5
deve ser verificado em seguida e um loop while pode ser usado para determinar o próximo índice a ser verificado, dependendo do valor encontrado no índicei + 5
.Embora isso tenha complexidade
O(n)
(tempo linear em termos de complexidade assintótica), é melhor do que uma pesquisa linear normal em termos práticos, pois todos os índices não são visitados.Obviamente, tudo isso será revertido se
array[i]
(nosso ponto de partida) for estranho.fonte
A abordagem apresentada por John Coleman é o que o entrevistador esperava, com toda a probabilidade.
Se você estiver disposto a ir um pouco mais complicado, pode aumentar a duração esperada do salto:
Chame o valor alvo k . Comece com o valor do primeiro elemento v na posição p e chame a diferença kv dv com o valor absoluto av . Para acelerar pesquisas negativas, dê uma olhada no último elemento como o outro valor u na posição o: se dv × du for negativo, k está presente (se qualquer ocorrência de k for aceitável, você pode restringir o intervalo do índice aqui da forma como a pesquisa binária faz). Se av + au for maior que o comprimento da matriz, k estará ausente. (Se dv × du é zero, V ou L é igual a k.)
Omitindo validade índice: Sonda o ( "Avançar") posição onde a sequência pode voltar a v com k no meio:
o = p + 2*av
.Se dv × du for negativo, encontre k (recursivamente?) De p + av para o-au;
se for zero, u é igual a k em o.
Se du é igual a dv e o valor no meio não é k, ou au excede av,
ou você não consegue encontrar k de p + av para o-au,
deixe
p=o; dv=du; av=au;
e continue sondando.(Para um flashback completo dos textos dos anos 60, veja com o Courier. Meu "primeiro segundo pensamento" foi usar
o = p + 2*av - 1
, o que exclui du equals dv .)fonte
PASSO 1
Comece com o primeiro elemento e verifique se é 7. Digamos que
c
seja o índice da posição atual. Portanto, inicialmentec = 0
,.PASSO 2
Se for 7, você encontrou o índice. É
c
. Se você alcançou o final do array, saia.ETAPA 3
Se não for, então 7 devem estar pelo menos
|array[c]-7|
posições de distância, porque você só pode adicionar uma unidade por índice. Portanto, adicione|array[c]-7|
ao seu índice atual, c, e vá para o PASSO 2 novamente para verificar.No pior caso, quando há alternativos 1 e -1s, a complexidade do tempo pode chegar a O (n), mas os casos médios seriam entregues rapidamente.
fonte
|c-7|
onde|array[c]-7|
parece necessário.)array[c]-7
pode ser positivo ou negativo. Você precisa se inscreverabs()
antes de avançar.array[c] - 7
com o operador de módulo|array[c] - 7|
,.Aqui estou dando a implementação em java ...
fonte
Aqui está uma solução de estilo dividir e conquistar. À custa de (muito) mais contabilidade, podemos pular mais elementos; em vez de digitalizar da esquerda para a direita, teste no meio e pule nas duas direções.
fonte
Queria incluir uma solução recursiva para o problema. Aproveitar
fonte