มีอัลกอริธึมในโลกแห่งความเป็นจริงที่มีประสิทธิภาพสูงกว่าในชั้นเรียนด้านล่างหรือไม่? [ปิด]


39

เมื่อคืนฉันพูดคุยกับโปรแกรมเมอร์คนอื่นว่าถึงแม้บางอย่างอาจเป็น O (1) การดำเนินการที่เป็น O (n) อาจเหนือกว่าถ้ามีค่าคงที่ขนาดใหญ่ในอัลกอริทึม O (1) เขาไม่เห็นด้วยดังนั้นฉันจึงนำมันมาที่นี่

มีตัวอย่างของอัลกอริทึมที่มีประสิทธิภาพสูงกว่าในคลาสด้านล่างหรือไม่? ตัวอย่างเช่น O (n) เร็วกว่า O (1) หรือ O (n 2 ) เร็วกว่า O (n)

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


15
แม้แต่อัลกอริธึม "ใหญ่" แต่ขนาดเล็กก็ไม่จำเป็น ตัวอย่างเช่นการกำจัด gaussian คือ O (n ^ 3) แต่มีอัลกอริธึมที่สามารถทำได้ใน O (n ^ 2) แต่สัมประสิทธิ์สำหรับอัลโกกำลังสองนั้นใหญ่มากจนผู้คนไปกับ O (n ^ 3) หนึ่ง
BlackJack

11
คุณต้องเพิ่ม "... สำหรับปัญหาในโลกแห่งความเป็นจริง" หรือบางอย่างเพื่อทำให้เป็นคำถามที่สมเหตุสมผล มิฉะนั้นคุณจะต้องทำให้nใหญ่พอที่จะชดเชยค่าคงที่ (ซึ่งเป็นจุดสัญกรณ์ใหญ่ -O)
starblue

8
อย่าใช้สัญลักษณ์ใหญ่เพื่อความเร็ว
Codism

16
จุดสำคัญของสัญกรณ์ -O ใหญ่ไม่ใช่เพื่อบอกให้คุณรู้ว่าอัลกอริทึมทำงานเร็วแค่ไหน แต่มันปรับขนาดได้ดีแค่ไหน
BlueRaja - Danny Pflughoeft

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

คำตอบ:


45

การค้นหาในตารางข้อมูลคงที่น้อยมาก ตารางแฮชที่ได้รับการปรับให้เหมาะสมอาจเป็น O (1) และยังช้ากว่าการค้นหาแบบไบนารีหรือแม้แต่การค้นหาแบบเชิงเส้นเนื่องจากค่าใช้จ่ายในการคำนวณแฮช


14
การค้นหา hashtable ที่แม่นยำยิ่งขึ้นคือ O (m) โดยที่ m คือขนาดของคีย์ คุณจะเรียกมันว่า O (1) เท่านั้นถ้าขนาดของคีย์คงที่ นอกจากนี้โดยปกติแล้วจะถูกตัดจำหน่าย - มิฉะนั้นตารางจะไม่สามารถขยาย / ลดขนาดได้ ต้นไม้ Ternary สามารถเอาชนะตารางแฮชเพื่อค้นหาสตริงในบริบทที่ไม่พบสตริงบ่อยนักการค้นหาต้นไม้ที่พบบ่อยจะพบว่าไม่มีคีย์ในขณะที่ยังคงตรวจสอบอักขระตัวแรกหรือสองตัวของสตริง รุ่น hashtable ยังไม่ได้คำนวณการแฮช
Steve314

2
ฉันชอบคำตอบของ Loren Pechtel และความคิดเห็นแรกของ Steve314 ฉันเคยเห็นสิ่งนี้เกิดขึ้นจริง หากคุณสร้างคลาส Java ที่มีเมธอดแฮชโค้ด () ซึ่งใช้เวลานานเกินไปในการส่งคืนค่าแฮช (และไม่สามารถ / ไม่สามารถแคช) ดังนั้นให้ใช้อินสแตนซ์ของคลาสดังกล่าวในคอลเลกชันแฮช (เช่น HashSet) จะทำให้คอลเลกชันนั้นช้ากว่าคอลเลกชันประเภทอาร์เรย์ (เช่น ArrayList)
Shivan Dragon

