Existem algoritmos O (1 / n)?


335

Existem algoritmos O (1 / n)?

Ou qualquer outra coisa que seja menor que O (1)?


A maioria das perguntas pressupõe que você quer dizer "Existem algoritmos com uma complexidade temporal de O (1 / n)?" Vamos assumir que este é o caso? Big-O (e Big-Theta, etc.) descrevem funções, não algoritmos. (Não sei de nenhuma equivalência entre funções e algoritmos.)
jyoungdev

4
Essa é a definição comumente entendida de "algoritmo O (X)" em ciência da computação: um algoritmo cuja complexidade de tempo é O (X) (para alguma expressão X).
David Z

2
Eu ouvi esse limite no caso do algoritmo de fila de prioridade eficiente de E / S usando a Árvore de Buffer. Em uma árvore de buffer, cada operação recebe E / Ss (1 / B); onde B é o tamanho do bloco. E o total de E / S para n operações é O (n / B.log (base M / B) (n / B)), em que parte do log é a altura da árvore do buffer.
CODError

Existem muitos algoritmos com probabilidade de erro O (1 / n). Por exemplo, um filtro de bloom com baldes O (n log n).
Thomas Ahle 16/05

Você não pode pôr um ovo mais rápido adicionando galinhas.
Wyck

Respostas:


310

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:

def get_faster(list):
    how_long = (1 / len(list)) * 100000
    sleep(how_long)

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 sleeppode 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).


22
'Reforçado pelo hardware' também se aplica a uma máquina de Turing. No caso de O (1 / n), sempre haverá um tamanho de entrada para o qual o algoritmo não deve executar nenhuma operação. E, portanto, eu pensaria que a complexidade do tempo O (1 / n) é realmente impossível de alcançar.
Roland Ewald

28
Mehrdad, você não entende. A notação O é algo sobre o limite (tecnicamente lim sup) como n -> ∞. O tempo de execução de um algoritmo / programa é o número de etapas em alguma máquina e, portanto, é discreto - há um limite inferior a zero no tempo que um algoritmo pode levar ("uma etapa"). Ele é possível que até alguns N finito um programa leva um número de etapas decrescentes com n, mas a única maneira que um algoritmo pode ser O (1 / n), ou, de facto o (1), é se leva tempo 0 para todos suficientemente grande n - o que não é possível.
ShreevatsaR

28
Não estamos discordando da existência de funções O (1 / n) (no sentido matemático). Obviamente eles fazem. Mas a computação é inerentemente discreta. Algo que tem um limite inferior, como o tempo de execução de um programa - na arquitetura von Neumann ou em uma máquina de Turing puramente abstrata - não pode ser O (1 / n). Equivalentemente, algo que é O (1 / n) não pode ter um limite inferior. (Sua função "sleep" deve ser chamada ou a variável "list" deve ser examinada - ou a fita de entrada deve ser examinada em uma máquina de Turing. Portanto, o tempo necessário mudaria com n, pois alguns ε + 1 / n, que não é O (1 / n))
ShreevatsaR

16
Se T (0) = ∞, ele não pára. Não existe algo como "T (0) = ∞, mas ainda pára". Além disso, mesmo se você trabalhar em R∪ {∞} e definir T (0) = ∞, e T (n + 1) = T (n) / 2, então T (n) = ∞ para todos os n. Deixe-me repetir: se uma função de valor discreto é O (1 / n), então para todos n suficientemente grandes é 0. [Prova: T (n) = O (1 / n) significa que existe uma constante c tal que para n> N0, T (n) <c (1 / n), o que significa que para qualquer n> max (N0,1 / c), T (n) <1, o que significa T (n) = 0.] Nenhuma máquina, real ou abstrata, pode demorar 0 tempo: precisa observar a entrada. Bem, além da máquina que nunca faz nada, e para a qual T (n) = 0 para todos os n.
ShreevatsaR

43
Você precisa gostar de qualquer resposta que comece "Esta pergunta não é tão estúpida quanto pode parecer".
Telêmaco

138

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.


2
Então, se alguém perguntasse qual é a complexidade de tempo de um algoritmo vazio, você responderia com O (1 / n) ??? De alguma forma eu duvido disso.
phkahler

