Existem algoritmos O (1 / n)?
Ou qualquer outra coisa que seja menor que O (1)?
theory
complexity-theory
big-o
Peter Mortensen
fonte
fonte
Respostas:
Esta questão não é tão estúpida quanto possa parecer. Pelo menos teoricamente, algo como O (1 / n ) é completamente sensível quando adotamos a definição matemática da notação O grande :
Agora você pode facilmente substituir g ( x ) por 1 / x … é óbvio que a definição acima ainda vale para alguns f .
Com o objetivo de estimar o crescimento assintótico do tempo de execução, isso é menos viável ... um algoritmo significativo não pode ficar mais rápido à medida que a entrada cresce. Claro, você pode construir um algoritmo arbitrário para cumprir isso, por exemplo, o seguinte:
Claramente, essa função gasta menos tempo à medida que o tamanho da entrada aumenta ... pelo menos até algum limite, imposto pelo hardware (precisão dos números, tempo mínimo que
sleep
pode esperar, tempo para processar argumentos etc.): esse limite seria então um limite inferior constante; de fato, a função acima ainda possui o tempo de execução O (1).Mas não são de fato algoritmos do mundo real, onde o tempo de execução pode diminuir (pelo menos parcialmente) quando o tamanho de entrada aumenta. Observe que esses algoritmos não exibem comportamento em tempo de execução abaixo de O (1). Ainda assim, eles são interessantes. Por exemplo, considere o algoritmo de pesquisa de texto muito simples da Horspool . Aqui, o tempo de execução esperado diminuirá à medida que a duração do padrão de pesquisa aumentar (mas o aumento da duração do palheiro aumentará novamente o tempo de execução).
fonte
Sim.
Existe precisamente um algoritmo com tempo de execução O (1 / n), o algoritmo "vazio".
Para um algoritmo ser O (1 / n), significa que ele é executado assintoticamente em menos etapas que o algoritmo que consiste em uma única instrução. Se for executado em menos de um passo para todos os n> n0, deverá consistir precisamente em nenhuma instrução para os n. Como a verificação de 'se n> n0' custa pelo menos 1 instrução, ela não deve consistir em nenhuma instrução para todos os n.
Resumindo: O único algoritmo que é O (1 / n) é o algoritmo vazio, que não consiste em nenhuma instrução.
fonte
sharptooth está correto, O (1) é o melhor desempenho possível. No entanto, isso não implica uma solução rápida, apenas uma solução em tempo fixo.
Uma variante interessante, e talvez o que realmente esteja sendo sugerido, é quais problemas ficam mais fáceis à medida que a população cresce. Eu posso pensar em uma resposta, embora artificial e explícita:
Duas pessoas em um set têm o mesmo aniversário? Quando n exceder 365, retorne true. Embora para menos de 365, este seja O (n ln n). Talvez não seja uma ótima resposta, pois o problema não fica lentamente mais fácil, mas se torna O (1) para n> 365.
fonte
Isso não é possível. A definição de Big-O não é maior que desigualdade:
Portanto, B (n) é de fato o valor máximo; portanto, se diminuir à medida que n aumenta, a estimativa não será alterada.
fonte
Do meu aprendizado anterior sobre a grande notação O, mesmo que você precise de 1 etapa (como verificar uma variável, realizar uma atribuição), é O (1).
Observe que O (1) é o mesmo que O (6), porque a "constante" não importa. É por isso que dizemos que O (n) é o mesmo que O (3n).
Portanto, se você precisar de apenas 1 passo, é O (1) ... e como seu programa precisa de pelo menos 1 passo, o mínimo que um algoritmo pode seguir é O (1). A menos que não façamos, então é O (0), eu acho? Se fizermos alguma coisa, então é O (1), e esse é o mínimo que pode ser.
(Se escolhermos não fazê-lo, isso poderá se tornar uma pergunta Zen ou Tao ... no domínio da programação, O (1) ainda é o mínimo).
Ou que tal:
programador : chefe, encontrei uma maneira de fazer isso em O (1) tempo!
chefe : não há necessidade de fazê-lo, estamos falidos esta manhã.
programador : oh, então, torna-se O (0).
fonte
Não, isso não é possível:
Como n tende ao infinito em 1 / n, finalmente alcançamos 1 / (inf), que é efetivamente 0.
Assim, a classe grande-oh do problema seria O (0) com um n massivo, mas mais próximo do tempo constante com um n baixo. Isso não é sensato, pois a única coisa que pode ser feita mais rapidamente que o tempo constante é:
void nothing() {};
E mesmo isso é discutível!
Assim que você executa um comando, você está em pelo menos O (1), então não, não podemos ter uma grande classe de O (1 / n)!
fonte
Que tal não executar a função (NOOP)? ou usando um valor fixo. Isso conta?
fonte
Costumo usar O (1 / n) para descrever probabilidades que diminuem à medida que as entradas aumentam - por exemplo, a probabilidade de uma moeda justa aparecer depois do log2 (n) é O (1 / n).
fonte
O (1) significa simplesmente "tempo constante".
Quando você adiciona uma saída antecipada a um loop [1], está (em notação big-O) transformando um algoritmo O (1) em O (n), mas tornando-o mais rápido.
O truque é, em geral, o algoritmo de tempo constante é o melhor e o linear é melhor que o exponencial, mas para pequenas quantidades de n, o algoritmo exponencial pode ser realmente mais rápido.
1: Assumindo um comprimento de lista estático para este exemplo
fonte
Para quem ler esta pergunta e quiser entender do que se trata a conversa, isso pode ajudar:
fonte
Acredito que algoritmos quânticos podem fazer vários cálculos "de uma só vez" via superposição ...
Duvido que seja uma resposta útil.
fonte
muitas pessoas tiveram a resposta correta (Não) Aqui está outra maneira de provar isso: Para ter uma função, você deve chamar a função e retornar uma resposta. Isso leva uma certa quantidade constante de tempo. MESMO QUE o restante do processamento levou menos tempo para entradas maiores, imprimir a resposta (que podemos assumir como um único bit) leva pelo menos tempo constante.
fonte
Se a solução existe, pode ser preparada e acessada em tempo constante = imediatamente. Por exemplo, usando uma estrutura de dados LIFO, se você souber que a consulta de classificação é por ordem inversa. Os dados já estão classificados, dado que o modelo apropriado (LIFO) foi escolhido.
fonte
Quais problemas ficam mais fáceis à medida que a população cresce? Uma resposta é uma coisa como bittorrent, em que a velocidade do download é uma função inversa do número de nós. Ao contrário de um carro, que diminui a velocidade do carregamento, uma rede de compartilhamento de arquivos como o bittorrent acelera os nós conectados.
fonte
Você não pode ir abaixo de O (1), no entanto O (k) onde k é menor que N é possível. Nós os chamamos de algoritmos de tempo sublinear . Em alguns problemas, o algoritmo de tempo sublinhado pode fornecer apenas soluções aproximadas para um problema específico. No entanto, às vezes, uma solução aproximada é ótima, provavelmente porque o conjunto de dados é muito grande ou muito caro em termos computacionais para calcular tudo.
fonte
Que tal isso:
À medida que o tamanho da lista aumenta, o tempo de execução esperado do programa diminui.
fonte
constains
é O (1)O (1 / n) não é menor que O (1), basicamente significa que quanto mais dados você tiver, mais rápido será o algoritmo. Digamos que você obtenha uma matriz e sempre preencha até 10 100 elementos se ela tiver menos que isso e não faça nada se houver mais. Este não é O (1 / n), é claro, mas algo como O (-n) :) A notação O-big muito ruim não permite valores negativos.
fonte
Como foi apontado, além da possível exceção da função nula, não pode haver
O(1/n)
funções, pois o tempo necessário terá que se aproximar de 0.Obviamente, existem alguns algoritmos, como o definido por Konrad, que parecem ser menos do que
O(1)
em pelo menos algum sentido.Se você deseja investigar esses algoritmos, defina sua própria medida assintótica ou sua própria noção de tempo. Por exemplo, no algoritmo acima, eu poderia permitir o uso de várias operações "gratuitas" por um determinado período de vezes. No algoritmo acima, se eu definir t 'excluindo o tempo para tudo, menos o sono, então t' = 1 / n, que é O (1 / n). Provavelmente existem exemplos melhores, pois o comportamento assintótico é trivial. Na verdade, tenho certeza de que alguém lá fora pode ter sentidos que dão resultados não triviais.
fonte
A maioria das demais respostas interpreta big-O como sendo exclusivamente sobre o tempo de execução de um algoritmo. Mas como a pergunta não mencionou, achei que vale a pena mencionar a outra aplicação de big-O na análise numérica, que é sobre erro.
Muitos algoritmos podem ser O (h ^ p) ou O (n ^ {- p}), dependendo do tamanho da etapa (h) ou do número de divisões (n). Por exemplo, no método de Euler , você procura uma estimativa de y (h), considerando que conhece y (0) e dy / dx (a derivada de y). Sua estimativa de y (h) é mais precisa quanto mais próximo h estiver de 0. Portanto, para encontrar y (x) para algum x arbitrário, é preciso pegar o intervalo de 0 a x, dividi-lo até n pedaços e executar o método de Euler em cada ponto, para ir de y (0) a y (x / n) a y (2x / n) e assim por diante.
Portanto, o método de Euler é um algoritmo O (h) ou O (1 / n), em que h é tipicamente interpretado como um tamanho de etapa en é interpretado como o número de vezes que você divide um intervalo.
Você também pode ter O (1 / h) em aplicativos de análise numérica reais, devido a erros de arredondamento de ponto flutuante . Quanto menor o intervalo, mais cancelamentos ocorrem para a implementação de determinados algoritmos, mais perda de dígitos significativos e, portanto, mais erros, que são propagados pelo algoritmo.
Para o método de Euler, se você estiver usando pontos flutuantes, use uma etapa e o cancelamento suficientemente pequenos e adicione um número pequeno a um número grande, deixando o número grande inalterado. Para algoritmos que calculam a derivada subtraindo um ao outro dois números de uma função avaliada em duas posições muito próximas, aproximando y '(x) de (y (x + h) - y (x) / h), em funções suaves y (x + h) se aproxima de y (x) resultando em cancelamento grande e uma estimativa para o derivado com menos números significativos. Por sua vez, isso será propagado para qualquer algoritmo para o qual você precise da derivada (por exemplo, um problema de valor limite).
fonte
OK, pensei um pouco sobre isso, e talvez exista um algoritmo que possa seguir esta forma geral:
Você precisa calcular o problema do vendedor ambulante para um gráfico de 1000 nós; no entanto, você também recebe uma lista de nós que não pode visitar. À medida que a lista de nós invisíveis aumenta, o problema se torna mais fácil de resolver.
fonte
Eu vejo um algoritmo que é O (1 / n) reconhecidamente em um limite superior:
Você tem uma grande série de entradas que estão sendo alteradas devido a algo externo à rotina (talvez elas reflitam o hardware ou pode ser outro núcleo no processador que está fazendo isso.) E você deve selecionar uma aleatória, mas válida.
Agora, se não estivesse mudando, você simplesmente faria uma lista de itens, escolha um aleatoriamente e obtenha O (1). No entanto, a natureza dinâmica dos dados impede a criação de uma lista. Você simplesmente precisa fazer uma sondagem aleatória e testar a validade da sondagem. (E observe que, inerentemente, não há garantia de que a resposta ainda seja válida quando for devolvida. Isso ainda pode ter utilidades - por exemplo, a IA de uma unidade em um jogo. Ele poderia disparar contra um alvo que desapareceu de vista enquanto estava apertando o gatilho.)
Isso tem um desempenho de infinito no pior caso, mas um desempenho médio de caso que diminui à medida que o espaço de dados se enche.
fonte
Na análise numérica, os algoritmos de aproximação devem ter complexidade assintótica sub-constante na tolerância de aproximação.
fonte
Eu acho que menos de O (1) não é possível. Qualquer tempo gasto por algo é denominado O (1). Mas para O (1 / n), que tal a função abaixo. (Eu sei que existem muitas variantes já apresentadas nesta solução, mas acho que todas elas têm algumas falhas (não são importantes, explicam bem o conceito). Então, aqui está uma, apenas por uma questão de argumento:
Assim, à medida que n aumenta, a função leva cada vez menos tempo. Também é garantido que, se a entrada realmente for 0, a função levará uma eternidade para retornar.
Pode-se argumentar que será limitado pela precisão da máquina. portanto, sinc eit tem um limite superior, é O (1). Mas também podemos ignorar isso, inserindo entradas de n e C na string. E adição e comparação são feitas na string. A idéia é que, com isso, possamos reduzir n arbitrariamente pequenos. Portanto, o limite superior da função não é limitado, mesmo quando ignoramos n = 0.
Eu também acredito que não podemos apenas dizer que o tempo de execução é O (1 / n). Mas devemos dizer algo como O (1 + 1 / n)
fonte
Pode ser possível construir um algoritmo que seja O (1 / n). Um exemplo seria um loop que itera alguns múltiplos de f (n) -n vezes em que f (n) é alguma função cujo valor é garantido maior que n e o limite de f (n) -n à medida que n se aproxima do infinito é zero. O cálculo de f (n) também precisaria ser constante para todos os n. Eu não sei de imediato como seria f (n) ou qual aplicativo esse algoritmo teria, na minha opinião, porém, essa função poderia existir, mas o algoritmo resultante não teria outro objetivo senão provar a possibilidade de um algoritmo com O (1 / n).
fonte
Eu não sei sobre algoritmos, mas complexidades menores que O (1) aparecem em algoritmos aleatórios. Na verdade, o (1) (pouco o) é menor que O (1). Esse tipo de complexidade geralmente aparece em algoritmos aleatórios. Por exemplo, como você disse, quando a probabilidade de algum evento é da ordem 1 / n, eles o denotam com o (1). Ou quando eles querem dizer que algo acontece com alta probabilidade (por exemplo, 1 - 1 / n), eles denotam isso com 1 - o (1).
fonte
Se a resposta for a mesma, independentemente dos dados de entrada, você terá um algoritmo O (0).
ou em outras palavras - a resposta é conhecida antes dos dados de entrada serem enviados - a função pode ser otimizada - então O (0)
fonte
A notação Big-O representa a pior cenário para um algoritmo que não é a mesma coisa que seu tempo de execução típico. É simples provar que um algoritmo O (1 / n) é um algoritmo O (1). Por definição,
O (1 / n) -> T (n) <= 1 / n, para todos n> = C> 0
O (1 / n) -> T (n) <= 1 / C, uma vez que 1 / n <= 1 / C para todos n> = CO
(1 / n) -> O (1), pois a notação Big-O ignora constantes (ou seja, o valor de C não importa)
fonte
hashtable-contains
algoritmo que pode ser indicado como O (1) - e o pior caso pode ser dado com muita precisão como Theta (n)! Omega e Theta podem simplesmente ser usados para denotar outros limites, mas para repetir : eles não têm nada a ver com o melhor ou o médio.Nada é menor que a notação O (1) Big-O implica a maior ordem de complexidade para um algoritmo
Se um algoritmo tem um tempo de execução de n ^ 3 + n ^ 2 + n + 5, então é O (n ^ 3) As potências mais baixas não têm importância aqui porque, como n -> Inf, n ^ 2 será irrelevante em comparação com n ^ 3
Da mesma forma que n -> Inf, O (1 / n) será irrelevante em comparação com O (1), portanto, 3 + O (1 / n) será o mesmo que O (1), tornando O (1) o menor valor computacional possível complexidade
fonte
fonte
Aqui está um algoritmo O (1 / n) simples. E até faz algo interessante!
O (1 / n) é possível, pois descreve como a saída de uma função é alterada, considerando o tamanho crescente da entrada. Se estivermos usando a função 1 / n para descrever o número de instruções que uma função executa, não há requisitos para que a função siga zero instruções para qualquer tamanho de entrada. Pelo contrário, é que para cada tamanho de entrada, n acima de algum limite, o número de instruções necessárias é limitado acima por uma constante positiva multiplicada por 1 / n. Como não existe um número real para o qual 1 / n seja 0 e a constante seja positiva, não há razão para que a função seja restrita a receber 0 ou menos instruções.
fonte