J'ai vu que dans la plupart des cas, la complexité temporelle est liée à la complexité spatiale et inversement. Par exemple dans une traversée de tableau:
for i=1 to length(v)
print (v[i])
endfor
Ici, il est facile de voir que la complexité de l’algorithme en termes de temps est O (n), mais il me semble que la complexité de l’espace est aussi n (également représenté par O (n)?).
Ma question: est-il possible qu'un algorithme ait une complexité temporelle différente de celle d'un espace?
Les complexités temps et espace ne sont pas liées les unes aux autres. Ils sont utilisés pour décrire l'espace/le temps que votre algorithme prend en fonction de l'entrée.
Par exemple, lorsque l'algorithme a la complexité space de:
O(1)
- constante - l'algorithme utilise une quantité d'espace fixe (petite) qui ne dépend pas de l'entrée. Pour chaque taille de l'entrée, l'algorithme prendra la même quantité d'espace (constant). C’est le cas dans votre exemple car l’entrée n’est pas prise en compte et ce qui compte, c’est le temps/espace de la commande print
.O(n)
, O(n^2)
, O(log(n))
... - indiquent que vous créez des objets supplémentaires en fonction de la longueur de votre entrée. Par exemple, créer une copie de chaque objet de v
et le stocker dans un tableau, puis l’imprimer après cela prend O(n)
espace lorsque vous créez des objets supplémentaires n
.En revanche, la complexité time décrit le temps que votre algorithme consomme en fonction de la longueur de l'entrée. Encore:
O(1)
- quelle que soit la taille de l'entrée, elle prend toujours un temps constant - par exemple, une seule instruction. Comme
function(list l) {
print("i got a list");
}
O(n)
, O(n^2)
, O(log(n))
- là encore, cela dépend de la longueur de l'entrée. Par exemple
function(list l) {
for (node in l) {
print(node);
}
}
Notez que les deux derniers exemples prennent O(1)
espace car vous ne créez rien. Comparez-les à
function(list l) {
list c;
for (node in l) {
c.add(node);
}
}
qui prend O(n)
espace parce que vous créez une nouvelle liste dont la taille dépend de la taille de l’entrée de manière linéaire.
Votre exemple montre que la complexité temporelle et spatiale peut être différente. Il faut v.length * print.time
pour imprimer tous les éléments. Mais l'espace est toujours le même - O(1)
car vous ne créez pas d'objets supplémentaires. Donc, oui, il est possible qu'un algorithme ait une complexité temporelle et spatiale différente, car ils ne sont pas dépendants les uns des autres.
La complexité temporelle et spatiale est un aspect différent du calcul de l'efficacité d'un algorithme.
La complexité temporelle consiste à déterminer comment calculer le temps de calcul de un algorithme change avec le changement de taille de l'entrée.
D'autre part, complexité de l'espace s'occupe de déterminer combien (extra) l'espace serait requis par l'algorithme avec changement dans le taille d'entrée.
Pour calculer la complexité temporelle de l'algorithme, le meilleur moyen consiste à vérifier si nous augmentons la taille de l'entrée. Le nombre de comparaisons (ou d'étapes de calcul) augmentera-t-il également, et pour calculer la complexité de l'espace, le mieux est de visualiser des besoins en mémoire supplémentaires de l'algorithme change également avec le changement de la taille de l'entrée.
Un bon exemple pourrait être de Sorte de bulle .
Disons que vous avez essayé de trier un tableau de 5 éléments. Lors du premier passage, vous comparerez le 1er élément avec les 4 suivants. Dans le second passage, vous comparerez le 2ème élément avec les 3 suivants et vous poursuivrez cette procédure jusqu'à épuisement de la liste.
Maintenant, qu'arrivera-t-il si vous essayez de trier 10 éléments. Dans ce cas, vous commencerez par comparer le 1er élément avec les 9 prochains éléments, puis le 2e avec les 8 suivants et ainsi de suite. En d'autres termes, si vous avez un tableau de N éléments, vous commencerez par comparer le 1er élément avec N-1 éléments, puis le 2ème élément avec N-2 éléments, etc. Cela se traduit par O(N^2)
complexité temporelle.
Mais qu'en est-il de la taille. Lorsque vous avez trié un tableau de 5 éléments ou d’éléments sur 10, avez-vous utilisé un tampon supplémentaire ou de l’espace mémoire? Vous pourriez dire Oui, j’ai utilisé une variable temporaire pour effectuer l’échange. Mais le nombre de variables a-t-il changé lorsque vous avez augmenté la taille d'un tableau de 5 à 10. Non, quelle que soit la taille de l'entrée, vous utiliserez toujours une seule variable pour effectuer l'échange. Cela signifie que la taille de l’entrée n’a rien à voir avec l’espace supplémentaire dont vous aurez besoin, ce qui entraîne un O(1)
ou une complexité constante de l’espace.
Maintenant, comme exercice pour vous, recherchez la complexité temporelle et spatiale de fusion
Tout d'abord, la complexité spatiale de cette boucle est O(1)
(l'entrée n'est généralement pas incluse dans le calcul de la quantité de mémoire requise par un algorithme).
La question que je me pose est la suivante: est-il possible qu’un algorithme ait une complexité temporelle différente de la complexité spatiale?
Oui, ça l'est. En général, la complexité temporelle et spatiale d'un algorithme n'est pas liée.
Parfois, l’un peut être augmenté aux dépens de l’autre. Ceci s'appelle compromis espace-temps .
Oui, c'est certainement possible. Par exemple, le tri de n
nombres réels nécessite O(n)
espace, mais O(n log n)
temps. Il est vrai que la complexité de l’espace est toujours une complexité de lowbound on, car le temps d’initialisation de l’espace est inclus dans le temps d’exécution.
Il existe une relation bien connue entre la complexité du temps et de l'espace.
Tout d’abord, le temps est une contrainte évidente à la consommation d’espace: dans le temps t.__, vous ne pouvez pas atteindre plus de O(t) cellules de mémoire. Ceci est généralement exprimépar l'inclusion
DTime(f) ⊆ DSpace(f)
où DTime (f) et DSpace (f) sont l'ensemble des langages reconnaissables par une machine de Turing déterministe dans le temps .__ (respectivement, l'espace) O (f). Autrement dit, si un problème peut être résolu dans le temps O (f), il peut également être résolu dans l'espace O (f).
Le fait que l’espace soit lié au temps est moins évident. Supposons Que, sur une entrée de taille n, vous disposiez de f(n) cellules mémoire, Comprenant des registres, des caches et tout le reste. Après avoir écrit ces cellulesDans tous possibilités manières vous pourrez éventuellement arrêter votre calcul, Sinon, vous rentreriez dans une configuration que vous avez déjà passée, en commençant par boucler. Maintenant, sur un alphabet binaire, les cellules F (n) peuvent être écrites de 2 ^ f (n) manières différentes, ce qui donne à notre La limite supérieure du temps: soit le calcul s’arrête dans cette limite, ou vous pouvez forcer la résiliation, puisque le calcul ne s'arrêtera jamais.
Ceci est généralement exprimé dans l'inclusion
DSpace(f) ⊆ Dtime(2^(cf))
pour une constante c. La raison de la constante c est que, si L est dans DSpace (f), vous savez seulement que .__ sera reconnu dans l’espace O (f), alors que dans le raisonnement précédent, f était une borne réelle.
Les relations ci-dessus sont résumées par des versions plus fortes, impliquant Des modèles de calcul non déterministes, c’est ainsi qu’elles sont fréquemment énoncées dans les manuels (voir par exemple le théorème 7.4 dans Computational Complexity de Papadimitriou).
La manière dont la quantité d'espace de stockage requise par un algorithme varie en fonction de la taille du problème à résoudre. La complexité de l’espace est normalement exprimée en ordre de grandeur, par ex. O (N ^ 2) signifie que si la taille du problème (N) double, quatre fois plus de mémoire de travail sera nécessaire.