cara mengira kerumitan masa gelung bersarang


Jawapan 1:

Tidak, tentu tidak.

Mari kita pastikan kita sangat jelas mengenai perkara ini (kerana banyak orang tidak mendapat ini). Huruf "n" terdapat dalam O (n) adalah pemboleh ubah yang mempunyai makna tertentu. Ini bukan surat ajaib yang digunakan untuk waktu tayang.

Contohnya: adakah memasukkan nilai dalam pokok carian binari seimbang O (N) atau O (log N)? Kedua-duanya adalah jawapan yang sah; ia bergantung kepada maksud N.

  • Sekiranya N mencerminkan bilangan nod di pokok, maka penyisipan memerlukan O (log N).
  • Sekiranya N mencerminkan kedalaman pokok, maka penyisipan mengambil O (N).

Apabila seseorang mengatakan sesuatu seperti "carian binari dalam array adalah O (log N)", mereka sedikit tidak tepat. Kita semua tahu bahawa mereka bermaksud bahawa N adalah ukuran array (apa lagi maksudnya?), Jadi kita tidak terlalu terganggu olehnya. Tetapi secara teknikal, mereka harus menentukan maksud N.

Oleh itu, semestinya gelung tidak semestinya O (N ^ 2). Berikut adalah beberapa contoh:

Contoh 1: O (A * W) dan / atau O (N) Kod ini mengira bilangan a dalam susunan perkataan.

array = susunan kata (di mana semua perkataan mempunyai panjang yang sama)hitung_of_As = 0untuk setiap perkataan dalam susunan: untuk setiap watak dalam perkataan: jika watak == 'a': hitung_of_As + = 1

Ini adalah O (A * W), di mana A adalah panjang larik dan W adalah panjang setiap perkataan.

Anda boleh mengatakan bahawa itu adalah O (N), di mana N adalah bilangan watak dalam semua perkataan, digabungkan.

Anda sama sekali tidak boleh mengatakan bahawa itu O (N ^ 2), kerana apa maksud N? (Baiklah, ada beberapa perkara pelik yang boleh anda tetapkan untuk menjadi N. Sebagai contoh, jika anda menentukan N sebagai punca kuasa dua watak dalam semua perkataan. Itu adalah definisi N. yang sangat pelik.)

Contoh 2: O (N ^ 4) Kod ini membina rentetan unsur unsur.

susunan = susunan watakstr = ""untuk array x: untuk susunan y: pair_to_string = "(" + x + "," + y + ")" str + = pair_to_string

Banyak orang ingin mengatakan ini adalah O (N ^ 2), di mana N adalah panjang array. Tidak begitu.

Menyatukan watak K bersama (naif, dalam kebanyakan bahasa) sebenarnya memerlukan masa O (K ^ 2). Penjelasan yang sangat mudah adalah anda terus membuat rentetan baru. Kali pertama anda membuat rentetan berukuran 1, kemudian saiz 2, kemudian saiz 3, kemudian saiz 4. Jumlah watak yang diperuntukkan O (K ^ 2), yang akan memakan masa O (K ^ 2).

(Saya tidak termasuk masa ketika penyusun mungkin melakukan beberapa pengoptimuman, yang mungkin, atau ketika bahasa melakukan sesuatu yang lebih menarik. Ini adalah contoh yang naif dan sederhana.)

Oleh itu, jika menggabungkan watak K bersama adalah waktu K ^ 2, maka menggabungkan rentetan kecil N ^ 2 bersamaan akan menjadi waktu O ((N ^ 2) ^ 2), atau O (N ^ 4).

Contoh 3: O (N) Kod ini mengira bilangan urutan 5 aksara yang sama.

tatasusunan = susunan intshitung_5_tama_sama = 0untuk i dari 0 hingga array.length - 4: all_the_same = benar untuk j = i + 1 hingga i + 4: jika tatasusunan [i]! = tatasusunan [j]: all_the_same = salah jika semua_sama: hitung_5_sama_ = 1

Kod ini memerlukan masa O (N), di mana N adalah panjang array.

Contoh 4: O (N ^ 2 log N) Kod ini mengira berapa kali produk dua bilangan bulat dalam array yang disusun berada dalam array.

tatasusunan = susunan intshitung_produk_kejadian = 0untuk array x: untuk susunan y: produk = x * y jika binary_search (array, produk): kiraan_produk_kejadian + = 1

Kod ini akan memakan masa O (N ^ 2 log N). Ini kerana gelung untuk melalui lelaran O (N ^ 2), dan setiap lelaran melakukan carian O (log N).

