x=0; for(int i=1 ; i<=n ; i++){ for(int j=1 ; j<=n ; j++){ x++; n--; } } By testing the code, the nested FOR loop recurs ân/2â times per steps of the first For loop.But I don't know how to formulate these rules with sigmas. I would really appreciate if anyone can help me with this.
3 Réponses :
Vous pouvez exprimer T (n) comme T (n-2) +1, c'est-à-dire T (n) = T (n-2) +1 Ou sa complexité temporelle attendue est O (n / 2) => O (n).
Edit: L'expression T (n-2) +1 est évaluée comme vous pouvez voir si vous augmentez n-2 de 2 signifie que lorsque n-2 est devenu n, le nombre de fois que la boucle sera exécutée est le 1 + nombre de boucle temporelle exécuté pour n-2. 1 est dû au fait que vous incrémentez j et décrémentez n simultanément. c'est exactement la même chose que d'incrémenter j de 2.
Comment avez-vous obtenu T(n-2)+1
?
Je ne pense pas que ce serait la bonne réponse car nous ne décrémentons pas i et n simultanément. Chaque pas de la boucle externe divise n par 2.
Dans la boucle interne, étant donné que n décrémente en même temps que j incrémente, n va être inférieur à j au milieu de la différence entre les deux valeurs initiales, soit (n-1)/2
. C'est pourquoi vos tests montrent que la boucle interne s'exécute « ⌈n/2⌉
fois par itération de la boucle externe.
Alors la boucle externe va s'arrêter lorsque pour le i qui satisfait cette égalité n/2^i = i-1
. Cela affecte la condition d'arrêt de la boucle externe.
n (1/2 + 1/4 + ... + 1/(2^i))
=
n/2 + n/4 + T(n/4)
=
n/2 + T(n/2)
=
T(n)
Cette série converge vers n
sorte que l'algorithme est O(n)
.
Calculons la valeur exacte de x
.
TL; DR: x(N) = N-[N/2^i+1]
, où i
est le nombre le plus bas, satisfaisant la condition: (i+1) 2^i > N
Comme Mariano Demarchi l'a dit, T(N)=O(N)
.
Nous allons d'abord vérifier comment les variables changent après chaque boucle interne. Soit (n, i, x)
valeurs entre 2 et 3 lignes de code (avant la boucle interne):
j
et diminue n
, donc la distance entre eux diminue de deux. La distance de départ est n-1
, et finale, après la boucle, est 0
(si n
est impair) ou -1
(si n
est pair). Ainsi si n=2k
, la réponse est k
, sinon k+1
. Ainsi, la boucle interne fait [(n+1)/2] = d
itérations.x
augmentera de d
, n
devient nd
et i
devient i+1
.(n, i, x) -> (nd, i+1, x+d)
ou égal ([n/2], i+1, x + [(n+1)/2])
Concentrez-vous maintenant sur les valeurs de n
et i
variables dans la grande boucle:
(n, i) -> ([n/2], i+1)
[N/2^i] < i+1
, qui est égal à (i+1)*2^i > N
Bien sûr, nous avons besoin d'un i
minimal, satisfaisant la condition. Donc, i
est le premier nombre satisfaisant la condition et nous NE SOMMES PAS davantage:
// finding i unsigned long long i = 0; while ((i + 1) * (1ll << i) < n) ++i; // finding x x = n - (n >> (i + 1));
Par la magie de la théorie des nombres (non liée à cette question) cette série est égale à N (1-1/2^i+1)
. En particulier, si N
est une puissance de 2 moins 1, nous pouvons le voir facilement.
Donc, ce code renvoie exactement la même valeur en temps O(log(N))
.
x = [(N+1)/2] + [([N/2]+1)/2] + [([N/2^2]+1)/2] + ... + [([N/2^i-1]+1)/2]
salut! Cette question peut être mieux adaptée pour CS StackExchange .
Pourquoi la boucle for imbriquée se répète ⌈n / 2⌉ fois par pas de la première boucle for si elles s'exécutent toutes les deux jusqu'à ce qu'elles atteignent n?
@Eloy Pérez Torres - Parce que la variable n décrémente à chaque étape de la première boucle.