Existem algoritmos O (1 / n)?

335

Existem algoritmos O (1 / n)?

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

Peter Mortensen
fonte
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).

Konrad Rudolph
fonte
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.

Tobias
fonte
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.

Adrian
fonte
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.

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

動靜 能量
fonte
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)!

Ed James
fonte
7

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

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

Dave
fonte
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

LapTop006
fonte
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 |
Craig O'Connor
fonte
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.

Jeff Meatball Yang
fonte
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.

Brian Postow
fonte
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.

Larsson
fonte
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.

Niklas R.
fonte
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.

Hao Wooi Lim
fonte
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.

Shalmanese
fonte
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.

vava
fonte
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.

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

Andrew Lei
fonte
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.

Shalmanese
fonte
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.

Loren Pechtel
fonte
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
    }
}
Sam Harwell
fonte
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)

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

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

A. Mashreghi
fonte
-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)

pro
fonte
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)

Lawrence Barsanti
fonte
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

user112831
fonte
-2
inline void O0Algorithm() {}
sth
fonte
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.

ejspencer
fonte
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