วิธีค้นหาความซับซ้อนของเวลาของอัลกอริทึม


889

คำถาม

จะค้นหาความซับซ้อนของเวลาในอัลกอริทึมได้อย่างไร

ฉันทำอะไรก่อนโพสต์คำถามบน SO

ฉันได้ผ่านนี้ , นี้และการเชื่อมโยงอื่น ๆ อีกมากมาย

แต่ไม่มีที่ไหนที่ฉันสามารถหาคำอธิบายที่ชัดเจนและตรงไปตรงมาสำหรับวิธีการคำนวณความซับซ้อนของเวลา

ฉันรู้อะไร ?

พูดถึงโค้ดที่ง่ายเหมือนด้านล่าง:

char h = 'y'; // This will be executed 1 time
int abc = 0; // This will be executed 1 time

พูดเพื่อวนเหมือนด้านล่าง:

for (int i = 0; i < N; i++) {        
    Console.Write('Hello World !');
}

int i = 0; นี้จะมีการดำเนินการเพียงครั้งเดียว เวลาถูกคำนวณจริงi=0และไม่ใช่การประกาศ

ฉัน <N; สิ่งนี้จะถูกดำเนินการN + 1ครั้ง

ฉัน ++; สิ่งนี้จะถูกดำเนินการNครั้ง

ดังนั้นจำนวนการปฏิบัติการที่วงนี้ต้องการ

{1+ (N + 1) + N} = 2N + 2

หมายเหตุ: สิ่งนี้อาจผิดเนื่องจากฉันไม่มั่นใจเกี่ยวกับความเข้าใจในการคำนวณความซับซ้อนของเวลา

สิ่งที่ฉันอยากรู้

ตกลงดังนั้นการคำนวณพื้นฐานขนาดเล็กเหล่านี้ฉันคิดว่าฉันรู้ แต่ในกรณีส่วนใหญ่ฉันได้เห็นความซับซ้อนของเวลาเป็น

O (N) O (N2) O (log n) O (n!) .... และหลายอื่น ๆ ,

ทุกคนสามารถช่วยฉันเข้าใจว่าจะคำนวณความซับซ้อนของเวลาของอัลกอริทึมได้อย่างไร ฉันแน่ใจว่ามีมือใหม่มากมายเช่นฉันอยากรู้


138
โบนัสสำหรับผู้ที่สนใจ: The Big O Cheat Sheet bigocheatsheet.com
msanford

4
ตรวจสอบบล็อกนี้ออก: mohalgorithmsorbit.blogspot.com ครอบคลุมขั้นตอนวิธีแบบวนซ้ำและโดยเฉพาะอย่างยิ่ง
Mohamed Ennahdi El Idrissi

1
เหตุใด Console.Write ('Hello World!'); ไม่ใช่คำสั่งของเครื่อง?
Chetan


1
@Chetan หากคุณหมายถึงว่าคุณควรพิจารณาConsole.Writeเมื่อคำนวณความซับซ้อนนั่นเป็นความจริง แต่ก็ไม่เกี่ยวข้องเลยในกรณีนี้เพราะเพียงแค่เปลี่ยนปัจจัยคงที่ซึ่ง big-O จะไม่สนใจ (ดูคำตอบ) ดังนั้นผลลัพธ์สุดท้ายยังคงอยู่ ความซับซ้อนของ O (N)
Bernhard Barker

คำตอบ:


394

วิธีค้นหาความซับซ้อนของเวลาของอัลกอริทึม

คุณเพิ่มจำนวนคำสั่งเครื่องที่จะดำเนินการเป็นฟังก์ชั่นขนาดของอินพุตจากนั้นทำให้นิพจน์เป็นคำที่ใหญ่ที่สุด (เมื่อ N มีขนาดใหญ่มาก) และทำให้สามารถรวมปัจจัยคงที่ที่ทำให้ง่ายขึ้นได้

ตัวอย่างเช่นมาดูกันว่าเราทำให้2N + 2คำสั่งเครื่องง่ายขึ้นเพื่ออธิบายสิ่งนี้O(N)ได้อย่างไร

ทำไมเราเอาสอง2หรือไม่?

เราสนใจในประสิทธิภาพของอัลกอริทึมเมื่อ N กลายเป็นขนาดใหญ่

พิจารณาสองเทอม 2N และ 2

อะไรคืออิทธิพลสัมพัทธ์ของคำสองคำนี้เมื่อ N กลายเป็นใหญ่ สมมติว่า N เป็นล้าน

เทอมแรกคือ 2 ล้านและเทอมที่สองมีเพียง 2

ด้วยเหตุผลนี้เราจึงดรอปทั้งหมดยกเว้นเทอมที่ใหญ่ที่สุดสำหรับเอ็นใหญ่

ดังนั้นตอนนี้เราได้หายไปจากการ2N + 22N

ตามเนื้อผ้าเราให้ความสนใจในการปฏิบัติงานจนถึงปัจจัยคงที่เท่านั้น