1
@ Steve314: ทำไมคุณถึงคิดว่าฟังก์ชั่นแฮชคือ O (m) โดยที่ m คือขนาดของคีย์? ฟังก์ชันแฮชสามารถเป็น O (1) แม้ว่าคุณจะจัดการกับสตริง (หรือประเภทที่ซับซ้อนอื่น ๆ ) ไม่มีค่ามากเกินไปที่จะใส่ลงในคำจำกัดความที่เป็นทางการมากกว่าเพียงแค่ตระหนักว่าฟังก์ชั่นแฮชสามารถเปลี่ยนความซับซ้อนได้อย่างมากหากเลือกโครงสร้างข้อมูลที่ไม่ถูกต้อง (ตารางแฮช) สำหรับอินพุตของคุณ (ขนาดคีย์ไม่แน่นอน)
Codism

1
@ Steve314: โปรดทราบว่าฉันพูดตารางข้อมูลคงที่ พวกมันไม่เติบโต นอกจากนี้คุณจะได้รับประสิทธิภาพ O (1) จากตารางแฮชเท่านั้นหากคุณสามารถเพิ่มประสิทธิภาพคีย์เพื่อให้แน่ใจว่าไม่มีการชนกัน
Loren Pechtel

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

25

การคูณเมทริกซ์ อัลกอริทึมnaïve O (n ^ 3) มักใช้ในทางปฏิบัติเร็วกว่าของ O Strassen O (n ^ 2.8) สำหรับเมทริกซ์ขนาดเล็ก ish; และ Strassen's ถูกใช้แทน O (n ^ 2.3) Coppersmith – Winograd อัลกอริทึมสำหรับเมทริกซ์ขนาดใหญ่



2
Coppersmith-Winograd ไม่เคยถูกใช้ การนำไปใช้นั้นจะเป็นงานที่น่าสยดสยองในตัวเองและค่าคงที่แย่มากจนไม่สามารถทำได้แม้จะเป็นปัญหาเมทริกซ์ทางวิทยาศาสตร์ที่ทันสมัย
tskuzzy

24

ตัวอย่างง่ายๆคือความแตกต่างระหว่างอัลกอริทึมการเรียงลำดับ mergesort, heapsort และอื่น ๆ บางคนเป็นO (n log n) Quicksort เป็นกรณีที่แย่ที่สุดO (n ^ 2) แต่บ่อยครั้งที่ Quicksort เป็นเร็วขึ้นและในความเป็นจริงจะดำเนินการโดยเฉลี่ยเช่นO (n log n) ข้อมูลเพิ่มเติม

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

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


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

ฟีโบนักชีอันดับหนึ่งปิดตัวเล็กน้อย ขนาดเอาต์พุตเป็นเอ็กซ์โพเนนเชียลในขนาดอินพุตดังนั้นจึงเป็นความแตกต่างระหว่าง O (lg n * e ^ n) เทียบกับ O (lg lg n * e ^ n)
Peter Taylor

ภาคผนวก: ที่ดีที่สุด อัลกอริทึมที่ใช้เมทริกซ์ทำการคูณกับตัวเลขตามลำดับ 1.5 ^ n ดังนั้น O (lg lg n * ne ^ n) อาจเป็นขอบเขตที่ดีที่สุดที่พิสูจน์ได้
Peter Taylor

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

(2) เป็นประเภทของการพิจารณาจากภายนอกที่ต้องนำมาพิจารณาเมื่อดูประสิทธิภาพการทำงานของบิ๊กโอ อัลกอริทึม Mergesort ควรมีประสิทธิภาพเหนือกว่า Quicksort เสมอแต่การใช้ทรัพยากรและตำแหน่งในแคชโดยทั่วไปจะกลับตำแหน่งที่แท้จริงของโลก
Dan Lyons

18

หมายเหตุ: โปรดอ่านความคิดเห็นโดย @ back2dos ด้านล่างและกูรูอื่น ๆ เนื่องจากพวกเขามีประโยชน์มากกว่าที่ฉันเขียน - ขอบคุณสำหรับผู้มีส่วนร่วมทุกคน

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

