0-dan n - 1-ə qədər sıralama#8636

0-dan n - 1-ə qədər sıralama (Həll təhlili)

Verilmiş ardıcıllığı -dan n - 1-ə qədər ədədlərin bir permutasiyası kimi nəzərdən keçirək. Onu müstəqil dövrlərə (cycle) parçalanma şəklində təqdim edək.

Hər bir dövrü digərlərindən asılı olmayaraq sıralamaq olar. Tutaq ki, dövrün uzunluğu -dir. Onda bu dövrün bütün elementlərini öz düzgün yerlərinə qoymaq üçün k - 1 mübadilə kifayətdir. Doğrudan da, dövrdə məhz bir elementi dərhal düzgün mövqeyinə qoymaq olar, bundan sonra uzunluğu k - 1 olan dövr qalır və proses eyni qaydada davam edir.

-dan n - 1-ə qədər bütün indekslərini nəzərdən keçirək. Əgər a_i = i-dirsə, deməli element artıq öz yerindədir və heç nə etmək lazım deyil. Əgər a_i \ne i-dirsə, bu o deməkdir ki, biz hələ emal olunmamış bir dövr tapmışıq.

Sonra bu dövrü “açmağa” başlayırıq. a_i \ne i olduğu müddətdə və a_i mövqelərindəki elementləri yer dəyişirik. Belə mübadilədən sonra a_i elementi öz düzgün yerinə düşür. Bu əməliyyatı təkrar edərək cari dövrün bütün elementlərini yerinə yerləşdiririk.

Beləliklə, minimal mübadilə sayını tapmaq üçün kifayətdir:

Nümunə

İkinci nümunəni nəzərdən keçirək. (4, 0, 3, 2, 1) permutasiyası iki dövrə parçalanır:

Birinci dövr üçün 3 - 1 = 2 mübadilə, ikinci üçün isə 2 - 1 = 1 mübadilə lazımdır. Beləliklə, ümumi minimal mübadilə sayı 2 + 1 = 3-ə bərabərdir.

Alqoritmin reallaşdırılması

Giriş permutasiyasını massivində saxlayacağıq. Yerinə yetirilmiş mübadilələri massivində saxlayırıq.

vector<int> a;
vector<pair<int, int> > ans;

Giriş permutasiyasını oxuyuruq.

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

Əgər a_i \ne i-dirsə, onda a_i elementinin aid olduğu dövrü emal edirik və lazımi mübadilələri yerinə yetiririk. Yerinə yetirilmiş mübadilələrin sayını dəyişənində sayırıq.

for (i = 0; i < n; i++)
  while (a[i] != i)
  {
    ans.push_back(make_pair(i, a[i]));
    swap(a[i], a[a[i]]);
    cnt++;
  }

Mübadilələrin sayını , sonra isə mübadilələrin özünü çıxışa veririk.

printf("%d\n", cnt);
for (i = 0; i < ans.size(); i++)
  printf("%d %d\n", ans[i].first, ans[i].second);