ซึ่งหมายความว่าเราไม่สนใจจริงๆหากมีความแตกต่างของประสิทธิภาพการทำงานที่คงที่เมื่อ N มีขนาดใหญ่ หน่วยของ 2N นั้นไม่ได้ถูกกำหนดอย่างชัดเจนตั้งแต่แรก ดังนั้นเราสามารถคูณหรือหารด้วยปัจจัยคงที่เพื่อให้ได้นิพจน์ที่ง่ายที่สุด

ดังนั้นจะกลายเป็นเพียง2NN


53
เฮ้ขอบคุณที่ให้ฉันรู้ว่า "ทำไม O (2N + 2) ถึง O (N)" อธิบายไว้อย่างดีมาก แต่นี่เป็นเพียงส่วนหนึ่งของคำถามที่ใหญ่กว่าฉันต้องการให้ใครซักคนชี้ไปยังลิงก์ที่ซ่อนอยู่หรือใน ทั่วไปฉันต้องการทราบว่าคุณจะจบลงอย่างไรกับความซับซ้อนของเวลาเช่น O (N), O (n2), O (บันทึก n), O (n!) ฯลฯ ฉันรู้ว่าฉันอาจจะถามมาก แต่ ยังฉันสามารถลอง: {)
Yasser Shaikh

3
ความซับซ้อนในวงเล็บคือระยะเวลาที่อัลกอริทึมใช้งานง่ายขึ้นโดยใช้วิธีที่ฉันอธิบาย เราหาระยะเวลาที่อัลกอริทึมใช้เพียงเพิ่มจำนวนคำสั่งเครื่องที่จะใช้ เราทำได้ง่ายขึ้นโดยดูจากลูปที่คึกคักที่สุดและหารด้วยปัจจัยคงที่ดังที่ฉันได้อธิบายไว้
Andrew Tomazos

4
การให้ตัวอย่างคำตอบจะช่วยได้มากสำหรับผู้อ่านในอนาคต เพียงแค่ส่งลิงค์ที่ฉันต้องสมัครใช้งานจริง ๆ ก็ไม่ได้ช่วยฉันเมื่อฉันต้องการที่จะผ่านข้อความที่อธิบายอย่างบางอย่าง
bad_keypoints

2
ฉันอยากจะแนะนำให้ดูวิดีโอดร. Naveen Garg (IIT Delhi Prof. ) หากคุณต้องการความรู้ที่ดีเกี่ยวกับ DS และ Time complex ตรวจสอบลิงค์ nptel.ac.in/courses/106102064
Rohit Bandil

2
(ต่อ) ลำดับชั้นนี้จะมีความสูงตามลำดับของบันทึก N สำหรับ O (N!) การเปรียบเทียบของฉันจะไม่ตัด แต่การเรียงสับเปลี่ยนอยู่ในลำดับนั้น - มันสูงชันมากเกินกว่าพหุนามหรือ ที่ชี้แจง มี 10 อย่างแน่นอน! วินาทีในหกสัปดาห์ แต่จักรวาลน้อยกว่า 20! วินาทีเก่า
John P

389

นี่เป็นบทความที่ยอดเยี่ยม: http://www.daniweb.com/software-development/computer-science/threads/13488/time-complexity-of-algorithm

คำตอบด้านล่างถูกคัดลอกมาจากด้านบน (ในกรณีที่ลิงค์ที่ยอดเยี่ยมหลุด)

ตัวชี้วัดที่พบบ่อยที่สุดสำหรับการคำนวณความซับซ้อนของเวลาคือสัญกรณ์ Big O สิ่งนี้จะลบปัจจัยคงที่ทั้งหมดเพื่อให้เวลาในการรันสามารถประมาณโดยสัมพันธ์กับ N เมื่อ N เข้าใกล้อนันต์ โดยทั่วไปคุณสามารถคิดแบบนี้:

statement;

เป็นค่าคงที่ เวลาทำงานของคำสั่งจะไม่เปลี่ยนแปลงเมื่อเทียบกับ N

for ( i = 0; i < N; i++ )
     statement;

เป็นเส้นตรง เวลาทำงานของลูปเป็นสัดส่วนโดยตรงกับ N เมื่อ N เพิ่มขึ้นเป็นสองเท่าดังนั้นเวลาทำงาน

for ( i = 0; i < N; i++ ) {
  for ( j = 0; j < N; j++ )
    statement;
}

เป็นกำลังสอง เวลาทำงานของสองลูปเป็นสัดส่วนกับกำลังสองของ N เมื่อ N เพิ่มขึ้นเป็นสองเท่าเวลาทำงานเพิ่มขึ้น N * N

while ( low <= high ) {
  mid = ( low + high ) / 2;
  if ( target < list[mid] )
    high = mid - 1;
  else if ( target > list[mid] )
    low = mid + 1;
  else break;
}

