K-dispersiya#11317

K-dispersiya (Həll təhlili)

\sum_{i=1}^n (a_i - \bar{a})^2 = \sum_{i=1}^n \left(a_i - \frac{\sum_{i=1}^n a_i}{n} \right)^2 = \sum_{i=1}^n \left(a^2_i - \frac{2}{n} a_i \sum_{i=1}^n a_i + \frac{\left(\sum_{i=1}^n a_i \right)^2}{n^2} \right) = \\ \sum_{i=1}^n a^2_i - \frac{2}{n} \sum_{i=1}^n a_i \sum_{i=1}^n a_i + \frac{\left(\sum_{i=1}^n a_i \right)^2}{n} = \\ \sum_{i=1}^n a^2_i - \frac{2}{n} \left(\sum_{i=1}^n a_i \right)^2 + \frac{1}{n} \left(\sum_{i=1}^n a_i \right)^2 = \sum_{i=1}^n a^2_i - \frac{1}{n} \left(\sum_{i=1}^n a_i \right)^2

İndi dispersiya düsturunu aşağıdakı şəklə gətirə bilərik:

\sqrt{\sum_{i=1}^n (a_i - \bar{a})^2 \over n - 1} = \sqrt{\frac{\sum_{i=1}^n a^2_i - \frac{1}{n} \left(\sum_{i=1}^n a_i \right)^2}{n - 1}}

Əgər ardıcıllıq üçün \{a_i, a_{i+1}, ..., a_{i+k-1}\} onun elementlərinin cəmini (a_i + a_{i+1} + ... + a_{i+k-1}) və onların kvadratları cəmini (a^2_i + a^2_{i+1} + ... + a^2_{i+k-1}) hesablamaq lazımdırsa, o zaman verilən intervallarda axtarılan dispersiyanı sabit zaman içində tapmaq mümkündür.

Misal

Dispersiya üçün kəsrin surətini n = 3 üçün dəqiqləşdirək:

\left(a_1 - \frac{a_1 + a_2 + a_3}{3}\right)^2 + \left(a_2 - \frac{a_1 + a_2 + a_3}{3}\right)^2 + \left(a_3 - \frac{a_1 + a_2 + a_3}{3}\right)^2 = \\ a_1^2 + a_2^2 + a_3^2 - 2a_1 \cdot \frac{a_1 + a_2 + a_3}{3} - 2a_2 \cdot \frac{a_1 + a_2 + a_3}{3} - 2a_3 \cdot \frac{a_1 + a_2 + a_3}{3} + \\ \left(\frac{a_1 + a_2 + a_3}{3}\right)^2 + \left(\frac{a_1 + a_2 + a_3}{3}\right)^2 + \left(\frac{a_1 + a_2 + a_3}{3}\right)^2 = \\ a_1^2 + a_2^2 + a_3^2 - \frac{2}{3}(a_1 + a_2 + a_3)(a_1 + a_2 + a_3) + 3 \cdot \left(\frac{a_1 + a_2 + a_3}{3}\right)^2 = \\ a_1^2 + a_2^2 + a_3^2 - \frac{2}{3}(a_1 + a_2 + a_3)^2 + \frac{1}{3}(a_1 + a_2 + a_3)^2 = \\ a_1^2 + a_2^2 + a_3^2 - \frac{1}{3}(a_1 + a_2 + a_3)^2

Alqoritmin reallaşdırılması

Giriş məlumatlarını oxuyuruq.

scanf("%d %d", &n, &k);
a.resize(n);
for (i = 0; i < n; i++)
  scanf("%d", &a[i]);

[i - k + 1; i] intervalında iki dəyişəni dəstəkləyirik:

sum = sum2 = 0;

Ardıcıllığın elementlərini ardıcıllıqla nəzərdən keçiririk.

for (i = 0; i < n; i++)
{

və dəyərlərini yeniləyirik.

  sum += a[i];
  sum2 += a[i] * a[i];

yoxsa intervalda [i - k + 1; i] varsa, onun üçün cavabı çap edirik.

  if (i >= k - 1)
  {
    printf("%lf\n", sqrt((sum2 - (sum * sum) / k) / (k - 1)));

Nəzərdən keçirilən ardıcıllıqdan i - k + 1 indeksli elementi silirik.

    sum -= a[i - k + 1];
    sum2 -= a[i - k + 1] * a[i - k + 1];
  }
}