Existe-t-il des algorithmes O (1 / n)?

335

Existe-t-il des algorithmes O (1 / n)?

Ou autre chose qui est inférieur à O (1)?

Peter Mortensen
la source
La plupart des questions supposent que vous voulez dire "Existe-t-il des algorithmes avec une complexité temporelle de O (1 / n)?" Devons-nous supposer que c'est le cas? Big-O (et Big-Theta, etc.) décrivent des fonctions, pas des algorithmes. (Je ne connais aucune équivalence entre les fonctions et les algorithmes.)
jyoungdev
4
Telle est la définition communément comprise de "l'algorithme O (X)" en informatique: un algorithme dont la complexité temporelle est O (X) (pour une expression X).
David Z
2
J'ai entendu une telle limite en cas d'algorithme de file d'attente prioritaire efficace d'E / S utilisant Buffer Tree. Dans un arbre tampon, chaque opération nécessite des E / S O (1 / B); où B est la taille du bloc. Et le nombre total d'E / S pour n opérations est O (n / B.log (base M / B) (n / B)), où la partie logarithmique est la hauteur de l'arborescence du tampon.
CODError
Il existe de nombreux algorithmes avec une probabilité d'erreur O (1 / n). Par exemple, un filtre de bloom avec des seaux O (n log n).
Thomas Ahle
Vous ne pouvez pas pondre un œuf plus rapidement en ajoutant des poulets.
Wyck

Réponses:

310

Cette question n'est pas aussi stupide que cela puisse paraître. Au moins théoriquement, quelque chose comme O (1 / n ) est tout à fait sensé lorsque nous prenons la définition mathématique de la notation Big O :

Maintenant, vous pouvez facilement remplacer g ( x ) par 1 / x … il est évident que la définition ci-dessus est toujours valable pour certains f .

Dans le but d'estimer la croissance asymptotique à l'exécution, cela est moins viable… un algorithme significatif ne peut pas aller plus vite à mesure que l'entrée augmente. Bien sûr, vous pouvez construire un algorithme arbitraire pour y parvenir, par exemple le suivant:

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

De toute évidence, cette fonction passe moins de temps à mesure que la taille d'entrée augmente… au moins jusqu'à une certaine limite, imposée par le matériel (précision des nombres, minimum de temps qui sleeppeut attendre, temps pour traiter les arguments, etc.): cette limite serait alors un borne inférieure constante donc en fait la fonction ci-dessus a toujours le temps d'exécution O (1).

Mais il existe en fait des algorithmes du monde réel où le temps d'exécution peut diminuer (au moins partiellement) lorsque la taille d'entrée augmente. Notez cependant que ces algorithmes ne présenteront pas de comportement d'exécution inférieur à O (1). Pourtant, ils sont intéressants. Par exemple, prenez l'algorithme de recherche de texte très simple de Horspool . Ici, le temps d'exécution attendu diminuera à mesure que la longueur du modèle de recherche augmentera (mais l'augmentation de la longueur de la botte de foin augmentera à nouveau le temps d'exécution).

