จากความคิดเห็นของฉันเดิม: นี่เป็นเรื่องที่เกี่ยวข้องอย่างใกล้ชิดกับที่แพร่หลายในการประเมินปริมาณผลผลิตทางวิชาการดัชนี Hirsh ที่รู้จักกันดีในฐานะชั่วโมง -index ในระยะสั้นจะถูกกำหนดเป็นจำนวนสิ่งพิมพ์หนึ่งมีเช่นนั้นแต่ละคนมีการอ้างอิงอย่างน้อยh (ใหญ่ที่สุดเช่นh )ชั่วโมงชั่วโมงชั่วโมง
วิธีเดียวที่ปัญหาของคุณแตกต่างคือคุณจะสนใจไม่เพียง แต่ในสิ่งพิมพ์จำนวนมากที่ตรงตามเกณฑ์ แต่ยังรวมถึงสิ่งที่การอ้างอิงของพวกเขามีแต่สิ่งที่เปลี่ยนแปลงเล็กน้อย ข้อมูลมีอยู่แล้วอัลกอริธึมดั้งเดิมลดลง
ดำเนินการโดยทั่วไปการคำนวณค่อนข้างตรงไปตรงมาและเห็นด้วยกับคำตอบของ Karolis Juodelė
อัปเดต:ขึ้นอยู่กับขนาดและลักษณะของข้อมูลของคุณอาจเป็นวิธีการสำรวจที่คุ้มค่าในการเรียงลำดับอาร์เรย์บางส่วนโดยการกรองข้อมูลด้านบนและด้านล่างเป็นจุดสำคัญ จากนั้นขึ้นอยู่กับว่ามีจำนวนน้อยเกินไปหรือมากเกินไปปรับเดือยและทำซ้ำในชุดย่อยที่มีมันเป็นต้น คุณไม่ต้องการคำสั่งซื้อระหว่างองค์ประกอบที่สูงกว่าและไม่แน่นอนระหว่างองค์ประกอบที่ต่ำกว่านั้น ตัวอย่างเช่นเมื่อคุณพบองค์ประกอบทั้งหมดที่มากกว่าหรือเท่ากับh 1และมีน้อยกว่าh 1ขององค์ประกอบเหล่านั้นคุณไม่จำเป็นต้องแตะชุดย่อยนั้นอีกครั้งเพียงเพิ่มเข้าไป สิ่งนี้จะแปลงการเรียกซ้ำที่มีอยู่จริงเป็น quicksort เป็นการเรียกซ้ำแบบหางและสามารถเขียนใหม่เป็นวนซ้ำได้ชั่วโมงชั่วโมง1ชั่วโมง1
Haskell ของฉันเป็นสนิมเล็กน้อย แต่ควรทำสิ่งที่ฉันอธิบายไว้ข้างต้นและดูเหมือนว่าจะทำงาน หวังว่าจะสามารถเข้าใจได้ในระดับหนึ่งฉันยินดีที่จะให้คำอธิบายเพิ่มเติม
-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys
-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
| x == (1 + lGreater + lGranted) = x : merge greater granted
| x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
| otherwise = topImpl greater granted
where smaller = [y | y <- xs, y < x]
greater = [y | y <- xs, y >= x]
lGreater = length greater
lGranted = length granted
-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []
ความคิดคือการรวบรวมในgranted
สิ่งที่คุณรู้ว่าจะมีส่วนร่วมในผลลัพธ์อย่างแน่นอนและจะไม่เรียงลำดับใด ๆ เพิ่มเติม หากgreater
รวมกับชุดเข้าด้วยกันx
เราโชคดีไม่อย่างนั้นเราต้องลองชุดย่อยที่เล็กกว่า (เดือยx
เป็นสิ่งที่เกิดขึ้นเป็นรายการแรกของรายการย่อยที่พิจารณาในปัจจุบัน) โปรดทราบว่าข้อได้เปรียบที่สำคัญในการรับองค์ประกอบที่ใหญ่ที่สุดทีละคือเราทำสิ่งนี้ในบล็อกขนาดเฉลี่ยและไม่จำเป็นต้องจัดเรียงเพิ่มเติมr e m a i n i n g/ 2
ตัวอย่าง:
[1,3,4,1,3,6]
ลองตั้งค่าของคุณ
x = 1
, ,granted = []
greater = [3,4,1,3,6]
ดังนั้นเราถึงกรณีทางพยาธิวิทยาเมื่อเดือยมีขนาดเล็กเกินไป (จริง ๆ แล้วมีขนาดเล็กจนsmaller
ว่างเปล่า) ในขั้นตอนแรก โชคดีที่อัลโกของเราพร้อมแล้ว มันจะละทิ้งx
และลองอีกครั้งโดยgreater
ลำพัง
x = 3
, ,granted = []
greater = [4,3,6]
พวกเขารวมกันเป็นกลุ่มของความยาว 4 แต่เรามีข้อ จำกัด จากด้านล่างด้วย 3 ดังนั้นมันจึงมากเกินไป ทำซ้ำgreater
เพียงอย่างเดียว
x = 4
, ,granted = []
greater = [6]
สิ่งนี้ให้องค์ประกอบจำนวน 2 ชิ้นซึ่งแต่ละอันดูเหมือนว่าเราอาจจะใช้มันเพิ่มอีก smaller = [3]
เก็บนี้และทำซ้ำบน
x = 3
, ,granted = [4,6]
greater = []
สิ่งนี้เข้าด้วยกันให้องค์ประกอบ 3 ชิ้นแต่ละอันดังนั้นเราจึงมีวิธีแก้ปัญหาของเรา[3,4,6]
และเราสามารถกลับมาได้ (โปรดทราบว่าการเรียงสับเปลี่ยนอาจแตกต่างกันไปขึ้นอยู่กับการเรียงลำดับของอินพุต แต่จะมีคำที่เป็นไปได้สูงสุดเสมอไม่เช่น[3,3,6]
หรือ[3,3,4]
เป็นตัวอย่างของคุณ)
(Btw. โปรดทราบว่าการเรียกซ้ำเป็นจริงเพียงแค่ยุบลงในวงจร) ความซับซ้อนค่อนข้างดีกว่า quicksort เนื่องจากการเปรียบเทียบที่บันทึกไว้จำนวนมาก:
n - 1
O ( บันทึกn )O ( n )
nO ( n2)
มีการเปรียบเทียบที่ไม่จำเป็นในโค้ดด้านบนเช่นการคำนวณsmaller
ว่าเราต้องการหรือไม่สามารถลบออกได้อย่างง่ายดาย (ฉันคิดว่าการประเมินที่ขี้เกียจจะดูแลสิ่งนั้น)