เป็นลอการิทึม เวลาทำงานของอัลกอริทึมเป็นสัดส่วนกับจำนวนครั้งที่ N สามารถหารด้วย 2 นี่เป็นเพราะอัลกอริทึมจะแบ่งพื้นที่ทำงานเป็นครึ่งหนึ่งกับการวนซ้ำแต่ละครั้ง

void quicksort ( int list[], int left, int right )
{
  int pivot = partition ( list, left, right );
  quicksort ( list, left, pivot - 1 );
  quicksort ( list, pivot + 1, right );
}

คือ N * log (N) เวลาทำงานประกอบด้วย N ลูป (วนซ้ำหรือเรียกซ้ำ) ซึ่งเป็นลอการิทึมดังนั้นอัลกอริทึมจึงเป็นการรวมกันของเชิงเส้นและลอการิทึม

โดยทั่วไปการทำบางสิ่งกับทุกรายการในหนึ่งมิตินั้นเป็นแบบเส้นตรงการทำบางสิ่งกับทุกรายการในสองมิตินั้นเป็นกำลังสองและการแบ่งพื้นที่ทำงานครึ่งคือลอการิทึม มีมาตรการ Big O อื่น ๆ เช่นลูกบาศก์, เลขชี้กำลังและรากที่สอง แต่ก็ไม่ได้ใกล้เคียงกัน สัญกรณ์บิ๊กโอมีการอธิบายตามO ( <type> )ที่<type>เป็นมาตรการ อัลกอริทึม quicksort O ( N * log ( N ) )จะได้รับการอธิบายว่า

โปรดทราบว่ามาตรการเหล่านี้ไม่ได้คำนึงถึงมาตรการที่ดีที่สุดค่าเฉลี่ยและแย่ที่สุด แต่ละคนจะมีสัญลักษณ์ Big O ของตัวเอง โปรดทราบว่านี่เป็นคำอธิบายที่ง่ายมาก Big O เป็นเรื่องธรรมดา แต่ก็ซับซ้อนกว่าที่ฉันเคยแสดง นอกจากนี้ยังมีสัญลักษณ์อื่น ๆ เช่นโอเมก้าใหญ่โอตัวน้อยและทีต้าตัวใหญ่ คุณอาจไม่พบพวกเขานอกหลักสูตรการวิเคราะห์อัลกอริทึม ;)


10
quicksortขั้นตอนวิธีการในกรณีที่เลวร้ายที่สุดมีเวลาการทำงานของ N ^ 2 แม้ว่าพฤติกรรมนี้เป็นของหายาก
nbro

2
IIRC, เล็ก ๆ น้อย ๆ และโอเมก้าขนาดใหญ่จะใช้สำหรับความซับซ้อนของกรณีที่ดีที่สุดและโดยเฉลี่ย (กับ O ใหญ่เป็นกรณีที่เลวร้ายที่สุด) ดังนั้น "มาตรการที่ดีที่สุดโดยเฉลี่ยและที่เลวร้ายที่สุด จะไม่ถูกต้อง มีสัญลักษณ์มากขึ้นพร้อมความหมายที่เฉพาะเจาะจงมากขึ้นและ CS ไม่ได้ใช้สัญลักษณ์ที่เหมาะสมที่สุดเสมอไป ฉันมาเพื่อเรียนรู้สิ่งเหล่านี้ด้วยสัญลักษณ์ชื่อLandau btw +1 anyways b / c คำตอบที่ดีที่สุด
hiergiltdiestfu

@hiergiltdiestfu Big-O, Big-Omega และอื่น ๆ สามารถนำไปใช้กับกรณีที่ดีที่สุดโดยเฉลี่ยหรือเลวร้ายที่สุดเวลาทำงานของอัลกอริทึม O และΩเกี่ยวข้องกับกรณีที่เลวร้ายที่สุดและดีที่สุดได้อย่างไร?
Bernhard Barker

นอกจากนี้หากใครกำลังมองหาวิธีการคำนวณใหญ่สำหรับวิธีการใด ๆ : stackoverflow.com/a/60354355/4260691
OhadM

หนึ่งในคำอธิบายที่ดีที่สุด
Shivaraj Patil

172

นำมาจากที่นี่ - ความซับซ้อนของเวลาเบื้องต้นของอัลกอริทึม

1. บทนำ

ในวิทยาการคอมพิวเตอร์ความซับซ้อนของเวลาของอัลกอริทึมคำนวณจำนวนเวลาที่ใช้โดยอัลกอริธึมที่จะเรียกใช้เป็นฟังก์ชันของความยาวของสตริงที่เป็นตัวแทนของอินพุต

2. สัญกรณ์ Big O

ความซับซ้อนของเวลาของอัลกอริทึมจะแสดงโดยใช้สัญกรณ์ O ขนาดใหญ่ซึ่งไม่รวมค่าสัมประสิทธิ์และเงื่อนไขการสั่งซื้อที่ต่ำกว่า เมื่อแสดงด้วยวิธีนี้ความซับซ้อนของเวลาจะถูกอธิบายว่าไม่มีความหมายเช่นเมื่อขนาดอินพุตเป็นอินฟินิตี้