Konrad Rudolph
la source
22
«Appliqué par le matériel» s'applique également à une machine de Turing. Dans le cas de O (1 / n), il y aura toujours une taille d'entrée pour laquelle l'algorithme n'est censé exécuter aucune opération. Et donc je pense que la complexité temporelle O (1 / n) est en effet impossible à réaliser.
Roland Ewald
28
Mehrdad, vous ne comprenez pas. La notation O est quelque chose au sujet de la limite (techniquement lim sup) comme n -> ∞. Le temps d'exécution d'un algorithme / programme est le nombre d'étapes sur une machine, et est donc discret - il y a une limite inférieure non nulle sur le temps qu'un algorithme peut prendre ("une étape"). Il est possible que jusqu'à un certain N fini, un programme prenne un certain nombre d'étapes décroissantes avec n, mais la seule façon dont un algorithme peut être O (1 / n), ou même o (1), est s'il prend suffisamment de temps à 0 pour tous. grand n - ce qui n'est pas possible.
ShreevatsaR
28
Nous ne sommes pas en désaccord que O (1 / n) fonctions (au sens mathématique) existent. De toute évidence, ils le font. Mais le calcul est intrinsèquement discret. Quelque chose qui a une limite inférieure, comme le temps d'exécution d'un programme - sur l'architecture von Neumann ou une machine de Turing purement abstraite - ne peut pas être O (1 / n). De manière équivalente, quelque chose qui est O (1 / n) ne peut pas avoir de limite inférieure. (Votre fonction "sleep" doit être invoquée, ou la variable "list" doit être examinée - ou la bande d'entrée doit être examinée sur une machine de Turing. Ainsi, le temps nécessaire changerait avec n comme certains ε + 1 / n, qui n'est pas O (1 / n))
ShreevatsaR
16
Si T (0) = ∞, il ne s'arrête pas. Il n'y a rien de tel que "T (0) = ∞, mais ça s'arrête quand même". De plus, même si vous travaillez dans R∪ {∞} et définissez T (0) = ∞, et T (n + 1) = T (n) / 2, alors T (n) = ∞ pour tout n. Je répète: si une fonction à valeurs discrètes est O (1 / n), alors pour tout n suffisamment grand, elle est 0. [Preuve: T (n) = O (1 / n) signifie qu'il existe une constante c telle que pour n> N0, T (n) <c (1 / n), ce qui signifie que pour tout n> max (N0,1 / c), T (n) <1, ce qui signifie T (n) = 0.] Aucune machine, réelle ou abstraite, ne peut prendre 0 temps: elle doit regarder l'entrée. Eh bien, outre la machine qui ne fait jamais rien, et pour laquelle T (n) = 0 pour tout n.
ShreevatsaR
43
Vous devez aimer toute réponse qui commence par "Cette question n'est pas aussi stupide que cela puisse paraître."
Télémaque le
138

Oui.

Il existe précisément un algorithme à l'exécution O (1 / n), l'algorithme "vide".

Pour qu'un algorithme soit O (1 / n), cela signifie qu'il s'exécute asymptotiquement en moins d'étapes que l'algorithme composé d'une seule instruction. S'il s'exécute en moins d'étapes qu'une étape pour tout n> n0, il ne doit précisément contenir aucune instruction pour celles n. Étant donné que la vérification «si n> n0» coûte au moins 1 instruction, elle ne doit comprendre aucune instruction pour tous les n.

Pour résumer: le seul algorithme qui est O (1 / n) est l'algorithme vide, composé d' aucune instruction.

Tobias
la source
2
Donc, si quelqu'un demandait quelle était la complexité temporelle d'un algorithme vide, vous répondriez par O (1 / n) ??? D'une certaine manière, j'en doute.
phkahler
24
C'est la seule bonne réponse dans ce fil, et (malgré mon vote positif), elle est à zéro vote. Tel est StackOverflow, où les réponses «correctes» sont votées plus haut que les réponses réellement correctes.
ShreevatsaR
5
Non, sa note 0 car elle est incorrecte. Exprimer une valeur de grand Oh par rapport à N lorsqu'elle est indépendante de N est incorrect. Deuxièmement, exécuter n'importe quel programme, même celui qui existe, prend au moins un temps constant, O (1). Même si ce n'était pas le cas, ce serait O (0), pas O (1 / n).
kenj0418
32
Toute fonction qui est O (0) est également O (1 / n), et également O (n), également O (n ^ 2), également O (2 ^ n). Soupir, personne ne comprend les définitions simples? O () est une borne supérieure.
ShreevatsaR
16
@ kenj0418 Vous avez réussi à vous tromper dans chaque phrase. "Exprimer une valeur de grand Oh par rapport à N lorsqu'elle est indépendante de N est incorrect." Une fonction constante est une fonction parfaitement gaffée. "Deuxièmement, exécuter n'importe quel programme, même celui qui existe, prend au moins un temps constant, O (1)." La définition de la complexité ne dit rien sur l'exécution effective de programmes. "ce serait O (0), pas O (1 / n)". Voir le commentaire de @ ShreevatsaR.
Alexey Romanov
25

sharptooth est correct, O (1) est la meilleure performance possible. Cependant, cela n'implique pas une solution rapide, juste une solution à temps fixe.

Une variante intéressante, et peut-être ce qui est vraiment suggéré, est de savoir quels problèmes deviennent plus faciles à mesure que la population augmente. Je peux penser à 1 réponse, quoique artificielle et ironique:

Est-ce que deux personnes dans un ensemble ont le même anniversaire? Lorsque n dépasse 365, retourne vrai. Bien que pour moins de 365, c'est O (n ln n). Peut-être pas une bonne réponse car le problème ne devient pas plus facile mais devient simplement O (1) pour n> 365.

Adrian
la source
7
366. N'oubliez pas les années bissextiles!
Nick Johnson
1
Vous avez raison. Comme les ordinateurs, je suis parfois sujet à des erreurs d'arrondi :-)
Adrian
10
+1. Il existe un certain nombre de problèmes NP-complets qui subissent une "transition de phase" lorsque n augmente, c'est-à-dire qu'ils deviennent rapidement beaucoup plus faciles ou beaucoup plus difficiles lorsque vous dépassez une certaine valeur seuil de n. Un exemple est le problème de partitionnement des nombres: étant donné un ensemble de n entiers non négatifs, partitionnez-les en deux parties de sorte que la somme de chaque partie soit égale. Cela devient considérablement plus facile à une certaine valeur seuil de n.
j_random_hacker
23

Ce n'est pas possible. La définition de Big-O n'est pas plus grande que l' inégalité:

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)

