หารอบทั้งหมด


9

ฉันมีเซต จำกัด Sฟังก์ชั่น f:SSและคำสั่งซื้อทั้งหมด < บน S. ฉันต้องการค้นหาจำนวนรอบที่แตกต่างกันS.

สำหรับองค์ประกอบที่กำหนด sS ฉันสามารถใช้อัลกอริทึมของ Floyd (หรือ Brent's เป็นต้น) เพื่อค้นหาความยาวของวัฏจักรที่มีการใช้งานซ้ำ ๆ f ส่ง sถึง; ด้วยความพยายามอีกเล็กน้อยฉันสามารถระบุรอบนี้ (เช่นโดยมัน<องค์ประกอบขั้นต่ำ) วิธีที่ไม่ดีสำหรับการแก้ปัญหาคือการทำซ้ำแต่ละองค์ประกอบเรียงลำดับองค์ประกอบที่น้อยที่สุดที่ทำให้เกิดการทิ้งรายการที่ซ้ำกันและส่งกลับจำนวน แต่สิ่งนี้อาจเกี่ยวข้องกับการส่งผ่านจำนวนมากในองค์ประกอบเดียวกันและข้อกำหนดของพื้นที่ขนาดใหญ่

วิธีใดบ้างที่มีเวลาและพื้นที่ที่ดีกว่า ฉันไม่แน่ใจด้วยซ้ำว่าอะไรคือวิธีที่ดีที่สุดในการวัดพื้นที่ที่ต้องการ - ถ้าf เป็นฟังก์ชั่นตัวตนแล้ววิธีการใด ๆ ที่เก็บทุกรอบจะใช้ Ω(n) ช่องว่าง


4
หนึ่งในวิธีธรรมชาติในการวัดพื้นที่คือการพิจารณา S เป็นชุดของสตริง n-bit และ f เป็น oracle ดังนั้นอัลกอริธึมไร้เดียงสาที่คุณอธิบายต้องใช้พื้นที่เอ็กซ์โพเนนเชียล เราอาจหาอัลกอริธึมที่ใช้พื้นที่พหุนามเพียงอย่างเดียว แต่นี่ก็ไม่น่าจะเป็นไปได้
Tsuyoshi Ito

นั่นคือสิ่งที่ฉันหมายถึงโดย "ฉันไม่ทราบว่าวิธีที่ดีที่สุดในการวัดพื้นที่" อาจเป็นไปได้ว่าฉันควรตั้งเป้าหมาย O (poly (n) + y) โดยที่ y คือเอาต์พุตดังนั้นพื้นที่ที่ใช้คือพหุนามตราบใดที่ y มีขนาดเล็กเพียงพอ
ชาร์ลส์

ฟังก์ชันfของคุณมีคุณสมบัติที่ใช้งานได้หรือไม่? หรือไม่ว่าขั้นตอนวิธีการเป็นพหุนามหรือชี้แจงในวิธีที่คุณต้องการแสดงขนาดการป้อนข้อมูลจะค่อนข้างสงสัยถ้าคำตอบในทางปฏิบัติก็คือว่าขั้นตอนวิธีการที่จะนำทั้งเวลาและพื้นที่ในการสั่งซื้อของ cardinality ของS
Niel de Beaudrap

@Niel de Beaudrap: ฉันไม่แน่ใจว่าคุณสมบัติใดจะมีประโยชน์ ฉันคาดหวังว่าจำนวนรอบที่แตกต่างกันมีขนาดเล็ก แต่อาจเป็นไปได้O(n3); นั่นเป็นเหตุผลที่ฉันแนะนำฟังก์ชั่นของy และ n แทนที่จะเป็นเพียงแค่ n. ฉันยินดีที่จะใช้ exponential พื้นที่ในจำนวนบิตของการส่งออกถ้าจำเป็น
ชาร์ลส์

คำตอบ:


7

หากสิ่งที่คุณต้องการทำคือนับจำนวนรอบคุณสามารถทำได้ด้วย 2 | S | บิต (บวกเปลี่ยน) มูลค่าของพื้นที่ ดูเหมือนว่าไม่น่าเป็นไปได้ที่คุณจะสามารถทำได้ดีกว่ามากเว้นแต่ว่าSหรือfจะมีคุณสมบัติที่สะดวกสบายเป็นพิเศษ

เริ่มต้นด้วยอาร์เรย์ A จำนวนเต็มเก็บ {0,1,2} - หนึ่งต่อองค์ประกอบของS - เริ่มต้นเป็นศูนย์; เราจะแสดงให้เห็นเหล่านี้เป็น(unexplored), และ(partially explored) (fully explored)เริ่มต้นตัวนับรอบเป็นศูนย์ สำหรับแต่ละองค์ประกอบs  ∈  Sในการสั่งซื้อจะทำต่อไปนี้:

  1. หาก A [ s ] =  (fully explored)ให้ข้ามไปที่ขั้นตอนที่ 6
  2. Set A [ s ] ←  (partially explored)และตั้ง iterator เจ  ←  f (s)
  3. ในขณะที่ [ J ] =  (unexplored)กำหนด [ เจ ] ←  (partially explored)และชุดเจ  ←  f (ญ)
  4. หาก A [ j ] =  (partially explored)เราปิดรอบใหม่แล้ว การเพิ่มค่าcด้วย 1 (หากคุณต้องการเก็บบันทึกตัวแทนบางส่วนของวัฏจักรนี้ค่าปัจจุบันของjจะเป็นตัวเลือกโดยพลการแน่นอนสิ่งนี้ไม่จำเป็นต้องเป็นองค์ประกอบขั้นต่ำในรอบที่คุณต้องการ order <.) มิฉะนั้นเรามี A [ j ] =  (fully explored)ซึ่งหมายความว่าเราได้ค้นพบวงโคจรที่สำรวจก่อนซึ่งสิ้นสุดในรอบที่นับแล้ว อย่าเพิ่ม .
  5. เพื่อบ่งชี้ว่าวงโคจรที่เริ่มต้นที่sขณะนี้ได้รับการสำรวจอย่างเต็มที่ชุดเจ  ←  s
    ในขณะที่ [ J ] =  (partially explored)กำหนด [ เจ ] ←  (fully explored)และชุดเจ  ←  f (ญ)
  6. ดำเนินการต่อไปองค์ประกอบถัดไปs  ∈  S

ดังนั้นแต่ละรอบของวงโคจรที่ถูกเหนี่ยวนำโดยfจะถูกนับหนึ่งครั้ง และองค์ประกอบใด ๆ ที่คุณบันทึกในฐานะตัวแทนจะเป็นองค์ประกอบของรอบที่แตกต่างกัน ข้อกำหนดหน่วยความจำคือ 2 | S | สำหรับอาร์เรย์ A, O (บันทึก | S |) สำหรับจำนวนรอบและอัตราต่อรองและสิ้นสุดอื่น ๆ

แต่ละองค์ประกอบs  ∈  Sจะเข้าชมอย่างน้อยสองครั้งเมื่อค่าของได้ [ s ] จะเปลี่ยนจาก(unexplored)การและเมื่อการเปลี่ยนแปลงจะ(partially explored) (fully explored)จำนวนครั้งทั้งหมดที่โหนดใด ๆ ถูกตรวจทานอีกครั้งหลังจากถูก(fully explored)ล้อมรอบด้วยจำนวนครั้งที่พยายามค้นหารอบใหม่ซึ่งไม่สามารถทำได้ซึ่งเป็นอย่างมาก | S | - เกิดจากการ iterating วงหลักผ่านองค์ประกอบทั้งหมดของS ดังนั้นเราสามารถคาดหวังว่ากระบวนการนี้จะมีส่วนร่วมอย่างมากที่สุด 3 | S | node-traversals นับทุกครั้งที่มีการเยี่ยมชมหรือเยี่ยมชมโหนด

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


ยอดเยี่ยมนี้ช่วยเพิ่มความโง่ O(|S|log|S|)อัลกอริทึมพื้นที่ฉันมีในใจ ฉันไม่ต้องการตัวแทน ฉันแนะนำ<ในกรณีที่มันจะเป็นประโยชน์กับอัลกอริทึมบางอย่าง
ชาร์ลส์

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

1
ฉันคิดว่าควรเป็น #L (โดยใช้การจ่ายกำลังเมทริกซ์) นี่เป็น # L-hard หรือไม่
Kaveh

@Charles: ดูคำตอบล่าสุดของฉันซึ่งจะทำให้คุณได้รับการปรับปรุงถ้าคุณรู้ว่า# ก็ตาม cycles o ( | S | ) มันใช้มากกว่า polylog | S | พื้นที่ แต่ถ้าคุณยินดีแลกพื้นที่และเวลาอาจเป็นเรื่องดีสำหรับคุณ
Niel de Beaudrap

@Niel de Beaudrap: ขอบคุณ! +1 สำหรับทั้งคู่ อัลกอริทึมนี้ดูดีที่สุดตราบใดที่ข้อมูลยังอยู่ในหน่วยความจำ เมื่อมันหกฉันจะดูที่การใช้อื่น ๆ (เป็นไปได้ว่าคนอื่น ๆ จะดีกว่าถ้าฉันสามารถใส่ทุกอย่างในแคชได้ แต่นั่นอาจเป็นเรื่องที่ยุ่งยากมากเกินไป)
Charles

5

หากคุณมีรอบน้อยมากนี่คืออัลกอริทึมที่จะใช้พื้นที่น้อยลง แต่ใช้เวลานานกว่าในการยกเลิก

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

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

เริ่มต้นรายการส่วนประกอบที่ว่างเปล่า, complist. แต่ละองค์ประกอบจะถูกแทนด้วยชุดของตัวอย่างจากองค์ประกอบนั้น เรายังคงโครงสร้างการค้นหาsamplesที่จัดเก็บองค์ประกอบทั้งหมดที่ได้รับเลือกเป็นตัวอย่างสำหรับส่วนประกอบบางส่วนหรืออื่น ๆ ให้Gเป็นลำดับของจำนวนเต็มสูงสุดถึงnซึ่งสมาชิกสามารถกำหนดได้อย่างมีประสิทธิภาพโดยการคำนวณคำสั่งบูลีน ตัวอย่างเช่นอำนาจของ 2 หรือที่สมบูรณ์แบบP THอำนาจสำหรับบางจำนวนเต็มพี สำหรับแต่ละs  ∈  Sทำต่อไปนี้:

  1. ถ้าsอยู่ในsamplesให้ข้ามไปที่ขั้นตอนที่ 5
  2. เริ่มต้นรายการที่ว่างเปล่าcursampleตัววนซ้ำj  ← f ( s ) และตัวนับt  ← 1
  3. ในขณะที่เจไม่ได้อยู่ในsamples:
    - หากเสื้อ  ∈  Gแทรกทั้งในและcursample - เพิ่มเสื้อและชุดเจ  ←  f (ญ)samples
  4. ตรวจสอบว่าjอยู่cursampleหรือไม่ หากไม่มีเราพบองค์ประกอบที่สำรวจมาก่อนหน้านี้: เราตรวจสอบว่าองค์ประกอบjเป็นของอะไรและแทรกองค์ประกอบทั้งหมดของcursampleเข้าไปในองค์ประกอบที่เหมาะสมของcomplistเพื่อเพิ่มองค์ประกอบนั้น มิฉะนั้นเราได้อีกครั้งพบองค์ประกอบจากวงโคจรในปัจจุบันหมายความว่าเราได้สำรวจรอบอย่างน้อยหนึ่งครั้งโดยไม่ต้องเผชิญหน้าตัวแทนของรอบก่อนหน้านี้การค้นพบใด ๆ เราแทรกเป็นคอลเลกชันของกลุ่มตัวอย่างจากส่วนที่ค้นพบใหม่ลงไปcursamplecomplist
  5. ดำเนินการต่อไปองค์ประกอบถัดไปs  ∈  S

สำหรับn  = | S |, ให้X (n)เป็นฟังก์ชันเพิ่มเสียงเดียวที่อธิบายถึงจำนวนรอบที่คาดหวัง ( เช่น X (n)n 1/3 ), และให้Y (n) = y (n)  บันทึก ( n ) ∈Ω ( X (n)  log ( n )) เป็นฟังก์ชั่นเพิ่มเสียงโมโนโทนกำหนดเป้าหมายสำหรับการใช้หน่วยความจำ ( เช่น y (n)n 1/2 ) เราต้องการy (n)  ∈Ω ( X (n) ) เพราะมันจะใช้พื้นที่อย่างน้อยX (n)  log ( n ) เพื่อเก็บตัวอย่างหนึ่งตัวอย่างจากแต่ละองค์ประกอบ

  • ยิ่งมีวงโคจรที่เราสุ่มตัวอย่างมากเท่าไหร่ก็ยิ่งมีโอกาสมากขึ้นที่เราจะเลือกตัวอย่างในวงรอบปลายวงโคจรเร็วขึ้น จากจุด asymptotics ในมุมมองของมันก็ทำให้ความรู้สึกที่จะได้รับเป็นตัวอย่างมากที่สุดเท่าที่ขอบเขตหน่วยความจำของเราอนุญาต: เราอาจตามที่กำหนดไว้อย่างดีจีที่จะมีการคาดว่าปี (n)องค์ประกอบที่มีน้อยกว่าn
    - หากความยาวสูงสุดของวงโคจรในSคาดว่าจะเป็นLเราอาจปล่อยให้Gเป็นหลายจำนวนเต็มของL  /  Y (n)
    - หากไม่มีความยาวที่คาดไว้เราอาจสุ่มตัวอย่างหนึ่งครั้งทุก ๆn  /  y (n)องค์ประกอบ; นี่คือกรณีใด ๆ ขอบเขตบนบนช่วงเวลาระหว่างกลุ่มตัวอย่าง

  • หากในการค้นหาองค์ประกอบใหม่เราเริ่มสำรวจองค์ประกอบของSที่เราเคยเข้าชมก่อนหน้านี้ (ไม่ว่าจะเป็นองค์ประกอบใหม่ที่ถูกค้นพบหรือองค์ประกอบเก่าที่มีการค้นพบวงจรเทอร์มินัล) มันจะใช้เวลาn  /  yมากที่สุดn)การวนซ้ำเพื่อหาองค์ประกอบตัวอย่างก่อนหน้านี้ นี่เป็นขอบเขตบนของจำนวนครั้งสำหรับความพยายามในการค้นหาส่วนประกอบใหม่แต่ละครั้งเราสำรวจโหนดซ้ำซ้อน เพราะเราทำให้nความพยายามดังกล่าวเราจะเกินความจำเป็นแล้วแวะไปที่องค์ประกอบของSที่มากที่สุดn 2  /  Y (n)ครั้งรวม

  • งานที่ต้องใช้ในการทดสอบการเป็นสมาชิกในsamplesคือ O ( y (n)  log  y (n) ) ซึ่งเราทำซ้ำในทุกครั้งที่เข้าชม: ค่าใช้จ่ายสะสมของการตรวจสอบนี้คือ O ( n 2  log  y (n) ) นอกจากนี้ยังมีค่าใช้จ่ายในการเพิ่มตัวอย่างไปยังคอลเลกชันที่เกี่ยวข้องซึ่งรวมกันเป็น O ( y (n)  log  y (n) ) ในที่สุดทุกครั้งที่เราพบส่วนประกอบที่ค้นพบก่อนหน้านี้อีกครั้งเราจะต้องใช้เวลามากถึงX (n)  บันทึก *  y (n)เวลาเพื่อกำหนดองค์ประกอบที่เราค้นพบอีกครั้ง เช่นนี้อาจเกิดขึ้นได้ถึงnครั้งการทำงานที่เกี่ยวข้องกับการสะสมเป็นที่สิ้นสุดโดยn X (n)  เข้าสู่ระบบ  Y (n)

ดังนั้นงานสะสมที่ดำเนินการในการตรวจสอบว่าโหนดที่เราเข้าชมนั้นอยู่ในกลุ่มตัวอย่างหรือไม่นั้นควบคุมเวลาทำงาน: ค่าใช้จ่าย O ( n 2  log  y (n) ) จากนั้นเราควรทำให้y (n) มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้ซึ่งก็คือ O ( X (n) )

ดังนั้นหนึ่งอาจระบุจำนวนรอบ (ซึ่งเป็นเช่นเดียวกับจำนวนขององค์ประกอบที่สิ้นสุดในรอบเหล่านั้น) ในพื้นที่ O ( X (n)  บันทึก ( n )) การใช้ O ( n 2  log  X (n) ) เวลาที่จะทำเช่นนั้นโดยที่X (n)คือจำนวนรอบที่คาดไว้


1

คุณสามารถหลีกเลี่ยงการผ่านหลายครั้งในองค์ประกอบเดียวกันได้โดยใช้โครงสร้างข้อมูลชุดยูเนี่ยน หนึ่งผ่านแต่ละองค์ประกอบs การรวมชุดที่มี s กับชุดที่มี f(s). ยังคงใช้หน่วยความจำจำนวนมาก

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