24
Esta é a única resposta correta neste tópico, e (apesar do meu voto positivo), ela tem zero votos. É o StackOverflow, onde as respostas "corretas" são votadas mais altas do que as corretas.
ShreevatsaR

5
Não, é classificado como 0 porque está incorreto. A expressão de um valor grande-Oh em relação a N quando é independente de N está incorreta. Segundo, executar qualquer programa, mesmo que exista, leva pelo menos uma quantidade constante de tempo, O (1). Mesmo que não fosse esse o caso, seria O (0), não O (1 / n).
kenj0418

32
Qualquer função que seja O (0) também é O (1 / n) e também O (n), também O (n ^ 2), também O (2 ^ n). Suspiro, ninguém entende definições simples? O () é um limite superior.
ShreevatsaR

16
@ kenj0418 Você conseguiu estar errado em cada frase. "Expressar um valor grande-Oh em relação a N quando é independente de N está incorreto." Uma função constante é uma função perfeitamente divertida. "Segundo, executar qualquer programa, mesmo que exista, leva pelo menos uma quantidade constante de tempo, O (1)." A definição de complexidade não diz nada sobre a execução de nenhum programa. "seria O (0), não O (1 / n)". Veja o comentário de @ ShreevatsaR.
Alexey Romanov

25

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.


7
366. Não se esqueça dos anos bissextos!
25410 Nick Johnson

11
Você está certo. Tal como os computadores, eu sou ocasionalmente sujeita a erros de arredondamento :-)
Adrian

10
+1. Há vários problemas de NP-completo que passam por uma "transição de fase" à medida que n aumenta, ou seja, eles rapidamente se tornam muito mais fáceis ou muito mais difíceis à medida que você excede um determinado valor limite de n. Um exemplo é o Problema de Particionamento Numérico: dado um conjunto de n números inteiros não negativos, divida-os em duas partes para que a soma de cada parte seja igual. Isso fica muito mais fácil com um certo valor limite de n.
j_random_hacker

23

Isso não é possível. A definição de Big-O não é maior que desigualdade:

A(n) = O(B(n))
<=>
exists constants C and n0, C > 0, n0 > 0 such that
for all n > n0, A(n) <= C * B(n)

Portanto, B (n) é de fato o valor máximo; portanto, se diminuir à medida que n aumenta, a estimativa não será alterada.


42
Suspeito que esta resposta seja a "correta", mas infelizmente não tenho o intelecto para entendê-la.
Freespace

12
AFAIK, essa condição não precisa ser verdadeira para todos os n, mas para todos os n> n_0 (ou seja, somente quando o tamanho da entrada atingir um limite específico).
Roland Ewald

30
Não vejo como a definição (mesmo corrigida) contradiz a questão do OP. A definição vale para funções completamente arbitrárias! 1 / n é uma função completamente sensível para B e, de fato, sua equação não contradiz isso (faça as contas). Portanto, não, apesar de muito consenso, esta resposta está de fato errada . Desculpa.
Konrad Rudolph

10
Errado! Não gosto de voto negativo, mas você afirma que isso é impossível quando não há um consenso claro. Na prática, você está correto, se você construir uma função com 1 / n tempo de execução (fácil), ela atingirá algum tempo mínimo, efetivamente tornando-o um algoritmo O (1) quando implementado. Não há nada para impedir que o algoritmo seja O (1 / n) no papel.
21139 jheriko

3
@ Jason: Sim, agora que você diz ... :) @ jheriko: Uma complexidade de tempo de O (1 / n) não funciona no IMHO em papel. Estamos caracterizando a função de crescimento f (tamanho da entrada) = #ops para uma máquina de Turing. Se ele parar para uma entrada de comprimento n = 1 após x etapas, escolherei um tamanho de entrada n >> x, ou seja, grande o suficiente para que, se o algoritmo estiver realmente em O (1 / n), nenhuma operação deve ser realizada. feito. Como uma máquina de Turing deve perceber isso (não é permitido ler uma vez da fita)?
Roland Ewald

16

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).


Sua piada me lembrou algo do Tao da programação: canonical.org/~kragen/tao-of-programming.html#book8 (8.3)
kenj0418

Um algoritmo que consiste em zero etapas é O (0). Esse é um algoritmo muito preguiçoso.
nalply