Terdapat sebilangan besar contoh seperti ini. Mungkin anda merasa seperti contoh ini menipu atau membengkokkan peraturan soalan. Mungkin ... jika anda menentukan soalan sebagai berikut: Adakah semua bersarang untuk gelung O (N ^ 2) di mana:

  • Bahagian luar untuk gelung berulang kali O (N)
  • Bahagian dalam untuk gelung berulang kali O (N), untuk setiap lelaran bagi gelung
  • Bahagian luar untuk gelung hanya berfungsi O (1), selain bahagian dalam untuk gelung
  • Bahagian dalam untuk gelung hanya berfungsi O (1).

Sekiranya demikian, ya, semuanya mestilah semua O (N ^ 2). (Atau sekurang-kurangnya, saya tidak dapat memikirkan contoh kontra, tetapi ada kemungkinan saya kehilangan beberapa kelayakan tambahan.)

Pengambilan yang penting di sini adalah menyedari bahawa tidak ada apa-apa yang semestinya O (N) atau O (N ^ 2). N hanyalah pemboleh ubah dan selalu mempunyai makna yang sangat spesifik (walaupun kadang-kadang kita menyimpulkan apa itu). Big O hanyalah persamaan pemboleh ubah yang mencerminkan masa berjalan. Persamaan itu boleh menjadi apa sahaja dan boleh menggunakan sebarang pemboleh ubah.


Sebenarnya, jika anda bergelut sedikit pun dengan O besar (dan walaupun anda tidak, ini tidak boleh menyakitkan): hentikan penggunaan N sebagai pemboleh ubah di O besar. Gunakan nama pemboleh ubah logik yang menggambarkan maksudnya.

Terlalu banyak orang mengatakan "O (N)" apabila mereka benar-benar bermaksud "linear". Baik, linear dalam apa? Sekiranya anda mempunyai susunan rentetan [sama panjang], sebenarnya tidak jelas sama ada "N" anda merujuk kepada susunan atau panjang tali, atau yang lain.

Mengelakkan N sebagai nama berubah-ubah akan mengelakkan anda melakukan kesalahan bodoh seperti ini:

Menyusun rentetan memerlukan masa O (N log N). Oleh itu, jika anda mempunyai rentetan rentetan dan anda ingin menyusun semuanya, ia memerlukan O (N * N log N).

Eh ... bukan. Ns berbeza. Cuba lagi, gunakan S untuk panjang rentetan dan A untuk panjang array.


Jawapan 2:

Saya rasa banyak jawapan ini tidak tepat.

Berbeza dengan jawapan Cik McDowell, anda tidak akan menggambarkan operasi memasukkan nod ke dalam pokok dari segi kedalaman pokok. Dalam carian binari seimbang memasukkan nod baru mungkin memerlukan operasi log n di mana n adalah bilangan nod di pokok. Kedalaman maksimum pokok carian binari adalah log n, jadi kita juga dapat mengatakan bahawa kedalaman pokok binari seimbang tidak lebih cepat daripada log n, di mana n adalah bilangan nod di dalam pohon.

Walaupun pernyataan Cik McDowell bahawa "N adalah pemboleh ubah" adalah benar, titik notasi asimtotik adalah untuk memahami bagaimana bilangan operasi bertambah dengan bilangan operasi, N. Oleh itu N selalu merujuk kepada ukuran set data.

Dalam sains komputer analisis asimtotik digunakan untuk mengklasifikasikan algoritma dan operasi, bukan untuk menentukan kadar pertumbuhan mereka yang sebenarnya. Oleh itu notasi sensitif secara kontekstual terhadap N dan subrutin yang tidak berskala relatif dengan N tidak diperhitungkan dalam notasi.

Perlu diingat bahawa "big-O of n" boleh digantikan dengan "tumbuh tidak lebih cepat daripada" dan ia menjawab persoalannya, "seiring bertambahnya n, seberapa cepat jumlah waktu (dari segi jumlah operasi), atau ruang ( dari segi ingatan), menghampiri infiniti berbanding dengan n? "

Pertimbangkan graf di atas. Untuk sekumpulan data ukuran n, O (n ^ 2) menerangkan sebarang algoritma yang memerlukan lebih daripada operasi n * log n dan sebanyak operasi n ^ 2. Kegunaan notasi adalah memahami seberapa cepat prestasi akan merosot dalam keadaan terburuk.

Jadi kembali kepada soalan asal: adakah gelung dalam gelung selalu O (n ^ 2)? Sekiranya bilangan lelaran kedua-dua gelung tidak berubah ketika N berubah, maka tidak akan menjadi O (n ^ 2). Walau bagaimanapun, jika kedua-dua bilangan lelaran gelung berubah ketika N berubah, maka akan berlaku.

Satu catatan terakhir, pada pendapat saya, kadar pertumbuhan operasi khusus pelaksanaan, seperti penggabungan tali, tidak relevan. Semasa mengklasifikasikan algoritma, kami menyingkirkan keistimewaan pelaksanaan untuk mengkategorikan dan membandingkan prestasi konseptual (berbanding konkrit).


