O (…) คืออะไรและฉันจะคำนวณได้อย่างไร


31

ช่วยด้วย! ฉันมีคำถามที่ฉันต้องการวิเคราะห์ Big-O ของอัลกอริทึมหรือรหัสบางอย่าง

  • ฉันไม่แน่ใจว่า Big-O คืออะไรหรือเกี่ยวข้องกับ Big-Theta หรือวิธีอื่น ๆ ในการวิเคราะห์ความซับซ้อนของอัลกอริทึม

  • ฉันไม่แน่ใจว่า Big-O อ้างอิงถึงเวลาในการเรียกใช้รหัสหรือจำนวนหน่วยความจำที่ใช้ (การแลกเปลี่ยนพื้นที่ / เวลา)

  • ฉันมีการบ้านวิทยาการคอมพิวเตอร์ที่ฉันต้องใช้ลูปบางทีอัลกอริทึมแบบเรียกซ้ำและมากับ Big-O สำหรับมัน

  • ฉันกำลังทำงานกับโปรแกรมที่ฉันมีตัวเลือกระหว่างสองโครงสร้างข้อมูลหรืออัลกอริทึมกับ Big-O ที่รู้จักกันดีและไม่แน่ใจว่าจะเลือกตัวเลือกใด

ฉันจะเข้าใจวิธีการคำนวณและใช้ Big-O กับโปรแกรมการบ้านหรือความรู้ทั่วไปของวิทยาการคอมพิวเตอร์ได้อย่างไร

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


1
เพียงแค่บันทึกคำถามนี้จะถูกกล่าวถึงในmeta ที่นี่
enderland

2
แหล่งข้อมูลที่ดีสำหรับการเริ่มต้นคือหลักสูตรของ Khan Academy (Thomas Cormen ของ CLRS เป็นหนึ่งในนักเขียน) นี่เป็นแหล่งข้อมูลที่ยอดเยี่ยมสำหรับฉันในฐานะผู้สำเร็จการศึกษา CS เช่นกัน khanacademy.org/computing/computer-science/algorithms
Sudip Bhandari

3
สำหรับผู้ที่ตั้งค่าสถานะคำถามนี้: โปรดอ่านคำบรรยายท้ายบทที่ด้านล่างของคำถามและไปที่ลิงก์นั้นก่อนที่จะปิดการตั้งค่าสถานะหรือลงคะแนนให้ปิด

คำตอบ:


22

O (... ) หมายถึงสัญกรณ์ Big-O ซึ่งเป็นวิธีที่ง่ายในการอธิบายว่ามีการดำเนินการหลายวิธีที่อัลกอริทึมใช้ในการทำอะไร นี้เป็นที่รู้จักกันเป็นเวลาซับซ้อน

ในสัญกรณ์ Big-O ค่าใช้จ่ายของอัลกอริทึมจะแสดงโดยการดำเนินการที่มีราคาแพงที่สุดในจำนวนมาก หากอัลกอริทึมทำตามขั้นตอนมันจะแสดง O (n 3 ) อัลกอริทึมที่นับแต่ละรายการในรายการจะทำงานในเวลา O (n) เรียกว่าเวลาเชิงเส้นn3 + n2 + n

สำหรับรายการชื่อและตัวอย่างคลาสสิกใน Wikipedia: คำสั่งของฟังก์ชันทั่วไป

วัสดุที่เกี่ยวข้อง:


6
หมายเหตุ: ใหญ่ O ไม่ได้วัดเวลาหรือพื้นที่หรือสิ่งใดโดยเฉพาะ มันเพียงแค่ขอบเขตบนการเติบโตของซีมโทติคของฟังก์ชัน (มากถึงค่าคงที่) ฟังก์ชันนั้นอาจเป็นเวลาพื้นที่ ฯลฯ ของอัลกอริทึมในฐานะที่เป็นฟังก์ชั่นของความยาวอินพุตและโดยทั่วไปในบริบท CS คือเวลา แต่ไม่จำเป็นเลย
Reinstate Monica

23

ฟังก์ชันซีมโทติคคืออะไร เส้นกำกับคืออะไร

รับฟังก์ชั่นf (n)ที่อธิบายจำนวนทรัพยากร (เวลา CPU, RAM, พื้นที่ดิสก์, ฯลฯ ) ที่ใช้โดยอัลกอริทึมเมื่อใช้กับอินพุตขนาดnเราได้กำหนดสัญลักษณ์เชิงสัญลักษณ์สูงสุดสามตัวเพื่ออธิบายประสิทธิภาพสำหรับ ขนาดใหญ่n

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

