วิธีการค้นหาชุดสูงสุดขององค์ประกอบของอาร์เรย์เช่นว่าทุกองค์ประกอบในมากกว่าหรือเท่ากับ cardinality ของ ?


14

ฉันมีปัญหาเกี่ยวกับอัลกอริทึม

รับอาร์เรย์ (หรือชุด)ของจำนวนเต็มไม่ติดลบ ค้นหาชุดสูงสุดของซึ่งสำหรับ , a \ geqslant | S | .n S T a S a | S |TnSTaSa|S|

ตัวอย่างเช่น:

  1. ถ้าT = [1, 3, 4, 1, 3, 6] ดังนั้นSสามารถเป็น [3, 3, 6] หรือ [3, 4, 6] หรือ [4, 3, 6]
  2. ใน = [7, 5, 1, 1, 7, 4] ดังนั้นคือ [7, 5, 7, 4]STS

ฉันได้ลองใช้ฟังก์ชันเรียกซ้ำนี้แล้ว

function(T):
    if minimum(T) >= length(T): 
        return T
    else: 
        return function(T\minimum(T))

มีอัลกอริทึมที่ไม่เกิดซ้ำหรือไม่ (ฉันไม่ได้ตรวจสอบอัลกอริทึมแบบเรียกซ้ำดังนั้นจึงอาจมีข้อบกพร่องบางอย่าง)

คำตอบ:


14

T[i] >= i+1เรียงตันแล้วจึงนำเอาองค์ประกอบในขณะที่

sorted(T)=[6,4,3,3,1,1]เช่น จากนั้นT[0] = 6 > 1, T[1] = 4 > 2, T[2] = 3 <= 3และในที่สุดดังนั้นเราจึงมีT[3] = 3 < 4S = [T[0], T[1], T[2]]


3
แน่นอนว่านี่พลาดวิธีแก้ปัญหาอื่น ๆแต่ดูเหมือนว่า OP กำลังมองหาวิธีแก้ปัญหาใด ๆแทนที่จะเป็นวิธีแก้ปัญหาทั้งหมด {6,3,3}
Rick Decker

2
มันทำให้จำนวนองค์ประกอบถูกต้อง เรารู้ว่าเรามีวิธีแก้ปัญหาด้วย 3 องค์ประกอบ แต่ไม่ใช่ด้วย 4; ในกรณีนี้เรามี 4 องค์ประกอบ≥ 3 ดังนั้นเราจึงรู้ว่าเราสามารถเลือก 3 ข้อจากนั้นได้
gnasher729

3
ฉันขอขอบคุณข้อโต้แย้งของความถูกต้อง
ราฟาเอล

ฉันคิดว่าคุณน่าจะทำได้ในเวลา O (n) ด้วยการเลือก introselect
user2357112 รองรับ Monica

8

จากความคิดเห็นของฉันเดิม: นี่เป็นเรื่องที่เกี่ยวข้องอย่างใกล้ชิดกับที่แพร่หลายในการประเมินปริมาณผลผลิตทางวิชาการดัชนี 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อีม.aผมnผมnก./2

ตัวอย่าง:

[1,3,4,1,3,6]ลองตั้งค่าของคุณ

  1. x = 1, ,granted = [] greater = [3,4,1,3,6]ดังนั้นเราถึงกรณีทางพยาธิวิทยาเมื่อเดือยมีขนาดเล็กเกินไป (จริง ๆ แล้วมีขนาดเล็กจนsmallerว่างเปล่า) ในขั้นตอนแรก โชคดีที่อัลโกของเราพร้อมแล้ว มันจะละทิ้งxและลองอีกครั้งโดยgreaterลำพัง

  2. x = 3, ,granted = [] greater = [4,3,6]พวกเขารวมกันเป็นกลุ่มของความยาว 4 แต่เรามีข้อ จำกัด จากด้านล่างด้วย 3 ดังนั้นมันจึงมากเกินไป ทำซ้ำgreaterเพียงอย่างเดียว

  3. x = 4, ,granted = [] greater = [6]สิ่งนี้ให้องค์ประกอบจำนวน 2 ชิ้นซึ่งแต่ละอันดูเหมือนว่าเราอาจจะใช้มันเพิ่มอีก smaller = [3]เก็บนี้และทำซ้ำบน

  4. 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ว่าเราต้องการหรือไม่สามารถลบออกได้อย่างง่ายดาย (ฉันคิดว่าการประเมินที่ขี้เกียจจะดูแลสิ่งนั้น)


6

ไม่มีอะไรผิดปกติกับอัลกอริทึมของคุณและแน่นอนว่าอัลกอริทึมแบบเรียกซ้ำส่วนใหญ่สามารถแปลงเป็นลูปได้นี่คือลูปของรหัสแบบเรียกซ้ำของคุณ:

function(T):
    while minimum(T) <= lenght(T):
         remove minimum(T) from T
    loop

6
อัลกอริทึมแบบเรียกซ้ำทั้งหมดสามารถแปลงเป็นลูป ท้ายที่สุดเครื่องจักรทัวริงไม่รู้อะไรเกี่ยวกับการเรียกซ้ำ
David Richerby

4

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


3

ใช้ min-heap เพื่อทำ heapsort บางส่วนเนื่องจากคุณไม่ต้องการเรียงลำดับทั้งหมด

รักษา popping องค์ประกอบอย่างตะกละตะกลามจนกว่าคุณจะเกินเกณฑ์ที่กำหนด


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