Donc, le B (n) est en fait la valeur maximale, donc si elle diminue à mesure que n augmente, l'estimation ne changera pas.

dents de scie
la source
42
Je soupçonne que cette réponse est la «bonne», mais malheureusement je n'ai pas l'intellect pour la comprendre.
freespace
12
AFAIK cette condition ne doit pas être vraie pour tout n, mais pour tout n> n_0 (c'est-à-dire uniquement lorsque la taille de l'entrée atteint un seuil spécifique).
Roland Ewald
30
Je ne vois pas comment la définition (même corrigée) contredit la question du PO. La définition s'applique aux fonctions complètement arbitraires! 1 / n est une fonction tout à fait sensée pour B, et en fait votre équation ne contredit pas cela (faites simplement le calcul). Donc non, malgré beaucoup de consensus, cette réponse est en fait fausse . Désolé.
Konrad Rudolph,
10
Faux! Je n'aime pas voter en aval, mais vous dites que c'est impossible en l'absence d'un consensus clair. Dans la pratique, vous avez raison, si vous construisez une fonction avec un runtime 1 / n (facile), elle atteindra finalement le temps minimum, ce qui en fera un algorithme O (1) une fois implémenté. Cependant, rien n'empêche l'algorithme d'être O (1 / n) sur le papier.
jheriko
3
@Jason: Oui, maintenant que vous le dites ... :) @jheriko: Une complexité temporelle de O (1 / n) ne fonctionne pas sur le papier à mon humble avis. Nous caractérisons la fonction de croissance f (taille d'entrée) = #ops pour une machine de Turing. S'il s'arrête pour une entrée de longueur n = 1 après x étapes, je choisirai alors une taille d'entrée n >> x, c'est-à-dire suffisamment grande pour que, si l'algorithme est bien en O (1 / n), aucune opération ne soit terminé. Comment une machine Turing devrait-elle même remarquer cela (il n'est pas autorisé à lire une fois sur la bande)?
Roland Ewald
16

De mon apprentissage précédent de la grande notation O, même si vous avez besoin d'une étape (comme vérifier une variable, faire une affectation), c'est O (1).

Notez que O (1) est identique à O (6), car la "constante" n'a pas d'importance. C'est pourquoi nous disons que O (n) est identique à O (3n).

Donc, si vous avez besoin d'une seule étape, c'est O (1) ... et puisque votre programme a au moins besoin d'une étape, le minimum qu'un algorithme peut utiliser est O (1). A moins que si nous ne le faisons pas, alors c'est O (0), je pense? Si nous faisons quoi que ce soit, alors c'est O (1), et c'est le minimum que cela peut faire.

(Si nous choisissons de ne pas le faire, cela peut devenir une question Zen ou Tao ... dans le domaine de la programmation, O (1) est toujours le minimum).

Ou que diriez-vous de ceci:

programmeur : patron, j'ai trouvé un moyen de le faire en temps O (1)!
patron : pas besoin de le faire, nous sommes en faillite ce matin.
programmeur : oh alors, ça devient O (0).

動靜 能量
la source
Votre blague m'a rappelé quelque chose du Tao de programmation: canonical.org/~kragen/tao-of-programming.html#book8 (8.3)
kenj0418
Un algorithme composé de zéro pas est O (0). C'est un algorithme très paresseux.
2011
8

Non, ce n'est pas possible:

Comme n tend vers l'infini en 1 / n, nous obtenons finalement 1 / (inf), qui est en fait 0.

Ainsi, la classe big-oh du problème serait O (0) avec un n massif, mais plus proche du temps constant avec un n faible. Ce n'est pas raisonnable, car la seule chose qui peut être faite plus rapidement que le temps constant est:

void nothing() {};

Et même cela est défendable!

Dès que vous exécutez une commande, vous êtes au moins dans O (1), donc non, nous ne pouvons pas avoir une classe O de grande taille (1 / n)!

Ed James
la source
7

Qu'en est-il de ne pas exécuter la fonction du tout (NOOP)? ou en utilisant une valeur fixe. Cela compte-t-il?

Joint
la source
16
C'est toujours le runtime O (1).
Konrad Rudolph
2
Bon, c'est toujours O (1). Je ne vois pas comment quelqu'un peut comprendre cela, et pourtant je prétends dans une autre réponse que quelque chose de moins que NO-OP est possible.
ShreevatsaR
4
ShreevatsaR: il n'y a absolument aucune contradiction. Vous semblez ne pas comprendre que la grande notation O n'a rien à voir avec le temps passé dans la fonction - elle décrit plutôt comment ce temps change avec la modification de l'entrée (au-dessus d'une certaine valeur). Voir autre fil de commentaire pour plus.
Konrad Rudolph
Je la comprends parfaitement bien, merci. Le point - comme je l'ai fait plusieurs fois dans l'autre thread - est que si le temps diminue avec l'entrée, au taux O (1 / n), il doit finalement diminuer en dessous du temps pris par NOOP. Cela montre qu'aucun algorithme ne peut être O (1 / n) asymptotiquement, bien que son temps d'exécution puisse certainement diminuer jusqu'à une limite.
ShreevatsaR
1
Oui ... comme je l'ai dit ailleurs, tout algorithme qui est O (1 / n) devrait également prendre zéro temps pour toutes les entrées, donc selon que vous considérez l'algorithme nul comme prenant 0 fois ou non, il y a un O (1 / n) algorithme. Donc , si vous considérez NOOP être O (1), alors il n'y a pas d' algorithmes O (1 / n).
ShreevatsaR
7

J'utilise souvent O (1 / n) pour décrire les probabilités qui diminuent au fur et à mesure que les entrées augmentent - par exemple, la probabilité qu'une bonne pièce remonte en queue sur les flips log2 (n) est O (1 / n).

Dave
la source
6
Ce n'est pas ce que le grand O est cependant. Vous ne pouvez pas simplement le redéfinir afin de répondre à la question.
Zifre
11
Ce n'est pas une redéfinition, c'est exactement la définition du grand O.
ShreevatsaR
10
Je suis un informaticien théorique de métier. Il s'agit de l'ordre asymptotique d'une fonction.
Dave
4
Big O est une propriété d'une fonction réelle arbitraire. La complexité temporelle n'est qu'une de ses applications possibles. La complexité de l'espace (la quantité de mémoire de travail utilisée par un algorithme) en est une autre. Que la question porte sur les algorithmes O (1 / n) implique que c'est l'un d'entre eux (à moins qu'il y en ait un autre qui s'applique aux algorithmes que je ne connais pas). D'autres applications incluent des ordres de croissance démographique, par exemple dans Conway's Life. Voir aussi en.wikipedia.org/wiki/Big_O_notation
Stewart
5
@Dave: La question n'était pas de savoir s'il existe des fonctions O (1 / n), qui existent évidemment. Il s'agissait plutôt de savoir s'il existe des algorithmes O (1 / n) qui (à l'exception possible de la fonction nulle) ne peuvent pas exister
Casebash
6

O (1) signifie simplement "temps constant".

Lorsque vous ajoutez une sortie anticipée à une boucle [1], vous (en notation big-O) transformez un algorithme O (1) en O (n), mais en le rendant plus rapide.

L'astuce est en général l'algorithme à temps constant est le meilleur, et linéaire est meilleur qu'exponentiel, mais pour de petites quantités de n, l'algorithme exponentiel peut en fait être plus rapide.

1: en supposant une longueur de liste statique pour cet exemple

LapTop006
la source
6

Pour tous ceux qui lisent cette question et souhaitent comprendre de quoi parle la conversation, cela peut aider:

|    |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
la source
5

Je crois que les algorithmes quantiques peuvent effectuer plusieurs calculs "à la fois" via la superposition ...

Je doute que ce soit une réponse utile.

Jeff Meatball Yang
la source
Ce serait toujours un temps constant, c'est-à-dire O (1), ce qui signifie qu'il faut autant de temps pour s'exécuter pour les données de taille n que pour les données de taille 1.
espace libre
2
Mais que faire si le problème était une bière blonde? (ah. hah. ha.)
Jeff Meatball Yang
7
Ce serait une super position.
Daniel Earwicker
1
Les algorithmes quantiques peuvent effectuer plusieurs calculs, mais vous ne pouvez récupérer que le résultat d'un calcul, et vous ne pouvez pas choisir le résultat à obtenir. Heureusement, vous pouvez également effectuer des opérations sur un registre quantique dans son ensemble (par exemple, QFT), vous êtes donc beaucoup plus susceptible de trouver quelque chose :)
Gracenotes
2
ce n'est peut-être pas utile, mais cela a l'avantage d'être vrai, ce qui le place au-dessus de certaines des réponses les plus votées B-)
Brian Postow
4

beaucoup de gens ont eu la bonne réponse (Non) Voici une autre façon de le prouver: Pour avoir une fonction, vous devez l'appeler et vous devez renvoyer une réponse. Cela prend un certain temps constant. MÊME SI le reste du traitement a pris moins de temps pour des entrées plus importantes, l'impression de la réponse (qui peut être supposée être un seul bit) prend au moins un temps constant.

Brian Postow
la source
2

Si la solution existe, elle peut être préparée et accessible en temps constant = immédiatement. Par exemple, en utilisant une structure de données LIFO si vous savez que la requête de tri est pour l'ordre inverse. Ensuite, les données sont déjà triées, étant donné que le modèle approprié (LIFO) a été choisi.

Larsson
la source
2

Quels problèmes deviennent plus faciles avec l'augmentation de la population? Une réponse est une chose comme bittorrent où la vitesse de téléchargement est une fonction inverse du nombre de nœuds. Contrairement à une voiture, qui ralentit plus vous la chargez, un réseau de partage de fichiers comme bittorrent accélère plus de nœuds connectés.

Niklas R.
la source
Oui, mais le nombre de nœuds bittorrent ressemble plus au nombre de processeurs dans un ordinateur parallèle. Le "N" dans ce cas serait la taille du fichier essayant d'être téléchargé. Tout comme vous pourriez trouver un élément dans un tableau non trié de longueur N en temps constant si vous aviez N ordinateurs, vous pouvez télécharger un fichier de taille N en temps constant si vous aviez N ordinateurs essayant de vous envoyer les données.
Kibbee
2

Vous ne pouvez pas descendre en dessous de O (1), cependant O (k) où k est inférieur à N est possible. Nous les avons appelés algorithmes de temps sublinéaires . Dans certains problèmes, l'algorithme de temps sublinéaire ne peut donner que des solutions approximatives à un problème particulier. Cependant, parfois, une solution approximative est très bien, probablement parce que l'ensemble de données est trop volumineux, ou que c'est beaucoup trop coûteux en calcul pour tout calculer.

Hao Wooi Lim
la source
1
Pas sûr que je comprenne. Log (N) est inférieur à N. Est-ce à dire que Log (N) est un algorithme sublinéaire? Et de nombreux algorithmes Log (N) existent. Un tel exemple est de trouver une valeur dans un arbre binaire. Cependant, ceux-ci sont toujours différents de 1 / N, car Log (N) est toujours en augmentation, tandis que 1 / n est une fonction décroissante.
Kibbee
En regardant la définition, l'algorithme de temps sublinéaire est tout algorithme dont le temps se développe plus lentement que la taille N. Cela inclut donc l'algorithme de temps logarithmique, qui est Log (N).
Hao Wooi Lim
2
Euh, les algorithmes de temps sublinéaires peuvent donner des réponses exactes, par exemple la recherche binaire dans un tableau ordonné sur une machine RAM.
A. Rex,
@UNE. Rex: Hao Wooi Lim a dit "Dans certains problèmes".
LarsH
1

Et ça:

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

à mesure que la taille de la liste augmente, le temps d'exécution attendu du programme diminue.

Shalmanais
la source
je pense que vous ne comprenez pas le sens de O (n)
Markus Lausberg
Pas avec la liste cependant, avec un tableau ou un hachage où constainsest O (1)
vava
ok, la fonction aléatoire peut être considérée comme un tableau paresseux, donc vous recherchez essentiellement chaque élément dans la "liste aléatoire paresseuse" et vérifiez s'il est contenu dans la liste d'entrée. Je pense que c'est pire que linéaire, pas mieux.
hasen
Il a un certain point si vous remarquez que int a un ensemble limité de valeurs. Donc, quand l contiendrait 2 <sup> 64 </sup> valeurs, ça va être instantané jusqu'au bout. Ce qui le rend pire que O (1) de toute façon :)
vava
1

O (1 / n) n'est pas inférieur à O (1), cela signifie essentiellement que plus vous avez de données, plus l'algorithme va vite. Supposons que vous obtenez un tableau et remplissez-le toujours jusqu'à 10 100 éléments s'il en contient moins et ne faites rien s'il y en a plus. Celui-ci n'est pas O (1 / n) bien sûr mais quelque chose comme O (-n) :) Dommage que la notation O-big ne permette pas les valeurs négatives.

vava
la source
1
"O (1 / n) n'est pas inférieur à O (1)" - si une fonction f est O (1 / n), c'est aussi O (1). Et big-oh ressemble beaucoup à une relation "moindre que": c'est réflexif, c'est transitif, et si nous avons une symétrie entre f et g les deux sont équivalents, où big-theta est notre relation d'équivalence. Les relations d'ordre "réelles" ISTR nécessitant a <= b et b <= a pour impliquer a = b, cependant, et netcraft ^ W wikipedia le confirme. Donc, dans un sens, il est juste de dire qu'en effet O (1 / n) est "inférieur à" O (1).
Jonas Kölker
1

Comme cela a été souligné, à l'exception de l'exception possible de la fonction nulle, il ne peut y avoir de O(1/n)fonctions, car le temps nécessaire devra approcher de 0.

Bien sûr, il existe des algorithmes, comme celui défini par Konrad, qui semblent être inférieurs O(1)à au moins un certain sens.

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

Si vous souhaitez étudier ces algorithmes, vous devez soit définir votre propre mesure asymptotique, soit votre propre notion du temps. Par exemple, dans l'algorithme ci-dessus, je pourrais autoriser l'utilisation d'un certain nombre d'opérations "gratuites" un nombre de fois défini. Dans l'algorithme ci-dessus, si je définis t 'en excluant le temps pour tout sauf le sommeil, alors t' = 1 / n, qui est O (1 / n). Il y a probablement de meilleurs exemples, car le comportement asymptotique est trivial. En fait, je suis sûr que quelqu'un peut trouver des sens qui donnent des résultats non triviaux.

Casebash
la source
1

La plupart des autres réponses interprètent big-O comme étant exclusivement sur le temps d'exécution d'un algorithme. Mais comme la question ne le mentionnait pas, j'ai pensé qu'il valait la peine de mentionner l'autre application du big-O en analyse numérique, qui concerne l'erreur.

De nombreux algorithmes peuvent être O (h ^ p) ou O (n ^ {- p}) selon que vous parlez de taille de pas (h) ou de nombre de divisions (n). Par exemple, dans la méthode d'Euler , vous recherchez une estimation de y (h) étant donné que vous connaissez y (0) et dy / dx (la dérivée de y). Votre estimation de y (h) est d'autant plus précise que h se rapproche de 0. Ainsi, pour trouver y (x) pour des x arbitraires, on prend l'intervalle de 0 à x, on le divise jusqu'à n morceaux et on exécute la méthode d'Euler à chaque point, pour passer de y (0) à y (x / n) à y (2x / n), etc.

La méthode d'Euler est donc un algorithme O (h) ou O (1 / n), où h est généralement interprété comme une taille de pas et n est interprété comme le nombre de fois que vous divisez un intervalle.

Vous pouvez également avoir O (1 / h) dans de vraies applications d'analyse numérique, en raison d' erreurs d'arrondi à virgule flottante . Plus votre intervalle est petit, plus l'annulation se produit pour la mise en œuvre de certains algorithmes, plus la perte de chiffres significatifs, et donc plus d'erreurs, qui se propagent à travers l'algorithme.

Pour la méthode d'Euler, si vous utilisez des virgules flottantes, utilisez un pas et une annulation suffisamment petits et vous ajoutez un petit nombre à un grand nombre, en laissant le grand nombre inchangé. Pour les algorithmes qui calculent la dérivée en soustrayant l'un de l'autre deux nombres d'une fonction évaluée à deux positions très proches, approximant y '(x) avec (y (x + h) - y (x) / h), dans les fonctions lisses y (x + h) se rapproche de y (x), ce qui entraîne une annulation importante et une estimation du dérivé avec moins de chiffres significatifs. Cela se propagera à son tour à l'algorithme pour lequel vous avez besoin de la dérivée (par exemple, un problème de valeur limite).

Andrew Lei
la source
0

OK, j'y ai réfléchi un peu, et peut-être existe-t-il un algorithme qui pourrait suivre cette forme générale:

Vous devez calculer le problème du vendeur itinérant pour un graphique de 1000 nœuds, mais vous obtenez également une liste de nœuds que vous ne pouvez pas visiter. À mesure que la liste des nœuds invisibles s'allonge, le problème devient plus facile à résoudre.

Shalmanais
la source
4
C'est différent de n dans l'O (n) alors. Avec cette astuce, vous pourriez dire que chaque algorithme a O (q) où q est le nombre de personnes vivant en Chine par exemple.
vava
2
Boyer-Moore est du même type (O (n / m)), mais ce n'est pas vraiment "mieux que O (1)", car n> = m. Je pense que la même chose est vraie pour votre "TSP non visible".
Niki
Même dans ce cas, le temps d'exécution du TSP est NP-Complete, vous supprimez simplement les nœuds du graphique, et donc diminuez efficacement n.
Ed James
0

Je vois un algorithme qui est O (1 / n) certes à une limite supérieure:

Vous avez une grande série d'entrées qui changent en raison de quelque chose d'extérieur à la routine (peut-être qu'elles reflètent le matériel ou cela pourrait même être un autre cœur du processeur qui le fait.) Et vous devez sélectionner une aléatoire mais valide.

Maintenant, si cela ne changeait pas, il vous suffirait de faire une liste d'articles, d'en choisir un au hasard et d'obtenir O (1) fois. Cependant, la nature dynamique des données empêche de faire une liste, vous devez simplement sonder au hasard et tester la validité de la sonde. (Et notez qu'intrinsèquement, il n'y a aucune garantie que la réponse est toujours valide lorsqu'elle est retournée. Cela pourrait encore avoir des utilités - disons, l'IA d'une unité dans un jeu. Elle pourrait tirer sur une cible qui est tombée hors de vue alors qu'elle était tirant sur la détente.)

Cela a une performance de l'infini dans le pire des cas, mais une performance de cas moyenne qui diminue à mesure que l'espace de données se remplit.

Loren Pechtel
la source
0

En analyse numérique, les algorithmes d'approximation devraient avoir une complexité asymptotique sous-constante dans la tolérance d'approximation.

class Function
{
    public double[] ApproximateSolution(double tolerance)
    {
        // if this isn't sub-constant on the parameter, it's rather useless
    }
}
Sam Harwell
la source
voulez-vous vraiment dire sous-constante ou sublinéaire? Pourquoi les algorithmes d'approximation devraient-ils être sous-constants? Et qu'est-ce que cela signifie même ??
LarsH
@LarsH, l'erreur des algorithmes d'approximation est proportionnelle à la taille du pas (ou à une puissance positive de celui-ci), donc plus votre taille de pas est petite, plus l'erreur est petite. Mais une autre façon courante d'examiner un problème d'approximation est l'erreur par rapport au nombre de fois qu'un intervalle est divisé. Le nombre de partitions d'un intervalle est inversement proportionnel à la taille de l'étape, donc l'erreur est inversement proportionnelle à une certaine puissance positive du nombre de partitions - lorsque vous augmentez le nombre de partitions, votre erreur diminue.
Andrew Lei
@AndrewLei: Wow, une réponse presque 7 ans plus tard! Je comprends la réponse de Sam maintenant mieux que je ne le faisais alors. Merci d'avoir répondu.
LarsH
0

Je suppose que moins de O (1) n'est pas possible. Tout temps pris par algo est appelé O (1). Mais pour O (1 / n) que diriez-vous de la fonction ci-dessous. (Je sais qu'il existe de nombreuses variantes déjà présentées dans cette solution, mais je suppose qu'elles ont toutes quelques défauts (pas majeurs, elles expliquent bien le concept). En voici une, juste pour les besoins de l'argument:

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

Ainsi, à mesure que n augmente, la fonction prendra de moins en moins de temps. De plus, il est garanti que si l'entrée est réellement 0, la fonction prendra une éternité pour revenir.

On pourrait dire qu'il sera limité par la précision de la machine. ainsi sinc eit a une borne supérieure c'est O (1). Mais nous pouvons également contourner cela, en prenant les entrées de n et C dans la chaîne. Et l'addition et la comparaison se font sur chaîne. L'idée est que, avec cela, nous pouvons réduire n arbitrairement petit. Ainsi, la limite supérieure de la fonction n'est pas bornée, même lorsque nous ignorons n = 0.

Je crois également que nous ne pouvons pas simplement dire que le temps d'exécution est O (1 / n). Mais nous devrions dire quelque chose comme O (1 + 1 / n)

user1953366
la source
-1

Il peut être possible de construire un algorithme qui est O (1 / n). Un exemple serait une boucle qui itère un multiple de f (n) -n fois où f (n) est une fonction dont la valeur est garantie supérieure à n et la limite de f (n) -n lorsque n approche de l'infini est zéro. Le calcul de f (n) devrait également être constant pour tout n. Je ne sais pas à quoi ressemblerait f (n) ni quelle application aurait un tel algorithme, à mon avis cependant une telle fonction pourrait exister mais l'algorithme résultant n'aurait d'autre but que de prouver la possibilité d'un algorithme avec O (1 / n).

Greg
la source
Votre boucle nécessite une vérification qui prend au moins un temps constant, donc l'algorithme résultant a au moins la complexité O (1).
Stefan Reich
-1

Je ne connais pas les algorithmes mais des complexités inférieures à O (1) apparaissent dans les algorithmes randomisés. En fait, o (1) (petit o) est inférieur à O (1). Ce type de complexité apparaît généralement dans les algorithmes randomisés. Par exemple, comme vous l'avez dit, lorsque la probabilité d'un événement est d'ordre 1 / n, ils la désignent par o (1). Ou quand ils veulent dire que quelque chose se produit avec une probabilité élevée (par exemple 1 - 1 / n), ils le notent avec 1 - o (1).

A. Mashreghi
la source
-2

Si la réponse est la même quelles que soient les données d'entrée, vous disposez d'un algorithme O (0).

ou en d'autres termes - la réponse est connue avant la soumission des données d'entrée - la fonction pourrait être optimisée - donc O (0)

pro
la source
Vraiment? Vous auriez toujours besoin de renvoyer une valeur, alors ne serait-ce pas encore O (1)?
Joachim Sauer,
7
non, O (0) impliquerait qu'il ne faut aucun temps pour toutes les entrées. O (1) est un temps constant.
Pete Kirkham,
-2

La notation Big-O représente le pire scénario pour un algorithme qui n'est pas la même chose que son temps d'exécution typique. Il est simple de prouver qu'un algorithme O (1 / n) est un algorithme O (1). Par définition,
O (1 / n) -> T (n) <= 1 / n, pour tout n> = C> 0
O (1 / n) -> T (n) <= 1 / C, puisque 1 / n <= 1 / C pour tout n> = C
O (1 / n) -> O (1), car la notation Big-O ignore les constantes (c'est-à-dire que la valeur de C n'a pas d'importance)

Lawrence Barsanti
la source
Non: la notation Big O est également utilisée pour parler de scénarios dans le cas moyen et dans le temps prévu (et même dans le meilleur des cas). Le reste suit.
Konrad Rudolph
La notation «O» définit certainement une borne supérieure (en termes de complexité algorithmique, ce serait le pire des cas). Omega et Theta sont utilisés pour désigner respectivement le meilleur et le cas moyen.
Roland Ewald
2
Roland: C'est une idée fausse; la limite supérieure n'est pas la même chose que dans le pire des cas, les deux sont des concepts indépendants. Considérez le temps d'exécution attendu (et moyen) de l' hashtable-containsalgorithme qui peut être noté O (1) - et le pire des cas peut être donné très précisément comme Theta (n)! Omega et Theta peuvent simplement être utilisés pour désigner d'autres limites mais pour le dire encore : ils n'ont rien à voir avec la moyenne ou le meilleur des cas.
Konrad Rudolph
Konrad: C'est vrai. Pourtant, Omega, Theata et O sont généralement utilisés pour exprimer des limites, et si toutes les entrées possibles sont prises en compte, O représente la limite supérieure, etc.
Roland Ewald
1
Le fait que O (1 / n) soit un sous-ensemble de O (1) est trivial et découle directement de la définition. En fait, si une fonction g est O (h), alors toute fonction f qui est O (g) est également O (h).
Tobias
-2

Rien n'est plus petit que O (1) La notation Big-O implique le plus grand ordre de complexité pour un algorithme

Si un algorithme a un temps d'exécution de n ^ 3 + n ^ 2 + n + 5, alors il est O (n ^ 3) Les puissances inférieures n'ont pas d'importance ici car n -> Inf, n ^ 2 ne sera pas pertinent par rapport à n ^ 3

De même que n -> Inf, O (1 / n) ne sera pas pertinent par rapport à O (1) donc 3 + O (1 / n) sera le même que O (1) faisant ainsi de O (1) le plus petit calcul possible complexité

user112831
la source
-2
inline void O0Algorithm() {}
sth
la source
1
Ce serait un algorithme O (1).
Lasse V. Karlsen,
2
Cela aussi, mais le fait est que ce n'est pas Ω (1). Et pourquoi ma réponse a-t-elle été minimisée? Si vous pensez que je me trompe, que diriez-vous d'expliquer?
Stewart
J'ai demandé ailleurs si, fondamentalement, cette réponse même est correcte ou non, et elle semble être contestée: stackoverflow.com/questions/3209139/…
jyoungdev
Eh bien, c'est en ligne, vous pouvez donc le considérer O (0). Cependant, tous les algorithmes O (0) sont triviaux (ne rien faire), donc ... pas une réponse très intéressante.
Stefan Reich
@StefanReich C'est vrai, ce n'est pas une réponse très intéressante, mais c'est une réponse.
Stewart
-2

Voici un algorithme simple O (1 / n). Et ça fait même quelque chose d'intéressant!

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) est possible car il décrit comment la sortie d'une fonction change en fonction de la taille croissante de l'entrée. Si nous utilisons la fonction 1 / n pour décrire le nombre d'instructions qu'une fonction exécute, il n'est pas nécessaire que la fonction prenne zéro instruction pour n'importe quelle taille d'entrée. C'est plutôt que pour chaque taille d'entrée, n au-dessus d'un certain seuil, le nombre d'instructions requises est limité au-dessus par une constante positive multipliée par 1 / n. Comme il n'y a pas de nombre réel pour lequel 1 / n est 0 et la constante est positive, il n'y a aucune raison pour que la fonction soit contrainte de prendre 0 ou moins d'instructions.

ejspencer
la source
1
Puisque O (1 / n) tombera en dessous de la ligne horizontale = 1, et lorsque n atteindra l'infini, votre code exécutera toujours un nombre donné d'étapes, cet algorithme est un algorithme O (1). La notation Big-O est une fonction de toutes les différentes parties de l'algorithme, et elle sélectionne la plus grande. Étant donné que la méthode exécutera toujours certaines des instructions, lorsque n atteint l'infini, vous vous retrouvez avec ces mêmes instructions qui s'exécutent à chaque fois, et donc la méthode s'exécutera alors en temps constant. Certes, cela ne prendra pas beaucoup de temps, mais ce n'est pas pertinent pour la notation Big-O.
Lasse V. Karlsen