(หมายเหตุ: ในแง่ที่ใช้ในที่นี้ฟังก์ชัน asymptotic จะอยู่ใกล้กับฟังก์ชันดั้งเดิมหลังจากแก้ไขปัจจัยที่ไม่ใช่ค่าคงที่เท่านั้นเนื่องจากสัญกรณ์ทั้งสาม-O / Θ / Ωขนาดใหญ่ไม่สนใจปัจจัยคงที่นี้จากการพิจารณา)

สัญกรณ์ผูกเส้นกำกับสามเส้นคืออะไรและต่างกันอย่างไร

ทั้งสามใช้สัญกรณ์แบบนี้:

f (n) = O (g (n))

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

สัญกรณ์ Big-ϴ (Theta) ระบุความเสมอภาคในการเติบโตของf (n)ถึงปัจจัยคงที่ (เพิ่มเติมในภายหลัง) มันทำงานคล้ายกับ=ผู้ประกอบการสำหรับอัตราการเติบโต

Big-O สัญกรณ์อธิบายบน -bound ต่อการเจริญเติบโตของf (n) มันทำงานคล้ายกับผู้ประกอบการสำหรับอัตราการเติบโต

Big-Ω (โอเมก้า) สัญกรณ์อธิบายต่ำ -bound ในการเจริญเติบโตของf (n) มันทำงานคล้ายกับผู้ประกอบการสำหรับอัตราการเติบโต

มีสัญลักษณ์เชิงสัญลักษณ์อื่น ๆ อีกมากมายแต่ก็ไม่ได้เกิดขึ้นบ่อยนักในวรรณคดีวิทยาศาสตร์คอมพิวเตอร์

Big-O สัญลักษณ์และตระกูลของมันมักจะเป็นวิธีการเปรียบเทียบที่ซับซ้อนเวลา

ความซับซ้อนของเวลาคืออะไร?

ความซับซ้อนเวลาเป็นระยะแฟนซีสำหรับระยะเวลาที่t (n)จะใช้เวลาสำหรับขั้นตอนในการดำเนินการเป็นหน้าที่ของขนาดการป้อนข้อมูลของn สิ่งนี้สามารถวัดได้ในเวลาจริง (เช่นวินาที) จำนวนคำสั่งซีพียู ฯลฯ โดยปกติมันจะสันนิษฐานว่าอัลกอริทึมจะทำงานบนคอมพิวเตอร์สถาปัตยกรรม von Neumannของคุณทุกวัน แต่แน่นอนคุณสามารถใช้ความซับซ้อนของเวลาเพื่อพูดคุยเกี่ยวกับระบบคอมพิวเตอร์ที่แปลกใหม่มากขึ้นซึ่งสิ่งต่าง ๆ อาจแตกต่างกัน!

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

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

กำลังคำนวณ Big-ϴ

การคำนวณ Big-ϴ ของอัลกอริทึมเป็นหัวข้อที่สามารถเติมตำราเรียนขนาดเล็กหรือประมาณครึ่งภาคการศึกษาระดับปริญญาตรี: ส่วนนี้จะครอบคลุมพื้นฐาน

รับฟังก์ชั่นf (n)ใน pseudocode:

int f(n) {
  int x = 0;
  for (int i = 1 to n) {
    for (int j = 1 to n) {
      ++x;
    }
  }
  return x;
}

ความซับซ้อนของเวลาคืออะไร?

ลูปด้านนอกรันnครั้ง สำหรับแต่ละครั้งที่วงรอบด้านนอกทำงานวงด้านในจะทำงานnครั้ง ทำให้เวลานี้ทำงานที่T (n) = n 2

พิจารณาฟังก์ชั่นที่สอง:

int g(n) {
  int x = 0;
  for (int k = 1 to 2) {
    for (int i = 1 to n) {
      for (int j = 1 to n) {
        ++x;
      }
    }
  }
  return x;
}

ลูปด้านนอกรันสองครั้ง วงกลางทำงานnครั้ง สำหรับแต่ละครั้งที่วงกลางทำงานวงด้านในจะทำงานnครั้ง ทำให้เวลานี้ทำงานที่T (n) = 2n 2

ตอนนี้คำถามคือสิ่งที่เป็นเชิงเวลาการทำงานของฟังก์ชั่นทั้งสอง?

