Complexidade de encontrar o maior

7

O que segue é o meu algoritmo para fazer isso no que acredito ser O(n)tempo e minha prova disso. Meu professor discorda que seja executado emO(n) e, em vez disso, pensa que é executado em Ω(n2)Tempo. Quaisquer comentários sobre a prova em si ou o estilo (ou seja, minhas idéias podem ser claras, mas a apresentação não).

A pergunta original:

Dado n números, encontre o maior mn entre eles a tempo o(nlogn). Você não pode assumir mais nada sobrem.

Minha resposta:

  1. Classifique o primeiro melementos da matriz. Isso levaO(1) tempo, pois isso depende totalmente da m, não n.
  2. Armazene-os em uma lista vinculada (mantendo a ordem classificada). Isso também levaO(1) pelo mesmo motivo acima.
  3. Para todos os outros elementos da matriz, teste se é maior que o menor elemento da lista vinculada. Isso levaO(n) tempo como n comparações devem ser feitas.
  4. Se o número for realmente maior, exclua o primeiro elemento da lista vinculada (a mais baixa) e insira o novo número no local que manteria a lista na ordem classificada. Isso levaO(1) tempo porque é limitado por uma constante (m) acima, pois a lista não cresce.
  5. Portanto, a complexidade total do algoritmo é O(n).

Estou ciente de que o uso de uma árvore vermelho-preta em oposição à lista vinculada é mais eficiente em termos constantes (como o limite superior constante é O(mlog2(m)) em oposição a m e o problema de manter um ponteiro para o elemento mais baixo da árvore (para facilitar as comparações) é eminentemente possível, simplesmente não me ocorreu na época.

Qual é a minha prova que está faltando? Existe uma maneira mais padrão de apresentá-lo (mesmo que esteja incorreto)?

soandos
fonte
11
"melhor que O(nlogn)"- isso é difícil. Suponho que você queira dizer Θ(nlogn)? Outro problema da questão é que não está claro semestá consertado.
Raphael
@ Rafael, estou lhe enviando o que tenho. Não faço ideia do que ele quis dizer. Suponha que é realmenteO(nlog2(n)) Com relação à questão de saber se mé fixo, não faço ideia. Quando calculei a complexidade, presumi que sim, mas não havia base para essa suposição.
Soandos
11
@soandos: Então você pergunta ao seu professor; nem você nem nós podemos trabalhar com meia pergunta. A propósito, o texto real que você cita tem outro problema: todo algoritmo éO(1)se você fixar o tamanho da entrada em 10 bilhões.
Raphael
11
@soandos: incorporei sua atualização na "citação". As respostas de Louis e Joe abordam seu problema suficientemente (imho). E imperdoável resolve o exercício, é claro.
Raphael
11
@soandos Se o que você queria era uma solução para o exercício (obrigado imperdoável), deveria ter pedido desde o início. Em vez disso, você perguntou algo como: "é meu algoritmoO(n)e como posso melhorar minha prova? "
Joe

Respostas:

17

Aqui está um O(n) algoritmo que resolve o problema.

  1. Use o pior caso O(n) algoritmo de seleção para determinar anm+1estatísticas de terceira ordem. Deixeik seja esse número, que é o menor dos m maiores números que estamos tentando determinar.

  2. Agora particione a matriz em torno do pivô kusando a partição QuickSort função de . Este passo levaO(n) também.

  3. Saída do m números maiores: são dados por k e todos os números na sub-matriz superior gerados pela partição na etapa 2.

Massimo Cafaro
fonte
11
Agradável. Dependendo do algoritmo escolhido em 1., 2. já pode ser feito.
Raphael
5

Seu algoritmo leva Θ(n+mn)Tempo. Eu suspeito que seu professor está procurando algo que levaO(n+nlogm) tempo, o que deve ser possível, talvez usando uma pilha ...

A fonte de sua discordância com o professor é que ele ou ela não parece pensar mé uma constante, apesar de como a pergunta está formulada. Se não for, entãoΘ(m) é muito pior que Θ(logm).

Louis
fonte
A árvore vermelho-preta não leva esse tempo?
Soandos
4
Essa resposta não informa ao OP onde ele errou em seu raciocínio, você pode esclarecer isso?
Juho
Veja a atualização para a pergunta
soandos
1

Correção
Falta na sua apresentação é o loop invariável para estabelecer a correção: você mantém a maiormelementos encontrados até o momento em uma lista vinculada. Assim, no final do seu algoritmo, você testou todos os elementos e, portanto, possui o maiormelementos na matriz. Seu algoritmo ainda está correto, mas declarar o objetivo da lista vinculada no início da descrição torna sua correção mais explícita.

Tempo de execução
log10(10 billion)=10, (na base 2, é aproximadamente ~ 33), o que é muito menor que 10 milhões. No exemplo dado,m é muitas vezes maior que logne, portanto, não acho que você possa assumir com segurança que m é constante.

Você deve fornecer um algoritmo que seja o(nlogn) enquanto m=o(n). Substituir sua lista vinculada e pesquisa linear por uma árvore de pesquisa binária equilibrada ou um min-heap alcançará este tempo de execução:O(mlogm+nlogm)=O(nlogm)=o(nlogn). (assumindom=o(n), caso contrário, seu tempo de execução é Θ(nlogn))

Caso você não esteja familiarizado com a notação, a intuição por trás o(nlogn) é <O(nlogn), mas consulte a pergunta correspondente em cs.SE para obter detalhes da notação.

Joe
fonte
Veja a atualização para a pergunta
soandos
Parece que sua resposta é a resposta mais próxima do que foi solicitado, mas acho que você pode simplesmente dizer com m=n/2 O algoritmo do OP faz com que Θ(n2).