8

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)!


7

Que tal não executar a função (NOOP)? ou usando um valor fixo. Isso conta?


16
Ainda é tempo de execução O (1).
289 Konrad Rudolph

2
Certo, ainda é O (1). Não vejo como alguém possa entender isso e, ainda assim, afirmo em outra resposta que algo menos que NO-OP é possível.
ShreevatsaR

4
ShreevatsaR: não há absolutamente nenhuma contradição. Você parece não entender que a notação O grande não tem nada a ver com o tempo gasto na função - mas descreve como esse tempo muda com a alteração da entrada (acima de um determinado valor). Veja outro tópico de comentário para obter mais informações.
219 Konrad Rudolph

Entendo perfeitamente bem, obrigado. O ponto - como fiz várias vezes no outro encadeamento - é que, se o tempo diminuir com a entrada, na taxa O (1 / n), deverá eventualmente diminuir abaixo do tempo gasto pelo NOOP. Isso mostra que nenhum algoritmo pode ser O (1 / n) assintoticamente, embora certamente seu tempo de execução possa diminuir até um limite.
precisa

11
Sim ... como eu disse em outro lugar, qualquer algoritmo que seja O (1 / n) também deve levar tempo zero para todas as entradas, portanto, dependendo de você considerar o algoritmo nulo como tendo 0 tempo ou não, existe um O (1 / n) algoritmo. Então , se você considerar NOOP para ser O (1), então não há nenhum O (1 / N) algoritmos.
precisa

7

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).


6
Mas não é esse o grande O. Você não pode simplesmente redefini-lo para responder à pergunta.
Zifre 25/05/09

11
Não é uma redefinição, é exatamente a definição de grande O.
ShreevatsaR

10
Eu sou um cientista da computação teórico por profissão. É sobre a ordem assintótica de uma função.
252 Dave

4
Big O é uma propriedade de uma função real arbitrária. A complexidade do tempo é apenas uma de suas possíveis aplicações. A complexidade do espaço (a quantidade de memória de trabalho que um algoritmo usa) é outra. O fato de a questão ser sobre algoritmos O (1 / n) implica que é um deles (a menos que exista outro que se aplique a algoritmos dos quais eu não conheço). Outras aplicações incluem ordens de crescimento populacional, por exemplo, na vida de Conway. Veja também en.wikipedia.org/wiki/Big_O_notation
Stewart

5
@ Dave: A questão não era se existem O (1 / n) funções, que obviamente existem. Em vez disso, ele foi se existem O (1 / n) algoritmos, que (com a possível excepção da função nulo) não pode existir
Casebash

6

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


6

Para quem ler esta pergunta e quiser entender do que se trata a conversa, isso pode ajudar:

|    |constant |logarithmic |linear|  N-log-N |quadratic|  cubic  |  exponential  |
|  n |  O(1)   | O(log n)   | O(n) |O(n log n)|  O(n^2) |  O(n^3) |     O(2^n)    |
|  1 |       1 |          1 |     1|         1|        1|       1 |             2 |
|  2 |       1 |          1 |     2|         2|        4|       8 |             4 |
|  4 |       1 |          2 |     4|         8|       16|      64 |            16 |
|  8 |       1 |          3 |     8|        24|       64|     512 |           256 |
| 16 |       1 |          4 |    16|        64|      256|   4,096 |         65536 |
| 32 |       1 |          5 |    32|       160|    1,024|  32,768 | 4,294,967,296 |
| 64 |       1 |          6 |    64|       384|    4,069| 262,144 |   1.8 x 10^19 |

5

Acredito que algoritmos quânticos podem fazer vários cálculos "de uma só vez" via superposição ...

Duvido que seja uma resposta útil.


Que ainda seria constante de tempo, isto é, O (1), o que significa que tem a mesma quantidade de tempo para ser executado para os dados de tamanho n como faz para dados de tamanho 1.
freespace

2
Mas e se o problema fosse uma cerveja pálida? (ah hah ha...)
Jeff Meatball Yang

7
Isso seria uma posição super para estar dentro.
Daniel Earwicker

