การนับหมู่เกาะในเมทริกซ์บูลีน


9

ได้รับ n×ม. บูลีนเมทริกซ์ X, ปล่อย 0 รายการเป็นตัวแทนของทะเลและ 1รายการหมายถึงที่ดิน กำหนดเกาะเป็นแนวตั้งหรือแนวนอน (แต่ไม่ใช่แนวทแยงมุม) ที่อยู่ติดกัน1 รายการ.

คำถามเดิมคือการนับจำนวนเกาะในเมทริกซ์ที่กำหนด ผู้เขียนอธิบายถึงวิธีแก้ปัญหาแบบเรียกซ้ำ (O(nม.) หน่วยความจำ)

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


ตัวอย่างของเอาต์พุตที่คาดไว้สำหรับอินพุตบางอย่างสำหรับcountฟังก์ชัน:

โอยูnเสื้อ(010111010)=1;โอยูnเสื้อ(101010101)=5;โอยูnเสื้อ(111101111)=1;

โอยูnเสื้อ(1111100100010110100011011111)=2

โอยูnเสื้อ(101111)=1


1
1. คุณหมายถึงอะไรโดย "orthogonal"? คุณหมายถึงองค์ประกอบที่เชื่อมต่อหรือไม่ 2. เราคิดอย่างไรเกี่ยวกับวิธีการจัดเก็บเมทริกซ์ เราสามารถสมมติว่ามันถูกเก็บไว้ในที่จัดเก็บข้อมูลภายนอก (เช่นฮาร์ดดิสก์ช้า) เพื่อให้คุณสามารถอ่านส่วนใดก็ได้ที่คุณต้องการ แต่มันจะเร็วกว่าในการอ่านบล็อกในแต่ละครั้ง? หรือว่าเราจะได้รับเมทริกซ์ในแบบสตรีมมิ่งซึ่งเมื่อเราได้รับเมทริกซ์อินพุตเล็กน้อยเราจะไม่เห็นบิตของอินพุตนั้นอีกเลย
DW

1
เจ๋งขอบคุณ ฉันขอแนะนำให้คุณแก้ไขคำถามเพื่อชี้แจงประเด็นเหล่านั้น ถ้ามันเป็นแบบสตรีมบิตของเมทริกซ์จะเรียงตามลำดับอย่างไร การสแกนจากซ้ายไปขวาระหว่างแถวจากนั้นลงไปยังแถวถัดไป
DW

1
โปรดแก้ไขคำถามเพื่อรวมรายละเอียดทั้งหมดเหล่านี้ ความคิดเห็นเป็นชั่วคราว
Yuval Filmus

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

1
ความซับซ้อนของเวลาที่ต้องการคืออะไร
hengxin

คำตอบ:


4

นี่คือภาพร่างของอัลกอริทึมที่เก็บสองแถวในหน่วยความจำในแต่ละครั้งเท่านั้น O(m)หน่วยความจำ แต่เนื่องจากคุณสามารถเรียกใช้อัลกอริทึมนี้บนทรานสดิวเซอร์ของเมทริกซ์โดยไม่มีปัญหาความซับซ้อนที่แท้จริงคือO(min(m,n))หน่วยความจำ เวลาประมวลผลคือO(mn).

  1. การเริ่มต้น. สแกนแถวแรกและค้นหาสตริงย่อยที่เชื่อมต่อทั้งหมดของแถวนั้น กำหนดแต่ละสตริงย่อยที่ไม่รวมกันของรหัสบวกที่ไม่ซ้ำกันและบันทึกเป็นเวกเตอร์ซึ่งเป็นศูนย์ที่ไหนX เป็นศูนย์และรหัสบวกที่ไม่ซ้ำกันเป็นอย่างอื่น

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

    010402220333300506607080009990010402220333300504402020003330

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

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

    ตอนนี้คุณสามารถยกเลิกแถวก่อนหน้าและกำหนดแถวปัจจุบันให้กับแถวก่อนหน้าและดำเนินการต่อ

  3. หากต้องการจัดการแถวสุดท้ายอย่างถูกต้องจะมีศูนย์อีกหนึ่งแถวที่ด้านล่างของ X และเรียกใช้ขั้นตอนที่ 2 อีกครั้ง


6

Orlp ให้ทางออกโดยใช้ O(n) คำของพื้นที่ซึ่งเป็น O(nlogn) บิตของพื้นที่ (สมมติว่าความเรียบง่ายนั้น n=m) ตรงกันข้ามมันง่ายที่จะแสดงให้เห็นว่าΩ(n) จำเป็นต้องใช้พื้นที่บิตโดยการลดความไม่ลงรอยกันที่กำหนดให้กับปัญหาของคุณ

สมมติว่าอลิซถือไบนารีเวกเตอร์ x1,,xn และ Bob ถือเวกเตอร์ไบนารี่ y1,,ynและพวกเขาต้องการทราบว่ามีดัชนีอยู่หรือไม่ i ดังนั้น xi=yi=1. พวกเขาเรียกใช้อัลกอริทึมของคุณสำหรับ2×(2n1) เมทริกซ์ซึ่งมีแถวอยู่ x1,0,x2,0,,0,xn และ y1,0,y2,0,,0,yn. หลังจากอ่านแถวแรกแล้วอลิซก็ส่งบ๊อบixi เช่นเดียวกับเนื้อหาของหน่วยความจำเพื่อให้ Bob สามารถทำอัลกอริทึมและเปรียบเทียบให้เสร็จสมบูรณ์ i(xi+yi)ถึงจำนวนของส่วนประกอบที่เชื่อมต่อ หากตัวเลขสองตัวตรงกันทั้งสองเวกเตอร์จะแยกกัน (ไม่มีดัชนีi), และในทางกลับกัน. เนื่องจากโพรโทคอลใด ๆ สำหรับชุดความไม่ต่อเนื่องนั้นต้องการΩ(n) บิต (แม้ว่ามันจะผิดพลาดกับความน่าจะเป็นคงที่เล็ก ๆ ) เราก็อนุมาน Ω(n) ขอบเขตล่างซึ่งเก็บไว้สำหรับโปรโตคอลแบบสุ่มซึ่งอนุญาตให้ทำผิดพลาดด้วยความน่าจะเป็นคงที่เล็กน้อย

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

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