ตัวอย่างเช่นหากเวลาที่อัลกอริทึมต้องการในอินพุตทั้งหมดของขนาด n มีค่ามากที่สุด 5n 3 + 3n ความซับซ้อนของเวลาแบบอะซิมโทติคคือ O (n 3 ) เพิ่มเติมในภายหลัง

อีกไม่กี่ตัวอย่าง:

  • 1 = O (n)
  • n = O (n 2 )
  • log (n) = O (n)
  • 2 n + 1 = O (n)

3. O (1) เวลาคงที่:

อัลกอริทึมถูกเรียกใช้ในเวลาคงที่หากต้องการเวลาเท่ากันโดยไม่คำนึงถึงขนาดอินพุต

ตัวอย่าง:

  • array: เข้าถึงองค์ประกอบใด ๆ
  • สแต็กขนาดคงที่: วิธีการผลักดันและป๊อป
  • คิวขนาดคงที่: วิธีการจัดคิวและคิว

4. O (n) เวลาเชิงเส้น

อัลกอริทึมถูกเรียกใช้ในเวลาเชิงเส้นถ้าการดำเนินการเวลาเป็นสัดส่วนโดยตรงกับขนาดอินพุตเช่นเวลาเติบโตเป็นเชิงเส้นเมื่อขนาดอินพุตเพิ่มขึ้น

ลองพิจารณาตัวอย่างต่อไปนี้ด้านล่างฉันค้นหาองค์ประกอบเป็นเส้นตรงซึ่งมีความซับซ้อนของเวลาเป็น O (n)

int find = 66;
var numbers = new int[] { 33, 435, 36, 37, 43, 45, 66, 656, 2232 };
for (int i = 0; i < numbers.Length - 1; i++)
{
    if(find == numbers[i])
    {
        return;
    }
}

ตัวอย่างเพิ่มเติม:

  • อาเรย์: การค้นหาเชิงเส้น, การข้าม, ค้นหาขั้นต่ำ ฯลฯ
  • ArrayList: มีวิธีการ
  • คิว: มีวิธีการ

5. O (log n) เวลาลอการิทึม:

อัลกอริทึมถูกเรียกใช้ในเวลาลอการิทึมหากการดำเนินการเวลาเป็นสัดส่วนกับลอการิทึมของขนาดอินพุต

ตัวอย่าง: การค้นหาแบบไบนารี

จำเกม "ยี่สิบคำถาม" - งานคือการคาดเดาค่าของตัวเลขที่ซ่อนอยู่ในช่วงเวลา ทุกครั้งที่คุณคาดเดาคุณจะได้รับแจ้งว่าการเดาของคุณสูงหรือต่ำเกินไป เกมคำถามยี่สิบคำถามแสดงถึงกลยุทธ์ที่ใช้หมายเลขที่คุณคาดเดาเพื่อลดขนาดช่วงเวลาลงครึ่งหนึ่ง นี่คือตัวอย่างของวิธีการแก้ปัญหาทั่วไปที่เรียกว่าการค้นหาแบบไบนารี

6. O (n 2 ) เวลากำลังสอง

อัลกอริทึมถูกเรียกใช้ในเวลากำลังสองถ้าการดำเนินการเวลาเป็นสัดส่วนกับกำลังสองของขนาดอินพุต

ตัวอย่าง:

7. ลิงก์ที่มีประโยชน์


17
หมายเหตุ: ลิงค์แรกเสีย
Ziezi

2
ควรเขียน O (n2) O (n ^ 2) เพื่อหลีกเลี่ยงความสับสน
Rizki Hadiaturrasyid

100