pic-1


6
คำถามนี้ต้องการตัวอย่างอัลกอริทึมที่เฉพาะเจาะจง สิ่งนี้ไม่ได้มีอยู่ตามที่ควรจะเป็น
Megan Walker

19
คุณไม่เห็นอะไรบนกราฟนั้นซึ่งจะตอบคำถาม มันทำให้เข้าใจผิด กราฟนี้เพียงแปลงฟังก์ชั่นy = 1, y = log xและอื่น ๆ และจุดตัดของy = 1และเป็นจริงจุดy = x (1,1)ถ้าสิ่งนี้ถูกต้องจริง ๆ แล้วมันจะบอกคุณว่าอัลกอริธึมของความซับซ้อนที่สูงกว่านั้นสามารถเร็วกว่าสำหรับรายการที่ 0 ถึง 2 ซึ่งเป็นสิ่งที่คนแทบจะไม่สนใจ สิ่งที่กราฟไม่สามารถนำมาพิจารณาได้อย่างสมบูรณ์ (และความแตกต่างของประสิทธิภาพการรับรู้ที่เป็นปัญหามาจากอะไร) คือปัจจัยคงที่
back2dos

@ Samuel Walker ขอบคุณสำหรับความคิดเห็น ลิงค์ที่มีให้ (Link-1) มีตัวอย่างของอัลกอริทึมต่อหมวดหมู่
NoChance

5
@ back2dos: กราฟของมันไม่ตอบคำถาม แต่สามารถใช้เพื่อตอบคำถามได้ รูปร่างของแต่ละฟังก์ชั่นที่แสดงนั้นเหมือนกันสำหรับขนาดและค่าคงที่ใด ๆ ด้วยกราฟนี้แสดงให้เห็นว่าการรวมกันของฟังก์ชั่นมีช่วงของอินพุตที่หนึ่งมีขนาดเล็กและช่วงของอินพุตที่อื่น ๆ คือ
Jan Hudec

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

11

สำหรับค่าจริงของnใช่ สิ่งนี้เกิดขึ้นมากมายในทฤษฎี CS บ่อยครั้งที่มีอัลกอริทึมที่ซับซ้อนซึ่งมีประสิทธิภาพการทำงานที่ดีกว่าโอ้ แต่ปัจจัยคงที่มีขนาดใหญ่มากจนทำให้ไม่สามารถทำได้

ครั้งหนึ่งฉันเคยใช้รูปทรงเรขาคณิตคำนวณศาสตราจารย์อธิบายถึงอัลกอริธึมสำหรับการคำนวณรูปหลายเหลี่ยมในเวลาเชิงเส้น แต่เขาก็จบด้วย "ซับซ้อนมากฉันไม่คิดว่าจะมีใครนำไปใช้จริง" (!!)

นอกจากนี้กอง fibonacci มีลักษณะดีกว่ากองปกติ แต่ไม่เป็นที่นิยมมากเพราะพวกเขาไม่ได้ดำเนินการเช่นเดียวกับในทางปฏิบัติเป็นประจำกอง สิ่งนี้สามารถเรียงซ้อนกับอัลกอริธึมอื่น ๆ ที่ใช้ฮีป - ตัวอย่างเช่นเส้นทางที่สั้นที่สุดของ Dijkstra นั้นเร็วกว่าในทางคณิตศาสตร์ด้วยฟีโบนัชชีฮีป แต่โดยทั่วไปแล้วไม่ใช่ในทางปฏิบัติ


มันเร็วกว่าสำหรับกราฟขนาดใหญ่ตามลำดับยอดประมาณ 100,000 จุด
tskuzzy

Fibonacci heaps เป็นความคิดแรกของฉัน (อันที่จริงที่สอง) เช่นกัน
Konrad Rudolph

10

เปรียบเทียบการแทรกลงในรายการที่เชื่อมโยงและแทรกลงในอาร์เรย์ที่ปรับขนาดได้

จำนวนของข้อมูลจะต้องมีขนาดใหญ่พอสมควรสำหรับการแทรกรายการ O (1) ที่เชื่อมโยงให้คุ้มค่า

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