11
Os algoritmos quânticos podem fazer vários cálculos, mas você só pode recuperar o resultado de um cálculo e não pode escolher qual resultado obter. Felizmente, você também pode fazer operações num registo quantum como um todo (por exemplo, QFT) Então você é muito mais provável de encontrar algo :)
Gracenotes

2
talvez não seja útil, mas tem a vantagem de ser verdade, o que o coloca acima de alguns dos mais altamente votou respostas B-)
Brian Postow

4

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.


2

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.


2

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.


Sim, mas o número de nós bittorrent é mais parecido com o número de processadores em um computador paralelo. O "N" nesse caso seria o tamanho do arquivo que está tentando ser baixado. Assim como você pode encontrar um elemento em uma matriz não classificada de comprimento N em tempo constante, se você tiver N computadores, poderá baixar um arquivo de Tamanho N em tempo constante, se houver N computadores tentando enviar os dados.
Kibbee

2

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.


11
Não sei se entendi. Log (N) é menor que N. Isso significa que Log (N) é um algoritmo sublinear? E existem muitos algoritmos de log (N). Um exemplo é encontrar um valor em uma árvore binária. No entanto, eles ainda são diferentes de 1 / N, uma vez que Log (N) sempre aumenta, enquanto 1 / n é uma função decrescente.
Kibbee

Olhando para a definição, o algoritmo de tempo sublinear é qualquer algoritmo cujo tempo cresce mais lento que o tamanho N. Portanto, isso inclui o algoritmo de tempo logarítmico, que é Log (N).
Hao Wooi Lim

2
Os algoritmos de tempo sublinear podem fornecer respostas exatas, por exemplo, pesquisa binária em um array ordenado em uma máquina de RAM.
A. Rex

@UMA. Rex: Hao Wooi Lim disse "Em alguns problemas".
precisa saber é o seguinte

1

Que tal isso:

void FindRandomInList(list l)
{
    while(1)
    {
        int rand = Random.next();
        if (l.contains(rand))
            return;
    }
}

À medida que o tamanho da lista aumenta, o tempo de execução esperado do programa diminui.


eu acho que você não entender o significado de O (n)
Markus Lausberg

Não com a lista embora, com matriz ou de hash onde constainsé O (1)
vava

ok, a função aleatória pode ser pensada como uma matriz lenta, então você está basicamente pesquisando cada elemento na "lista aleatória lenta" e verificando se está contido na lista de entrada. Eu acho que isso é pior que linear, não melhor.
hasen

Ele tem algum argumento se você perceber que int possui um conjunto limitado de valores. Então, quando eu contiver 2 valores <sup> 64 </sup>, será instantâneo o tempo todo. O que o torna pior do que O (1) de qualquer maneira :)
vava

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.


11
"O (1 / n) não é menor que O (1)" - se uma função f é O (1 / n), também é O (1). E big-oh se parece muito com uma relação "menor que": é reflexiva, é transitiva, e se tivermos simetria entre f e g os dois são equivalentes, onde big-theta é nossa relação de equivalência. Relações de ordem "reais" ISTR exigindo que a <= b e b <= a implicam a = b, e a netcraft ^ W wikipedia confirma isso. Então, em certo sentido, é justo dizer que de fato O (1 / n) é "menor que" O (1).
Jonas Kölker

1

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.

def get_faster(list):
    how_long = 1/len(list)
    sleep(how_long)

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.


1

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).


0

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.


4
É um tipo diferente de n no O (n) então. Com esse truque, você poderia dizer que todo algoritmo possui O (q), onde q é o número de pessoas que vivem na China, por exemplo.
Vava

2
Boyer-Moore é de um tipo semelhante (O (n / m)), mas isso não é realmente "melhor que O (1)", porque n> = m. Eu acho que o mesmo é verdade para o seu "TSP invisível".
Niki

Mesmo nesse caso, o tempo de execução do TSP é NP-Complete, você está simplesmente removendo nós do gráfico e, portanto, diminuindo efetivamente n.
257 James Ed Ed

0

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.


0

Na análise numérica, os algoritmos de aproximação devem ter complexidade assintótica sub-constante na tolerância de aproximação.

class Function
{
    public double[] ApproximateSolution(double tolerance)
    {
        // if this isn't sub-constant on the parameter, it's rather useless
    }
}