แม้ว่าจะมีคำตอบที่ดีสำหรับคำถามนี้ loopผมอยากจะให้คำตอบที่นี่อีกหลายตัวอย่างของ

  • O (n) : ความซับซ้อนของเวลาของลูปนั้นถือเป็นO (n)หากตัวแปรลูปเพิ่มขึ้น / ลดลงตามจำนวนคงที่ ตัวอย่างเช่นฟังก์ชั่นต่อไปนี้มีความซับซ้อนของเวลาO (n)

    // Here c is a positive integer constant   
    for (int i = 1; i <= n; i += c) {  
        // some O(1) expressions
    }
    
    for (int i = n; i > 0; i -= c) {
        // some O(1) expressions
    }
    
  • O (n ^ c) : ความซับซ้อนของเวลาของลูปซ้อนกันจะเท่ากับจำนวนครั้งที่คำสั่งด้านในจะถูกดำเนินการ ตัวอย่างลูปตัวอย่างต่อไปนี้มีความซับซ้อนของเวลาO (n ^ 2)

    for (int i = 1; i <=n; i += c) {
       for (int j = 1; j <=n; j += c) {
          // some O(1) expressions
       }
    }
    
    for (int i = n; i > 0; i += c) {
       for (int j = i+1; j <=n; j += c) {
          // some O(1) expressions
    }
    

    ตัวอย่างเช่นการเรียงลำดับการเลือกและการเรียงการแทรกมีความซับซ้อนของเวลาO (n ^ 2)

  • O (Logn)ความซับซ้อนของเวลาของลูปนั้นถือเป็นO (Logn)หากตัวแปรลูปถูกแบ่ง / คูณด้วยจำนวนคงที่

    for (int i = 1; i <=n; i *= c) {
       // some O(1) expressions
    }
    for (int i = n; i > 0; i /= c) {
       // some O(1) expressions
    }
    

    ตัวอย่างเช่นการค้นหาแบบไบนารีมีความซับซ้อนของเวลาO (Logn)

  • O (LogLogn)ความซับซ้อนของเวลาของลูปนั้นถือเป็นO (LogLogn)หากตัวแปรลูปลดลง / เพิ่มขึ้นชี้แจงโดยจำนวนคงที่

    // Here c is a constant greater than 1   
    for (int i = 2; i <=n; i = pow(i, c)) { 
       // some O(1) expressions
    }
    //Here fun is sqrt or cuberoot or any other constant root
    for (int i = n; i > 0; i = fun(i)) { 
       // some O(1) expressions
    }
    

ตัวอย่างหนึ่งของการวิเคราะห์ความซับซ้อนของเวลา

int fun(int n)
{    
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j < n; j += i)
        {
            // Some O(1) task
        }
    }    
}

วิเคราะห์ :

For i = 1, the inner loop is executed n times. For i = 2, the inner loop is executed approximately n/2 times. For i = 3, the inner loop is executed approximately n/3 times. For i = 4, the inner loop is executed approximately n/4 times. ……………………………………………………. For i = n, the inner loop is executed approximately n/n times.

ดังนั้นความซับซ้อนเวลารวมของขั้นตอนวิธีการข้างต้นนี้(n + n/2 + n/3 + … + n/n)ซึ่งจะกลายเป็นn * (1/1 + 1/2 + 1/3 + … + 1/n)

สิ่งที่สำคัญเกี่ยวกับชุด(1/1 + 1/2 + 1/3 + … + 1/n)เท่ากับO (logn) ดังนั้นเวลาซับซ้อนของโค้ดข้างต้นคือO (nlogn)


Ref: 1 2 3


1
@Simon คุณช่วยโปรดคิดว่าส่วนไหนไม่ถูกต้อง?
zangw

ขอบคุณที่ถาม. ฉันอ่านรหัสผิด ฉันลบความคิดเห็นของฉัน ขออภัย!
Simon

74

ความซับซ้อนของเวลากับตัวอย่าง

1 - การใช้งานขั้นพื้นฐาน (เลขคณิตการเปรียบเทียบการเข้าถึงองค์ประกอบของอาร์เรย์การกำหนด): เวลาที่ใช้งานจะเป็นค่าคงที่ O เสมอ (1)

ตัวอย่าง:

read(x)                               // O(1)
a = 10;                               // O(1)
a = 1.000.000.000.000.000.000         // O(1)

2 - ถ้าเป็นอย่างอื่น statement: ใช้เวลาทำงานสูงสุดจากสองข้อความที่เป็นไปได้เท่านั้น

ตัวอย่าง:

age = read(x)                               // (1+1) = 2
if age < 17 then begin                      // 1
      status = "Not allowed!";              // 1
end else begin
      status = "Welcome! Please come in";   // 1
      visitors = visitors + 1;              // 1+1 = 2
end;

ดังนั้นความซับซ้อนของรหัสหลอกข้างต้นคือ T (n) = 2 + 1 + สูงสุด (1, 1 + 2) = 6 ดังนั้นขนาดใหญ่โอ้ยังคงเป็น T (n) = O (1)

3 - วนรอบ (สำหรับขณะทำซ้ำ): เวลาที่ใช้สำหรับคำสั่งนี้คือจำนวนการวนซ้ำคูณด้วยจำนวนการดำเนินการภายในลูปนั้น

ตัวอย่าง:

total = 0;                                  // 1
for i = 1 to n do begin                     // (1+1)*n = 2n
      total = total + i;                    // (1+1)*n = 2n
end;
writeln(total);                             // 1

ดังนั้นความซับซ้อนของมันคือ T (n) = 1 + 4n + 1 = 4n + 2 ดังนั้น T (n) = O (n)

4 - Nested Loop (การวนซ้ำภายในการวนซ้ำ): เนื่องจากมีการวนซ้ำอย่างน้อยหนึ่งการวนซ้ำภายในการวนรอบหลักเวลาทำงานของคำสั่งนี้จึงใช้ O (n ^ 2) หรือ O (n ^ 3)

ตัวอย่าง:

for i = 1 to n do begin                     // (1+1)*n  = 2n
   for j = 1 to n do begin                  // (1+1)n*n = 2n^2
       x = x + 1;                           // (1+1)n*n = 2n^2
       print(x);                            // (n*n)    = n^2
   end;