1
อาร์เรย์ที่ปรับขนาดได้จะเพิ่มเป็นสองเท่าในแต่ละครั้งที่เติมดังนั้นค่าเฉลี่ยของการปรับขนาดต่อการแทรกคือ O (1)
วินไคลน์

2
@ kevincline ใช่ แต่ O (n) มาจากการย้ายองค์ประกอบทั้งหมดหลังจากจุดแทรกไปข้างหน้า การจัดสรรจะถูกตัดจำหน่าย O (1) เวลา ประเด็นของฉันคือการเคลื่อนไหวนั้นยังเร็วมากดังนั้นในทางปฏิบัติมักจะเป็นรายการที่เชื่อมโยง
Winston Ewert

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

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

@jgmjgm หากคุณแทรกเข้าไปตรงกลางของอาร์เรย์ที่ปรับขนาดได้มันจะคัดลอกองค์ประกอบอย่างแน่นอนหลังจากนั้น
Winston Ewert

8

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

สัญลักษณ์ทั่วไป:

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

O (n) - จำนวนการวนซ้ำเพิ่มขึ้นในสัดส่วนเชิงเส้นตามขนาดของอินพุต ความหมาย - หากอัลกอริทึมวนซ้ำผ่านอินพุต N, 2 * N เท่าใดก็จะถือว่าเป็น O (n)

O (n ^ 2) (กำลังสอง) - จำนวนการวนซ้ำคือขนาดอินพุตกำลังสอง


2
ในการเพิ่มตัวอย่างให้กับคำตอบที่ดีเลิศ: วิธีการ O (1) อาจใช้เวลา 37 ปีต่อการโทรในขณะที่วิธีการ O (n) อาจใช้เวลา 16 * n ไมโครวินาทีต่อการโทร ไหนเร็วกว่ากัน
Kaz Dragon

16
ฉันล้มเหลวอย่างสิ้นเชิงที่จะเห็นว่าสิ่งนี้ตอบคำถามได้อย่างไร
avakar

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

เมื่อคุณใส่คำถามในรูปแบบ "มีตัวอย่าง ... " บางคนย่อมต้องตอบว่า "ใช่" โดยไม่ต้องให้ใด ๆ
rakslice

1
@rakslice: อาจจะเป็นเช่นนั้น อย่างไรก็ตามไซต์นี้ต้องการคำอธิบาย (หรือดีกว่ายังพิสูจน์) ของข้อความใด ๆ ที่คุณทำ ตอนนี้วิธีที่ดีที่สุดที่จะพิสูจน์ว่ามีตัวอย่างดังกล่าวคือการให้หนึ่ง;)
back2dos

6

ห้องสมุด regex มักจะมีการดำเนินการที่จะทำย้อนรอยซึ่งมีกรณีที่เลวร้ายเวลาชี้แจงมากกว่ารุ่น DFA O(nm)ซึ่งมีความซับซ้อนของ

การย้อนรอยแบบไร้เดียงสาสามารถเป็นนักแสดงที่ดีกว่าเมื่ออินพุตอยู่บนเส้นทางที่เร็วหรือล้มเหลวโดยไม่จำเป็นต้องย้อนรอยมากเกินไป

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


ฉันคิดว่ามันเป็นส่วนหนึ่งในประวัติศาสตร์ - อัลกอริทึมสำหรับการเปลี่ยนนิพจน์ทั่วไปให้เป็น DFA นั้นได้รับการจดสิทธิบัตรเมื่อเครื่องมือก่อนหน้านี้บางส่วน (sed และ grep ฉันเดา) กำลังได้รับการพัฒนา แน่นอนฉันได้ยินสิ่งนี้จากอาจารย์ผู้เรียบเรียงของฉันที่ไม่แน่ใจทั้งหมดดังนั้นนี่เป็นบัญชีมือสอง
Tikhon Jelvis

5

O(1)ขั้นตอนวิธีการ:

def constant_time_algorithm
  one_million = 1000 * 1000
  sleep(one_million) # seconds
end

O(n)ขั้นตอนวิธีการ:

def linear_time_algorithm(n)
  sleep(n) # seconds
end

