วิธีการใช้สองกองในหนึ่งแถว?


15

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

ฉันพยายามที่จะแก้ปัญหาการออกกำลังกาย 10.1-2จากบทที่ 10 โครงสร้างข้อมูลพื้นฐานจาก CLRS Second Edition นี่คือสิ่งที่รัฐ:

อธิบายวิธีการใช้สองกองในหนึ่งอาร์เรย์[1..n]ในลักษณะที่ไม่สแต็คล้นเว้นแต่จำนวนรวมขององค์ประกอบทั้งในกองด้วยกันคือn การผลักดันการดำเนินงานและ POP ควรทำงานในO (1)เวลา

ทางออกที่ฉันเกิดขึ้นจนถึงตอนนี้คือ:

ให้อาร์เรย์[1..n]ใช้สองกอง: S1 [1..i]และS2 [i..n]

สำหรับการดำเนินการPUSH-S1และPUSH-S2หากสแต็ค 'เต็ม' จากนั้นเริ่มต้นการผลักองค์ประกอบเข้าสู่สแต็กอื่น ๆ (เช่นถ้าสแต็คS1เต็มเมื่อองค์ประกอบใหม่พยายามที่จะผลักดันเข้าไปแล้วผลักองค์ประกอบนั้นเข้าไป stack S2และในทางกลับกัน)

ปัญหาของวิธีนี้คือฉันจะไม่สามารถใช้POP-S1หรือPOP-S2ได้อย่างน่าเชื่อถือเนื่องจากไม่มีวิธีการ 'จดจำ' องค์ประกอบใดที่เป็นของสแต็กใด หากองค์ประกอบของสแต็กเป็นคู่(คีย์, ค่า)คีย์คือหมายเลขสแต็กจากนั้นจึงปรากฏองค์ประกอบที่ฉันจะต้องค้นหาในกรณีที่เลวร้ายที่สุดฉันหรือ (ni) ครั้ง - ซึ่งจะเป็นO (n ) (รู้สึกอิสระที่จะถูกต้องฉันหากฉันผิดที่นี่) ซึ่งจะไม่เป็นO (1)

ฉันต่อสู้กับคำถามมาระยะหนึ่งแล้ว ฉันกำลังติดตามใช่ไหม? ใครสามารถให้คำแนะนำที่เป็นไปได้สำหรับการแก้ไขปัญหานี้ได้บ้าง

โดยทั่วไปแล้วฉันควร 'คิด' เกี่ยวกับปัญหาเหล่านี้อย่างไร หรือคนที่ฉลาดจริงๆเท่านั้นที่สามารถแก้ปัญหาประเภทนี้ได้? การแก้ปัญหา / การแก้ปัญหาเช่นนี้ (เช่นได้รับประสบการณ์) จะช่วยให้ฉันดีขึ้นในเรื่องนี้หรือไม่?

ฉันรอการตรัสรู้


3
"การแก้ปัญหา / การแก้ปัญหาเช่นนี้ (เช่นได้รับประสบการณ์) จะช่วยให้ฉันพัฒนาตัวเองได้ดีขึ้นหรือไม่" จากประสบการณ์ของฉันนี่เป็นกรณีที่แน่นอน หากไม่มีสิ่งใดคุณจะต้องคิดในหลาย ๆ ทางเกี่ยวกับปัญหา อย่างที่ฉันบอกเมื่อเร็ว ๆ นี้: วิธีที่ดีที่สุดในการมีความคิดที่ดีคือการมีความคิดมากมาย
G. Bach

คำตอบ:


7

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


5

นี่คือคำแนะนำบางส่วน:

  1. หนึ่งในกองที่ควรเติบโต "ขึ้น" และอื่น ๆ "ลง"
  2. ไม่มีวิธีใดในการ 'จดจำ' องค์ประกอบใดที่เป็นของสแต็ก - คุณได้รับอนุญาตให้ใช้ตัวแปรเพิ่มเติมเพื่อช่วยคุณในเรื่องเช่นนั้น (วิธีนี้เหมาะสมสำหรับการแก้ปัญหาที่เสนอโดยคำใบ้แรก)

1

สแต็กแรกเริ่มต้นที่ 1 และเติบโตขึ้นสู่ n ในขณะที่สองเริ่มฟอร์ม n และเติบโตลงสู่ 1 สแต็คล้นเกิดขึ้นเมื่อองค์ประกอบถูกผลักเมื่อสแต็คพอยน์เตอร์ทั้งสองอยู่ติดกัน


1

วิธีนี้ใช้พื้นที่ที่มีอยู่อย่างมีประสิทธิภาพ มันไม่ได้ทำให้เกิดการโอเวอร์โฟลว์หากมีที่ว่างใน arr [] ความคิดคือการเริ่มต้นสองกองจากสองมุมสุดขีดของ arr [] stack1 เริ่มต้นจากองค์ประกอบซ้ายสุดองค์ประกอบแรกใน stack1 ถูกผลักไปที่ดัชนี 0 stack2 เริ่มต้นจากมุมขวาสุดองค์ประกอบแรกใน stack2 ถูกผลักไปที่ดัชนี (n-1) สแต็คทั้งคู่เติบโต (หรือหด) ในทิศทางตรงกันข้าม ในการตรวจสอบโอเวอร์โฟลทั้งหมดที่เราต้องตรวจสอบคือช่องว่างระหว่างองค์ประกอบด้านบนของทั้งสองสแต็ค


-1

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


ยังไม่มีข้อความยังไม่มีข้อความยังไม่มีข้อความ/2

-2

คำแนะนำบางอย่าง

สร้างอาร์เรย์

องค์ประกอบอาร์เรย์ที่มีดัชนีคี่สำหรับกองซ้อน 1

องค์ประกอบอาร์เรย์ที่มีดัชนีสม่ำเสมอสำหรับ stack2

ตอนนี้คุณสามารถเติบโตได้ทั้งสองทิศทางจากซ้ายไปขวา

เพียงแค่เก็บตัวแปรที่รักษาตำแหน่งสูงสุดของทั้งสองกองไว้ คุณจะไม่ต้องค้นหาอาร์เรย์

และถ้า stack1 เต็มในขณะที่ stack2 ว่างคุณสามารถติดตามองค์ประกอบเพิ่มเติม stack1 ใน stack2 โดยการบำรุงรักษาตัวแปรบางอย่าง


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