end;

เวลาทำงานปกติ

มีเวลาทำงานทั่วไปเมื่อวิเคราะห์อัลกอริทึม:

  1. O (1) - เวลาคงที่คงที่เวลาหมายถึงเวลาทำงานเป็นค่าคงที่ก็ไม่ได้รับผลกระทบจากขนาดการป้อนข้อมูล

  2. O (n) - เวลาเชิงเส้นเมื่ออัลกอริทึมยอมรับขนาดอินพุต n จะดำเนินการ n ด้วยเช่นกัน

  3. O (log n) - อัลกอริทึมเวลาลอการิทึมที่มีเวลาทำงาน O (log n) จะเร็วกว่า O (n) เล็กน้อย โดยทั่วไปอัลกอริทึมจะแบ่งปัญหาออกเป็นปัญหาย่อยด้วยขนาดเดียวกัน ตัวอย่าง: อัลกอริทึมการค้นหาแบบไบนารี, อัลกอริทึมการแปลงแบบไบนารี

  4. O (n log n) - Linearithmic Time เวลาทำงานนี้มักจะพบใน "การหาร & พิชิตอัลกอริธึม" ซึ่งแบ่งปัญหาออกเป็นปัญหาย่อยซ้ำแล้วรวมเข้าด้วยกันในเวลา n ตัวอย่าง: ผสานอัลกอริทึมการเรียงลำดับ

  5. O (n 2 ) - อัลกอริธึมการเรียงลำดับฟองดูกำลังสอง!

  6. O (n 3 ) - ลูกบาศก์เวลามันมีหลักการเดียวกันกับ O (n 2 )

  7. O (2 n ) - เวลาเอ็กซ์โปเนนเชียลมันช้ามากเมื่ออินพุทใหญ่ขึ้นถ้า n = 1,000.000, T (n) จะเป็น 21000.000 อัลกอริทึม Brute Force มีเวลาทำงานนี้

  8. O (n!) - Factorial Time ช้าที่สุด !!! ตัวอย่าง: ปัญหาพนักงานขายเดินทาง (TSP)

ที่นำมาจากบทความนี้ อธิบายได้ดีมากควรให้อ่าน


ในตัวอย่างที่ 2 ของคุณที่คุณเขียนคือvisitors = visitors + 1 1 + 1 = 2คุณช่วยอธิบายให้ฉันฟังหน่อยได้ไหมว่าทำไมคุณถึงทำอย่างนั้น?
Sajib Acharya

3
@Sajib Acharya ดูจากขวาไปซ้าย ขั้นตอนแรก: คำนวณvisitors + 1 ขั้นตอนที่สอง: กำหนดค่าจากขั้นตอนแรกถึงvisitors ดังนั้นการแสดงออกข้างต้นจะเกิดขึ้นจากสองคำสั่ง; ขั้นตอนแรก + ขั้นตอนที่สอง => 1 + 1 = 2
Bozidar Sikanjic

@nbro ทำไมจึงเป็น 1 + 1 ในage = read(x) // (1+1) = 2
Humty

@BozidarSikanjic ทำไมจึงเป็น 1 + 1 ในage = read(x) // (1+1) = 2
Humty

1
@Humty ตรวจสอบจุดเริ่มต้นของคำตอบนี้: read(x) // O(1) a = 10; // O(1)อันดับแรกคือการเรียกใช้ฟังก์ชัน => O (1) ///// ที่สองคือการมอบหมายตามที่ nbro พูด แต่ 10 คงที่ดังนั้นวินาทีคือ => O (1) ...
Bozidar Sikanjic

41

เมื่อคุณวิเคราะห์โค้ดคุณจะต้องวิเคราะห์ทีละบรรทัดนับการดำเนินการทุกครั้ง / การรับรู้ความซับซ้อนของเวลาในที่สุดคุณจะต้องรวมมันเพื่อให้ได้ภาพรวมทั้งหมด

ตัวอย่างเช่นคุณสามารถมีหนึ่งวงที่เรียบง่ายกับความซับซ้อนเชิงเส้นแต่ต่อมาในโปรแกรมเดียวกันกับที่คุณสามารถมีสามห่วงที่มีลูกบาศก์ซับซ้อนดังนั้นโปรแกรมของคุณจะมีลูกบาศก์ซับซ้อน ลำดับฟังก์ชั่นของการเติบโตเข้ามาเล่นที่นี่