เห็นได้ชัดว่าสำหรับค่าใด ๆnที่n < one_millionในO(n)ขั้นตอนวิธีการที่กำหนดในตัวอย่างจะได้เร็วขึ้นกว่าO(1)อัลกอริทึม

ในขณะที่ตัวอย่างนี้ค่อนข้างน่ากลัว แต่ก็เทียบเท่ากับวิญญาณต่อไปนี้เป็นตัวอย่าง:

def constant_time_algorithm
  do_a_truckload_of_work_that_takes_forever_and_a_day
end

def linear_time_algorithm(n)
  i = 0
  while i < n
    i += 1
    do_a_minute_amount_of_work_that_takes_nanoseconds
  end
end

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

มิฉะนั้นคุณจะต้องเกณฑ์มาตรฐานทั้งสองขั้นตอนวิธีการที่มีค่าของnในช่วงที่คาดหวังเพื่อที่จะกำหนดposterioriขั้นตอนวิธีจบลงด้วยการได้เร็วขึ้น


4

เรียงลำดับ:

การเรียงลำดับการแทรกคือ O (n ^ 2) แต่มีประสิทธิภาพสูงกว่าอัลกอริทึมการเรียงลำดับ O (n * log (n)) อื่น ๆ สำหรับองค์ประกอบจำนวนน้อย

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

ดูTimsortการใช้งานเริ่มต้นปัจจุบันของการเรียงลำดับ Python และ Java 7 ที่ใช้เทคนิคนี้


4

ผสมผสานขั้นตอนวิธีการใช้ในการปฏิบัติคือการชี้แจงในกรณีที่เลวร้ายที่สุดสำหรับปัจจัยการผลิตทางพยาธิวิทยาบาง

มีอัลกอริทึมการรวมพหุนามแต่มันช้าเกินไปในทางปฏิบัติ


3

Bubblesort ในหน่วยความจำสามารถทำได้ดีกว่า quicksort เมื่อโปรแกรมถูกสลับไปยังดิสก์หรือจำเป็นต้องอ่านทุกรายการจากดิสก์เมื่อเปรียบเทียบ

นี่ควรเป็นตัวอย่างที่เขาสามารถเกี่ยวข้องได้


ความซับซ้อนที่ยกมาใน quicksort และ bubbleort ไม่ถือว่า O (1) การเข้าถึงหน่วยความจำแบบสุ่มหรือไม่? หากไม่มีกรณีนี้อีกต่อไปคุณจะไม่ต้องตรวจสอบความซับซ้อนอีกครั้งอย่างรวดเร็วหรือไม่
Viktor Dahl

@ViktorDahl เวลาเข้าถึงรายการไม่ได้เป็นส่วนหนึ่งของสิ่งที่ถูกวัดแบบดั้งเดิมในความซับซ้อนของอัลกอริทึมการเรียงลำดับดังนั้น "O (1)" ไม่ใช่ตัวเลือกที่ถูกต้องของคำที่นี่ ใช้ "เวลาคงที่" แทน PHK เขียนบทความย้อนหลังเกี่ยวกับอัลกอริธึมการเรียงลำดับซึ่งรู้ว่าบางรายการมีราคาแพงกว่าการเรียกคืน (อื่น ๆ หน่วยความจำเสมือน) - que.acm.org/detail.cfm?id=1814327 - คุณอาจพบว่ามันน่าสนใจ

ฉันเห็นความผิดพลาดของฉันตอนนี้ โดยปกติแล้วจะวัดจำนวนการเปรียบเทียบและแน่นอนว่าไม่ได้รับผลกระทบจากความเร็วของสื่อบันทึกข้อมูล นอกจากนี้ขอขอบคุณสำหรับลิงค์
Viktor Dahl

3

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

ตัวอย่างเช่น: การค้นหาแบบไบนารีและการค้นหาตารางแฮชจะเร็วกว่ามากต่อการค้นหาจากนั้นเป็นการค้นหาแบบเชิงเส้น แต่ต้องการให้คุณเรียงลำดับรายการหรือสร้างตารางแฮชตามลำดับ