Jawapan 3:

Lihat beberapa jalan terpendek atau algoritma pokok rentang minimum di mana terdapat gelung di dalam gelung tetapi kerumitannya adalah O (| V | + | E |). Masa berjalan algoritma tidak hanya bergantung pada bilangan konstruk gelung tetapi juga pada apa yang anda lakukan di dalam gelung.

Juga, gelung untuk mempunyai had atas bilangan lelaran. Sekiranya terikat adalah N di kedua gelung maka kita hanya dapat mengatakan bahawa masa berjalan terburuk adalah O (N ^ 2).

Bayangkan anda mempunyai pernyataan rehat dan anda mengetahui sesuatu yang lebih banyak mengenai masalah seperti di MST atau jalan terpendek algoritma Dijkstra yang dapat dijalankan oleh gelung dalam | E | hanya beberapa kali sahaja, jadi kami sentiasa boleh mendapatkan kod yang lebih ketat.

Lihat algoritma MST ini

Algoritma Minimum Spanning Tree Prim - Techie Me

Jawapan 4:

tidak, gelung tertanam dalam gelung lain tidak memberi anda kerumitan O (n ^ 2) automatik. Terdapat banyak contoh yang mungkin. Di atas kepalaku, contoh sepele, anggap input anda adalah senarai perkataan Inggeris (ukuran rata-rata 5.5, perkataan terpanjang 12 huruf, perkataan terpendek 2 huruf).

Dalam kes ini, ukuran input anda, n, adalah jumlah kata dalam senarai. Katakan anda perlu memproses setiap huruf dalam setiap kata untuk beberapa alasan, maka kerumitan rata-rata anda akan menjadi 5n, yang merupakan O (n). Oleh itu, walaupun anda mempunyai gelung di dalam satu gelung, kerumitan anda akan tetap linear.

Anda akan mendapat n ^ 2 dalam contoh di mana anda akan mengambil setiap perkataan dalam senarai, dan menggabungkannya dengan naif dalam operasi (seperti perbandingan) dengan setiap perkataan lain dalam senarai.


Jawapan 5:

Contoh kontra yang mudah ialah:

untuk (int i = 0; i untuk (int j = 1; j <= i; j * = 2) { ; }}

Dua gelung bersarang, dengan bahagian dalam mengambil operasi O (log (i)). Kedua-dua gelung bersama adalah O (N * log (N)).


Jawapan 6:

Ia bergantung pada keadaan yang diberikan dalam gelung untuk. Algoritma dikatakan O (n ^ 2) jika untuk semua unsur n, kod tersebut dilaksanakan n kali. Sekiranya anda memberikan keadaan dalam gelung dalam yang selalu akan menghentikan gelung dalam dan / atau gelung luar tanpa menjalankan n kali untuk semua elemen, maka ia akan mempunyai kerumitan masa kurang dari O (n). Begitu juga, keadaan yang anda berikan dalam gelung dalam boleh menjadikannya lebih besar daripada O (n ^ 2). Bilangan langkah pelaksanaan menentukan susunan algoritma.


Jawapan 7:

Contoh kaunter yang mudah,

untuk (int i = 0; i untuk (int j = 0; j <50; j ++) { //Lakukan sesuatu. }}

Kod ini berjalan di O (n) kerana gelung dalam selalu berjalan tepat 50 kali. Apabila n bertambah besar, frekuensi gelung dalam akan berjalan (selalu betul-betul 50) akan menjadi sepele berbanding dengan berapa kali gelung luar akan berjalan. Lebih daripada itu, kerana gelung dalam selalu berjalan dalam jangka masa yang tetap, ia dianggap sebagai O (1). Apabila anda mempunyai gelung bersarang, anda boleh menggandakan kerumitan waktunya untuk mencari kerumitan masa bagi blok kod anda, O (n * 1) = O (n).


Jawapan 8:

Pertimbangkan:

kiraan int = 0;untuk (int i = n; i> 0; i / = 2) { untuk (int j = 0; j kiraan ++; }}

Sekarang, cuba fahami kerumitan masa ...

Baiklah, mari kita lihat: i = n, gelung dalam berjalan n kali i = n / 2, gelung dalam berjalan n / 2 kali i = n / 4, gelung dalam berjalan n / 4 kali ...

Jumlah masa = n + n / 2 + n / 4 + \ titik

yang kurang dari 2n,

yang merupakan O (n).


Jawapan 9:

Saringan Erasthon adalah salah satu contohnya. Secara amnya dua bersarang untuk gelung tidak semestinya menunjukkan kerumitan O (N ^ 2).