ลองดูสิ่งที่เป็นไปได้สำหรับความซับซ้อนของเวลาของอัลกอริทึมคุณสามารถดูลำดับการเติบโตที่ฉันได้กล่าวไว้ข้างต้น:

  • เวลาคงที่มีลำดับของการเติบโต1ตัวอย่างเช่น:a = b + c.

  • เวลาลอการิทึมมีลำดับของการเจริญเติบโตLogNมันมักจะเกิดขึ้นเมื่อคุณแบ่งบางสิ่งในครึ่ง (การค้นหาแบบไบนารีต้นไม้แม้กระทั่งลูป) หรือการคูณบางอย่างด้วยวิธีเดียวกัน

  • เป็น LinearลำดับของการเจริญเติบโตNเช่น

    int p = 0;
    for (int i = 1; i < N; i++)
      p = p + 2;
    
  • Linearithmicลำดับของการเติบโตn*logNมักเกิดขึ้นในการแบ่งและพิชิตอัลกอริธึม

  • ลูกบาศก์ , ลำดับการเติบโตN^3, ตัวอย่างคลาสสิกคือวงสามวงที่คุณตรวจสอบทริปเปิลทั้งหมด:

    int x = 0;
    for (int i = 0; i < N; i++)
       for (int j = 0; j < N; j++)
          for (int k = 0; k < N; k++)
              x = x + 2
    
  • เอ็กซ์โพเนนเชียลลำดับของการเติบโต2^Nมักเกิดขึ้นเมื่อคุณทำการค้นหาแบบละเอียดตัวอย่างเช่นตรวจสอบชุดย่อยของบางชุด


หากเป็นเช่นนี้ความซับซ้อนจะเป็นอย่างไร สำหรับ (int i = 0; i <N; i ++) สำหรับ (int j = i + 1; j <N; j ++) สำหรับ (int k = j + 1; k <N; k ++) x = x + 2
user3156040

35

ความซับซ้อนของเวลาเป็นวิธีหนึ่งในการสรุปว่าจำนวนการดำเนินการหรือเวลาทำงานของอัลกอริทึมเพิ่มขึ้นอย่างไรเมื่อขนาดอินพุตเพิ่มขึ้น

เช่นเดียวกับสิ่งส่วนใหญ่ในชีวิตปาร์ตี้ค็อกเทลสามารถช่วยให้เราเข้าใจ

บน)

เมื่อคุณมาถึงงานปาร์ตี้คุณต้องจับมือทุกคน (จัดการทุกรายการ) ขณะที่จำนวนของผู้เข้าร่วมประชุมNเพิ่มเวลา / O(N)การทำงานก็จะพาคุณไปเขย่าของทุกคนเพิ่มขึ้นเป็นมือ

ทำไมO(N)ไม่cN?

มีการเปลี่ยนแปลงในระยะเวลาที่ใช้ในการจับมือกับผู้คน cคุณสามารถเฉลี่ยนี้ออกและจับมันในอย่างต่อเนื่อง แต่การดำเนินการขั้นพื้นฐานที่นี่ - จับมือกับทุกคน - จะเป็นสัดส่วนเสมอO(N)ไม่ว่าอะไรcจะเกิดขึ้น เมื่อถกเถียงกันว่าเราควรจะไปงานเลี้ยงค็อกเทลบ่อยครั้งเราสนใจในข้อเท็จจริงที่ว่าเราจะต้องพบกับทุกคนมากกว่าในรายละเอียดของการประชุมเหล่านั้น

O (n ^ 2)

โฮสต์ของปาร์ตี้ค็อกเทลต้องการให้คุณเล่นเกมที่งี่เง่าที่ทุกคนพบกับคนอื่น ดังนั้นคุณต้องพบN-1คนอื่นและเพราะคนต่อไปได้พบคุณแล้วพวกเขาจะต้องพบปะN-2ผู้คนและอื่น ๆ x^2/2+x/2ผลรวมของชุดนี้คือ เมื่อจำนวนผู้เข้าร่วมเพิ่มขึ้นเรื่อย ๆx^2เทอมนั้นใหญ่ขึ้นอย่างรวดเร็วดังนั้นเราจึงทิ้งทุกอย่างไว้

O (n ^ 3)

คุณต้องพบกับคนอื่นและในการประชุมแต่ละครั้งคุณต้องพูดคุยเกี่ยวกับคนอื่นในห้อง

O (1)

โฮสต์ต้องการประกาศบางสิ่งบางอย่าง พวกเขาจิ้มแก้วไวน์และพูดเสียงดัง ทุกคนได้ยินพวกเขา ปรากฎว่าไม่สำคัญว่ามีผู้เข้าร่วมประชุมกี่รายการดำเนินการนี้ใช้เวลาเท่ากันเสมอ

O (บันทึก N)

โฮสต์ได้จัดวางทุกคนไว้ที่โต๊ะตามลำดับตัวอักษร แดนอยู่ที่ไหน คุณให้เหตุผลว่าเขาจะต้องอยู่ที่ไหนสักแห่งระหว่างอดัมและแมนดี้ (ไม่ใช่แน่นอนระหว่างแมนดี้และซัค!) ระบุว่าเขาอยู่ระหว่างจอร์จกับแมนดี้หรือไม่? ไม่เขาต้องอยู่ระหว่างอาดัมกับเฟร็ดและระหว่างซินดี้กับเฟร็ด และอื่น ๆ ... เราสามารถค้นหา Dan ได้อย่างมีประสิทธิภาพโดยดูที่ครึ่งชุดจากนั้นครึ่งหนึ่งของชุดนั้น ในท้ายที่สุดเรามองไปที่O (log_2 N)บุคคล