การเรียงลำดับจะทำให้คุณเสียค่าใช้จ่าย N log (N) และตารางแฮชจะมีค่าใช้จ่ายอย่างน้อย N ตอนนี้ถ้าคุณกำลังทำการค้นหาหลายร้อยหรือหลายพันการค้นหา แต่ถ้าคุณต้องการค้นหาเพียงหนึ่งหรือสองครั้งมันอาจสมเหตุสมผลที่จะทำการค้นหาเชิงเส้นและประหยัดต้นทุนเริ่มต้น


1

การถอดรหัสมักจะเป็น 0 (1) ตัวอย่างเช่นพื้นที่ที่สำคัญสำหรับ DES คือ 2 ^ 56 ดังนั้นการถอดรหัสข้อความใด ๆ เป็นการดำเนินการเวลาคงที่ เป็นเพียงว่าคุณมีปัจจัย 2 ^ 56 อยู่ในนั้นดังนั้นมันคงที่ใหญ่มาก


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

คุณอาจหมายถึงการเข้ารหัสแบบเข้ารหัสแทนที่จะถอดรหัส?
leftaroundabout

3
ใช่มีหลายสิ่งหลายอย่างที่คุณสามารถทำให้เป็นค่าคงที่และประกาศอัลกอริทึมให้เป็น O (1) [การเรียงลำดับโดยนัยถือว่าองค์ประกอบใช้เวลาในการเปรียบเทียบอย่างคงที่เช่นหรือคณิตศาสตร์ใด ๆ ที่มีตัวเลขที่ไม่ใช่
บิกตัม

1

การใช้งานที่แตกต่างกันของชุดฤดูใบไม้ผลิในใจของฉัน หนึ่งในความไร้เดียงสาที่สุดคือการนำมันไปใช้กับเวกเตอร์ซึ่งมีความหมายremoveเช่นกันcontainsและดังนั้นจึงaddใช้ O (N) ด้วย
อีกทางเลือกหนึ่งคือนำไปใช้กับแฮชของวัตถุประสงค์ทั่วไปซึ่งจะแมปแฮชอินพุตกับค่าอินพุต ดังกล่าวดำเนินการการดำเนินงานชุดกับ O (1) สำหรับadd, และcontainsremove

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

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

คุณไม่สามารถรู้ได้อย่างรวดเร็วว่ามีอะไรอยู่ในสถานการณ์โลกแห่งความเป็นจริงจนกว่าคุณจะนำมันมาเป็นหนึ่งเดียว บ่อยครั้งที่ผลลัพธ์เป็นสิ่งที่น่าประหลาดใจ (อย่างน้อยสำหรับฉัน)


1

ใช่สำหรับขนาดเล็กที่เหมาะสม N จะมี N ด้านบนซึ่งคุณจะมีลำดับ O (1) <O (lg N) <O (N) <O (N log N) <O (N ^ c ) <O (c ^ N) (โดยที่ O (1) <O (lg N) หมายความว่าที่อัลกอริทึม O (1) จะทำงานน้อยลงเมื่อ N มีขนาดใหญ่พอสมควรและ c เป็นค่าคงที่คงที่ที่มากกว่า 1 )

สมมติว่าอัลกอริทึมเฉพาะ O (1) ใช้การดำเนินงาน f (N) = 10 ^ 100 (a googol) อย่างแน่นอนและอัลกอริทึม O (N) ใช้ g (N) = 2 N + 5 การดำเนินการทุกประการ อัลกอริทึม O (N) จะให้ประสิทธิภาพที่ดีกว่าจนกว่าคุณ N จะเป็น googol (โดยทั่วไปเมื่อ N> (10 ^ 100 - 5) / 2) ดังนั้นหากคุณคาดหวังว่า N จะอยู่ในช่วง 1,000 ถึงพันล้านคุณ จะได้รับโทษอย่างรุนแรงโดยใช้อัลกอริทึม O (1)

หรือสำหรับการเปรียบเทียบที่เหมือนจริงสมมติว่าคุณกำลังคูณตัวเลข n หลักด้วยกัน Karatsuba อัลกอริทึมที่มากที่สุด 3 n ^ (LG 3) การดำเนินงาน (นั่นคือประมาณ O (n ^ 1.585)) ในขณะที่ขั้นตอนวิธี schonhage-strassenเป็น O (n log n log log n) ซึ่งเป็นคำสั่งซื้อได้เร็วขึ้นแต่จะอ้าง วิกิพีเดีย:

ในทางปฏิบัติอัลกอริธึมSchönhage – Strassen เริ่มมีประสิทธิภาพสูงกว่าวิธีเก่าเช่น Karatsuba และ Toom – Cook การคูณสำหรับตัวเลขที่เกิน 2 ^ 2 ^ 15 ถึง 2 ^ 2 ^ 17 (10,000 ถึง 40,000 ทศนิยม) [4] [5] [6] ]