ในการคำนวณสิ่งนี้เราดำเนินการสองขั้นตอน:

  • ลบค่าคงที่ เมื่ออัลกอริธึมเพิ่มขึ้นเนื่องจากอินพุทคำอื่น ๆ จะควบคุมเวลาทำงานทำให้ไม่สำคัญ
  • ลบทั้งหมดยกเว้นคำที่ใหญ่ที่สุด ในฐานะที่เป็นnไปที่อินฟินิตี้, n 2อย่างรวดเร็วแซงหน้าn

พวกเขาที่สำคัญที่นี่คือการมุ่งเน้นในแง่ที่โดดเด่นและลดความซับซ้อนในการคำเหล่านั้น

T (n) = n 2 ∈ ϴ (n 2 )
T (n) = 2n 2 ∈ ϴ (n 2 )

หากเรามีอัลกอริทึมอื่นที่มีหลายคำเราจะทำให้มันง่ายขึ้นโดยใช้กฎเดียวกัน:

T (n) = 2n 2 + 4n + 7 ∈ ϴ (n 2 )

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

กำลังคำนวณ Big-Ωและ Big-O

ก่อนอื่นให้เตือนว่าในวรรณกรรมที่ไม่เป็นทางการ “ Big-O” มักจะถูกใช้เป็นคำพ้องสำหรับ Big-perhaps อาจเป็นเพราะตัวอักษรกรีกเป็นเรื่องยากที่จะพิมพ์ ดังนั้นหากมีคนออกมาจากสีน้ำเงินขอให้คุณใช้ Big-O ของอัลกอริทึมพวกเขาอาจต้องการ Big-Θ

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

สำหรับอัลกอริทึมที่มีT (n) ∈ ϴ (n 2 )รายการใด ๆ ต่อไปนี้เป็นข้อความที่ถูกต้องอย่างเป็นทางการที่จะต้องทำ:

  • T (n) ∈ O (n 2 )
  • T (n) ∈ O (n 3 )
  • T (n) ∈ O (n 5 )
  • T (n) ∈ O (n 12345 × e n )
  • T (n) ∈Ω (n 2 )
  • T (n) ∈Ω (n)
  • T (n) ∈Ω (บันทึก (n))
  • T (n) ∈Ω (บันทึก (บันทึก (n)))
  • T (n) ∈Ω (1)

แต่มันก็ไม่ถูกต้องไปยังรัฐT (n) ∈ O (n)หรือT (n) ∈Ω (n 3 )

ความซับซ้อนสัมพัทธ์คืออะไร? มีอัลกอริทึมใดบ้าง

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

คลาสของอัลกอริทึมแยกย่อยดังนี้:

  • Θ (1) - คงที่ ตัวอย่างเช่นการเลือกหมายเลขแรกในรายการจะใช้เวลาเท่ากันเสมอ

  • Θ (n) - เป็นเส้นตรง ยกตัวอย่างเช่นการทำซ้ำรายการมักจะใช้เวลาสัดส่วนกับขนาดของรายการที่ n

  • Θ (log (n)) - ลอการิทึม (ฐานปกติไม่สำคัญ) อัลกอริทึมที่แบ่งพื้นที่อินพุตในแต่ละขั้นตอนเช่นการค้นหาแบบไบนารีเป็นตัวอย่าง

  • Θ (n × log (n)) - linear time ลอการิทึม (“ linearithmic”) อัลกอริทึมเหล่านี้มักจะแบ่งและพิชิต ( log (n) ) ในขณะที่ยังคงวนซ้ำ ( n ) อินพุตทั้งหมด อัลกอริทึมการเรียงลำดับยอดนิยมจำนวนมาก (ผสานเรียงลำดับ Timsort) ตกอยู่ในหมวดหมู่นี้

  • Θ (n m ) - พหุนาม ( nยกเป็นmคงที่ใด ๆ) นี่เป็นคลาสความซับซ้อนที่พบบ่อยมากซึ่งมักพบในลูปซ้อนกัน

  • Θ (m n ) - เอ็กซ์โพเนนเชียล (ค่าคงที่mยกเป็นn ) อัลกอริทึมแบบเรียกซ้ำและกราฟจำนวนมากอยู่ในหมวดหมู่นี้

  • Θ (n!) - แฟกทอเรียล กราฟและอัลกอริธึม combinatorial มีความซับซ้อนของปัจจัย

สิ่งนี้เกี่ยวข้องกับกรณีที่ดีที่สุด / ปานกลาง / แย่ที่สุดหรือไม่?

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