você realmente quer dizer sub-constante ou sub-linear? Por que os algoritmos de aproximação devem ser sub-constantes? E o que isso significa?
LarsH

@LarsH, o erro dos algoritmos de aproximação é proporcional ao tamanho da etapa (ou a uma potência positiva), portanto, quanto menor o tamanho da etapa, menor o erro. Mas outra maneira comum de examinar um problema de aproximação é o erro em comparação com quantas vezes um intervalo é dividido. O número de partições de um intervalo é inversamente proporcional ao tamanho da etapa; portanto, o erro é inversamente proporcional a alguma potência positiva do número de partições - à medida que você aumenta o número de partições, seu erro diminui.
Andrew Lei

@AndrewLei: Uau, uma resposta quase 7 anos depois! Agora entendo a resposta de Sam melhor do que antes. Obrigado por responder.
LarsH

0

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:

def 1_by_n(n, C = 10):   #n could be float. C could be any positive number
  if n <= 0.0:           #If input is actually 0, infinite loop.
    while True:
      sleep(1)           #or pass
    return               #This line is not needed and is unreachable
  delta = 0.0001
  itr = delta
  while delta < C/n:
    itr += delta

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)


-1

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).


Seu loop requer uma verificação que leva pelo menos tempo constante, para que o algoritmo resultante tenha pelo menos complexidade O (1).
Stefan Reich

-1

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).


-2

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)


Mesmo? Você ainda precisaria retornar um valor, então ainda não seria O (1)?
Joachim Sauer

7
não, O (0) implicaria que leva tempo zero para todas as entradas. O (1) é tempo constante.
Pete Kirkham

-2

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)


Não: a notação Big O também é usada para falar de cenários de caso médio e tempo esperado (e até melhor). O resto segue.
219 Konrad Rudolph

A notação 'O' certamente define um limite superior (em termos de complexidade algorítmica, esse seria o pior caso). Omega e Theta são usados ​​para indicar casos melhores e médios, respectivamente.
Roland Ewald

2
Roland: Isso é um equívoco; limite superior não é a mesma coisa que na pior das hipóteses, os dois são conceitos independentes. Considere o tempo de execução esperado (e médio) do hashtable-containsalgoritmo 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.
289 Konrad Rudolph

Konrad: Verdade. Ainda, Omega, Theata e O são geralmente usadas para expressar limites, e se todas as entradas possíveis são considerados, S representa o limite superior, etc
Roland Ewald

11
O fato de O (1 / n) ser um subconjunto de O (1) é trivial e segue diretamente da definição. De fato, se uma função g é O (h), então qualquer função f que é O (g) também é O (h).
1111 Tobias

-2

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


-2
inline void O0Algorithm() {}

11
Isso seria um algoritmo O (1).
Lasse V. Karlsen

2
Isso também, mas o ponto é que não é Ω (1). E por que minha resposta foi rebaixada? Se você acha que estou errado, que tal explicar?
Stewart

Pedi outro lugar se, basicamente, esta mesma resposta está correta ou não, e parece ser contestado: stackoverflow.com/questions/3209139/...
jyoungdev

Bem, está embutido, então você pode considerá-lo O (0). No entanto, todos os algoritmos O (0) são triviais (sem fazer nada), então ... não é uma resposta muito interessante.
Stefan Reich

@StefanReich É verdade que não é uma resposta muito interessante, mas é uma resposta.
Stewart

-2

Aqui está um algoritmo O (1 / n) simples. E até faz algo interessante!

function foo(list input) {
  int m;
  double output;

  m = (1/ input.size) * max_value;  
  output = 0;
  for (int i = 0; i < m; i++)
    output+= random(0,1);

  return output;
}

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.


11
Como O (1 / n) ficará abaixo da linha horizontal = 1 e, quando n atingir infinito, seu código ainda executará um determinado número de etapas, esse algoritmo é um algoritmo O (1). A notação Big-O é uma função de todas as partes diferentes do algoritmo e escolhe a maior. Como o método sempre executa algumas das instruções, quando n chega ao infinito, você fica com as mesmas instruções executando sempre e, portanto, o método é executado em tempo constante. É verdade que não demorará muito tempo, mas isso não é relevante para a notação Big-O.
Lasse V. Karlsen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.