การพิจารณาว่าอัลกอริทึมเป็น O (บันทึก n)


25

ฉันรีเฟรช CS Theory ของฉันและฉันต้องการทราบวิธีระบุความซับซ้อนของอัลกอริทึม O (log n) โดยเฉพาะมีวิธีง่าย ๆ ในการระบุหรือไม่

ฉันรู้ด้วย O (n) คุณมักจะมีวงเดียว; O (n ^ 2) เป็นวงคู่ O (n ^ 3) เป็นสามวงเป็นต้นแล้ว O (log n) เป็นอย่างไร


2
stackoverflow.com/questions/749819/…หรือการอ่านที่ยาวมาก ๆ นี้: stackoverflow.com/questions/487258/…
wkl

Ah, นั่นคือที่เดียวที่ฉันไม่ได้ดู :)
Atif

คำตอบ:


32

ฉันรู้ด้วย O (n) คุณมักจะมีวงเดียว; O (n ^ 2) เป็นวงคู่ O (n ^ 3) เป็นสามวงเป็นต้นแล้ว O (log n) เป็นอย่างไร

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

for (i = 0; i < log2(input.count); i++) {
    doSomething(...);
}

ดังนั้นอัลกอริทึมใด ๆ ที่จำนวนของการดำเนินการที่จำเป็นอยู่ในลำดับของลอการิทึมของขนาดของอินพุตคือ O (log n) สิ่งสำคัญที่การวิเคราะห์ big-O บอกคุณว่าเวลาดำเนินการของอัลกอริทึมเปลี่ยนแปลงอย่างไรเมื่อเทียบกับขนาดของอินพุต: ถ้าคุณเพิ่มขนาดของอินพุตเป็นสองเท่าอัลกอริทึมจะใช้เวลาอีก 1 ขั้นตอน (O (log n)) สองขั้นตอนมาก (O (n)) สองเท่าหลายขั้นตอน (O (n ^ 2)) ฯลฯ

มันช่วยให้ทราบได้อย่างไรจากประสบการณ์ว่าอัลกอริทึมที่แบ่งพาร์ติชันอินพุตซ้ำ ๆ มักมี 'log n' เป็นส่วนประกอบของประสิทธิภาพหรือไม่? แน่ใจ แต่อย่ามองหาการแบ่งพาร์ติชันและข้ามไปยังข้อสรุปว่าประสิทธิภาพของอัลกอริทึมคือ O (log n) - อาจเป็นสิ่งที่คล้ายกับ O (n log n) ซึ่งแตกต่างกันมาก


3
โปรดทราบว่าวิธีพูดภาษาอื่น ๆ ที่จะพูดว่า "ในลำดับของลอการิทึมของขนาด" คือการพูดว่า "ในลำดับของจำนวนหลักในขนาด"

@Caleb ฐานจริงของลอการิทึมนั้นไม่สำคัญเมื่อพูดถึงการปรับสเกล

@Caleb การพูดถึงสัมบูรณ์ไม่สมเหตุสมผลกับ big-O ถ้อยคำที่คุณอาจชอบดีกว่า: เมื่อจำนวนหลักสองเท่าจำนวนของขั้นตอนที่สอง

@Caleb การพูดถึงสัมบูรณ์ไม่สมเหตุสมผลกับ big-O ถ้อยคำที่คุณอาจชอบดีกว่า: เมื่อจำนวนหลักสองเท่าจำนวนของขั้นตอนที่สอง

@ ThorbjørnRavnAndersenใช่นั่นคือสิ่งที่ "ลอการิทึมของขนาด" หมายถึง ฉันไม่แน่ใจว่าปัญหาของคุณกับวลีนั้นคืออะไรยกเว้นว่าคุณได้เลือกที่จะพูดให้แตกต่างออกไป พื้นฐานฉันคิดว่าเราเห็นด้วย
แม็กเคเล็บ

25

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

หมายเหตุ: คุณไม่จำเป็นต้องแบ่งเท่า ๆ กัน


1
ถ้าฉันแยกอินพุตเป็นสองครั้งจากนั้นวนซ้ำ 2 ^ (n / 2) ในส่วนที่เหลือก่อนที่จะแยกอีกครั้ง (แน่นอนฉันรู้ว่าแล้วฉันต้องการแสดงตัวอย่างที่วิธีการแบบง่าย ๆ นี้ล้มเหลว)
Tamás Szelei

@afish นั่นเป็นของหายาก มันหายากมากเมื่อค้นหา
Donal Fellows

1
@ DonalFellows ทฤษฎีอัลกอริทึมไม่ใช่วิทยาศาสตร์เชิงประจักษ์ และคำถามก็ไม่ได้เกี่ยวกับการค้นหา แต่เป็นเพียงการกล่าวถึงlog nการตอบสนองการค้นหาทวิภาคในผู้คน
Tamás Szelei

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

@afish: จุดดี เป้าหมายของฉันกับคำตอบนี้คือทำให้มันง่ายที่สุดเท่าที่จะเป็นไปได้ตามลักษณะของคำถาม ฉันเปลี่ยนบรรทัด "คุณแบ่งโครงสร้างครึ่ง ... " เป็น "คุณแบ่งโครงสร้างครึ่ง ... และดำเนินการจำนวนคงที่สำหรับแต่ละการแยก" เพื่อพยายามหาจุดนี้ได้ง่ายๆ
Casey Patton

2

ตัวอย่างทั่วไปคือตัวอย่างที่จัดการกับการค้นหาแบบไบนารี ยกตัวอย่างเช่นการค้นหาแบบทวิภาคO(log n)เป็นปกติ

หากคุณมีแผนภูมิการค้นหาแบบไบนารีการค้นหาการแทรกและการลบนั้นมีO(log n)ความซับซ้อนทั้งหมด

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


1

ถ้าคุณต้องการให้มันง่ายเหมือน "single loop -> O (n), double loop -> O (n ^ 2)" มากกว่าคำตอบน่าจะเป็น "Tree -> O (log n)" การสำรวจต้นไม้อย่างแม่นยำมากขึ้นจากรากหนึ่งไปยังอีกใบหนึ่ง (ไม่ใช่ทั้งหมด!) หรือรอบทางอื่น อย่างไรก็ตามสิ่งเหล่านี้ล้วนเป็นเรื่องง่ายเกินไป


ดังนั้นคำตอบของฉันคืออะไร ฉันเปิดให้วิจารณ์ที่สร้างสรรค์
Scarfridge

0

คุณต้องการทราบว่ามีวิธีง่าย ๆ ในการระบุว่าอัลกอริทึมเป็น O (log N) หรือไม่

ดี: เพียงแค่เรียกใช้และเวลามัน รันสำหรับอินพุต 1.000, 10.000, 100.000 และหนึ่งล้าน

หากคุณเห็นว่าเวลาทำงาน 3,4,5,6 วินาที (หรือหลาย ๆ อย่าง) คุณสามารถพูดได้อย่างปลอดภัยว่ามันเป็น O (บันทึก N) หากมันเป็นเช่น: 1,10,100,1000 วินาทีก็อาจเป็น O (N) และถ้ามันเป็นเช่น 3,40,500,6000 วินาทีมันก็จะเป็น O (N log N)


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