O (N log N)

คุณสามารถหาตำแหน่งที่จะนั่งลงที่โต๊ะโดยใช้อัลกอริทึมด้านบน ถ้าเป็นจำนวนมากของผู้คนมาถึงโต๊ะหนึ่งที่เวลาและทุกทำอย่างนี้ว่าจะใช้เวลาO (n log n)เวลา สิ่งนี้กลายเป็นว่าต้องใช้เวลานานแค่ไหนในการเรียงลำดับการรวบรวมรายการใด ๆ เมื่อต้องเปรียบเทียบ

กรณีที่ดีที่สุด / แย่ที่สุด

คุณมาถึงงานปาร์ตี้และต้องการหา Inigo - ใช้เวลานานเท่าไหร่? ขึ้นอยู่กับว่าคุณมาถึงเมื่อไหร่ หากทุกคนกำลังโวยวายไปรอบ ๆ คุณได้พบกับกรณีที่เลวร้ายที่สุดมันต้องใช้O(N)เวลา แต่ถ้าทุกคนนั่งลงที่โต๊ะก็จะใช้เวลาเพียงO(log N)เวลา หรือบางทีคุณอาจจะสามารถใช้ประโยชน์จากพลัง Wineglass-ตะโกนของโฮสต์และมันจะใช้เวลาเพียงO(1)เวลา

สมมติว่าโฮสต์ไม่พร้อมใช้งานเราสามารถพูดได้ว่าอัลกอริทึมการค้นหา Inigo มีขอบเขตล่างO(log N)และขอบบนของO(N)ขึ้นอยู่กับสถานะของพรรคเมื่อคุณมาถึง

อวกาศและการสื่อสาร

แนวคิดเดียวกันนี้สามารถนำไปใช้กับการทำความเข้าใจวิธีที่อัลกอริทึมใช้พื้นที่หรือการสื่อสาร

Knuth ได้เขียนกระดาษที่ดีเกี่ยวกับอดีตสิทธิ"ความซับซ้อนของเพลง"

ทฤษฎีบทที่ 2: มีเพลงที่ซับซ้อนตามอำเภอใจยาว O (1)

หลักฐาน: (เนื่องจาก Casey and the Sunshine Band) พิจารณาเพลง Sk ที่กำหนดโดย (15) แต่ด้วย

V_k = 'That's the way,' U 'I like it, ' U
U   = 'uh huh,' 'uh huh'

สำหรับ k ทั้งหมด


คุณจับมันตอนนี้เมื่อใดก็ตามที่ฉันไปงานเลี้ยงค็อกเทลฉันจะพยายามค้นหา Time Complexity จากกิจกรรมสนุก ๆ โดยไม่รู้ตัว ขอบคุณสำหรับตัวอย่างที่น่าขบขัน
Sabunkar Tejas Sahailesh

5

ฉันรู้ว่าคำถามนี้จะกลับไปและมีคำตอบที่ดีบางอย่างที่นี่ แต่ฉันต้องการแบ่งปันอีกเล็กน้อยสำหรับคนที่มีใจทางคณิตศาสตร์ที่จะสะดุดในโพสต์นี้ ทฤษฎีบทโทเป็นอีกหนึ่งสิ่งที่มีประโยชน์ที่จะรู้ว่าเมื่อศึกษาความซับซ้อน ฉันไม่เห็นมันพูดถึงในคำตอบอื่น ๆ


2

O (n) เป็นสัญกรณ์ O ขนาดใหญ่ที่ใช้สำหรับการเขียนความซับซ้อนของอัลกอริทึม เมื่อคุณเพิ่มจำนวนการประมวลผลใน algoritm คุณจะได้รับนิพจน์เช่น 2N + 2 ในนิพจน์นี้ N เป็นคำที่มีอำนาจเหนือ (คำที่มีผลต่อการแสดงออกมากที่สุดหากค่าเพิ่มขึ้นหรือลดลง) ตอนนี้ O (N) คือความละเอียดของเวลาในขณะที่ N เป็นคำศัพท์ ตัวอย่าง

For i= 1 to n;
  j= 0;
while(j<=n);
  j=j+1;

จำนวนการประมวลผลทั้งหมดสำหรับลูปภายในคือ n + 1 และจำนวนการประมวลผลสำหรับลูปภายนอกคือ n (n + 1) / 2 ดังนั้นจำนวนการประมวลผลทั้งหมดสำหรับอัลกอริทึมทั้งหมดคือ n + 1 + n (n + 1/2 ) = (n ^ 2 + 3n) / 2 นี่ n ^ 2 เป็นศัพท์ที่มีอิทธิพลดังนั้นความซับซ้อนของเวลาสำหรับอัลกอริทึมนี้คือ O (n ^ 2)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.