เพื่อพูดคุยเกี่ยวกับ Big-O ของอัลกอริทึมเราจะต้องผูกมัดกับโมเดลทางคณิตศาสตร์เฉพาะของอัลกอริทึมด้วยพารามิเตอร์ตัวเดียวnซึ่งควรจะอธิบาย“ ขนาด” ของอินพุทไม่ว่าอะไรจะมีประโยชน์ก็ตาม แต่ในโลกแห่งความเป็นจริงปัจจัยการผลิตมีโครงสร้างมากกว่าความยาวของพวกเขา ถ้าเรื่องนี้เป็นขั้นตอนวิธีการเรียงลำดับการที่ฉันสามารถกินอาหารในสตริง"abcdef", หรือ"fedcba" "dbafce"ทั้งหมดของพวกเขามีความยาว 6 แต่หนึ่งในนั้นถูกจัดเรียงแล้วหนึ่งถูกกลับรายการและสุดท้ายเป็นเพียงความสับสนแบบสุ่ม อัลกอริทึมการเรียงลำดับบางอย่าง (เช่น Timsort) ทำงานได้ดีขึ้นหากอินพุตถูกเรียงลำดับแล้ว แต่เราจะรวมเอาความไร้มนุษยธรรมนี้เข้ากับแบบจำลองทางคณิตศาสตร์ได้อย่างไร

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

แต่ถ้าคุณกังวลเกี่ยวกับการโจมตีแบบปฏิเสธการให้บริการคุณอาจต้องมองโลกในแง่ร้ายมากกว่า ในกรณีนี้มันปลอดภัยกว่าที่จะสมมติว่าอินพุตเพียงอย่างเดียวคือสิ่งที่ทำให้เกิดความเศร้าโศกมากที่สุดสำหรับอัลกอริทึมของคุณ นี้จะช่วยให้คุณมีความเลวร้ายที่สุดกรณีรูปแบบความซับซ้อนของขั้นตอนวิธี หลังจากนั้นคุณสามารถพูดคุยเกี่ยวกับ Big-O / Θ / Ω ฯลฯ ของโมเดลที่แย่ที่สุด

ในทำนองเดียวกันคุณยังสามารถมุ่งเน้นความสนใจไปยังอินพุตเฉพาะที่อัลกอริทึมของคุณมีปัญหาน้อยที่สุดในการเข้าถึงโมเดลที่ดีที่สุดจากนั้นดู Big-O / Θ / Ωเป็นต้น


นี่เป็นคำตอบที่ดี แต่ Big-O และ Big-Ωมีส่วนเกี่ยวข้องกับกรณีที่แย่ที่สุดและดีที่สุด มันเป็นขอบเขตบนและล่าง แต่ทั้งคู่สามารถใช้กับกรณีใดกรณีหนึ่งเช่นการเรียงลำดับการแทรกมีในกรณีที่ดีที่สุดเวลาที่ซับซ้อนของϴ(n)(ทั้ง Big-O และ Big-Ω) ขณะที่มีในกรณีที่แย่ที่สุด ความซับซ้อนของเวลาϴ(n²)(ทั้ง Big-O และ Big-Ω)
Paul

นอกจากนี้อัลกอริทึมใด ๆ ที่ไม่รวมอัลกอริทึมว่างอยู่Ω(1)ในกรณีที่ดีที่สุดเลวร้ายที่สุดและโดยเฉลี่ย แต่นั่นเป็นเพราะนั่นคือขอบเขตที่ต่ำกว่าและไม่มีอะไรเกี่ยวข้องกับกรณีที่ดีที่สุดของอัลกอริทึม
Paul

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

@ ย้อนกลับหากคุณคิดว่าคุณสามารถอธิบายได้ดีขึ้นแล้วไปข้างหน้า คุณรู้หรือไม่ว่านี่คือคำตอบของวิกิชุมชนใช่มั้ย

"ก่อนอื่นได้รับการเตือนว่าในวรรณกรรมที่ไม่เป็นทางการ" Big-O "มักถูกใช้เป็นคำเหมือนสำหรับ Big-Θ" -> ไม่เพียง แต่ในวรรณคดีนอกระบบ ภาคเรียนแรกของฉันในความซับซ้อน, กลับไปที่วิทยาลัย, สอนเราเกี่ยวกับคำจำกัดความของ Big-O ราวกับว่าเป็น Big-Θ (หนังสือเรียนของเราใช้คำจำกัดความนั้น) มันทำให้ฉันสับสนเมื่อฉันไปที่ Complexity II และฉันพบว่าทั้งสองนั้นไม่เหมือนกัน
T. Sar - Reinstate Monica
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.