ดังนั้นหากคุณคูณตัวเลข 500 หลักด้วยกันมันไม่สมเหตุสมผลเลยที่จะใช้อัลกอริธึมที่ "เร็วขึ้น" โดยอาร์กิวเมนต์ O ขนาดใหญ่

แก้ไข: คุณสามารถค้นหา f (N) เปรียบเทียบ g (N), โดยการ จำกัด N-> อนันต์ของ f (N) / g (N) หากขีด จำกัด คือ 0 ดังนั้น f (N) <g (N), ถ้าขีด จำกัด นั้นไม่มีที่สิ้นสุดดังนั้น f (N)> g (N), และถ้าขีด จำกัด เป็นค่าคงที่อื่นแล้ว f (N) ~ g (N) ในแง่ของสัญกรณ์ O ใหญ่


1

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

อย่างไรก็ตามในทางปฏิบัติกรณีเลวร้ายที่สุดแบบเอ็กซ์โปเนนเชียลสำหรับวิธี simplex ไม่ได้เกิดขึ้น - วิธี simplex นั้นรวดเร็วและเชื่อถือได้ในขณะที่อัลกอริธึมภายในจุดเริ่มต้นช้าเกินไปที่จะแข่งขัน (ขณะนี้มีอัลกอริธึมจุดตกแต่งภายในที่ทันสมัยกว่าซึ่งสามารถแข่งขันได้ - แต่วิธี simplex ก็เช่นกัน ... )


0

อัลกอริทึมของการสร้างส่วนต่อท้ายของ Ukkonen คือ O (n log n) มันมีข้อดีของการเป็น "ออนไลน์" - นั่นคือคุณสามารถเพิ่มข้อความเพิ่มเติม

เมื่อเร็ว ๆ นี้อัลกอริธึมที่ซับซ้อนกว่านี้อ้างได้ว่าเร็วกว่าในทางปฏิบัติส่วนใหญ่เป็นเพราะการเข้าถึงหน่วยความจำของพวกเขามีตำแหน่งที่สูงกว่า ดูเช่นการสำรวจนี้ซึ่งอ้างว่า 70-80% ของเวลาการประมวลผลใช้เวลารอหน่วยความจำและกระดาษนี้อธิบายอัลกอริทึม "wotd"

คำต่อท้ายพยายามมีความสำคัญในพันธุศาสตร์ (สำหรับการจับคู่ลำดับของยีน) และที่สำคัญน้อยกว่าในการดำเนินการตามพจนานุกรม Scrabble


0

มีอัลกอริทึมที่เร็วที่สุดและสั้นที่สุดเสมอสำหรับปัญหาที่กำหนดไว้อย่างดี มันเป็นเพียงแค่อัลกอริทึมที่เร็วที่สุด

ได้รับรายละเอียดใด ๆ ของปัญหาPและอินสแตนซ์สำหรับปัญหาที่ผมก็ระบุขั้นตอนวิธีการที่เป็นไปได้ทั้งหมดและพิสูจน์Pr , การตรวจสอบแต่ละคู่ดังกล่าวไม่ว่าจะเป็นพีอาร์เป็นหลักฐานที่ถูกต้องที่เป็นอัลกอริทึม asymptotically ที่เร็วที่สุดสำหรับP หากพบหลักฐานดังกล่าวมันก็รันบนผม

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


0

หลายภาษา / กรอบใช้การจับคู่แบบไร้เดียงสาที่จะตรงกับสตริงแทนเคเอ็มพี เรามองหาสตริงเช่น Tom, New York แทนที่จะเป็น ababaabababababababababababab

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