การค้นหาองค์ประกอบที่เกิดขึ้นมากที่สุดในไฟล์ที่มีขนาดใหญ่มาก


12

ฉันได้ยินคำถามสัมภาษณ์นี้ถามมากและฉันหวังว่าจะได้รับความคิดเห็นเกี่ยวกับคำตอบที่ดี: คุณมีไฟล์ขนาดใหญ่ 10+ GB และคุณต้องการค้นหาว่าองค์ประกอบใดที่เกิดขึ้นมากที่สุดวิธีที่ดีคืออะไร เพื่อทำสิ่งนี้?

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

ความคิดอื่น ๆ ที่ฉันได้รวมแยกไฟล์ที่จะทำซ้ำผ่านและประมวลผลโดยหลายกระทู้แล้วมีผลเหล่านั้นรวมกัน แต่ปัญหาหน่วยความจำสำหรับแผนที่ยังคงมี


2
องค์ประกอบของไฟล์คืออะไร? พวกเขาเป็นสตริง? หากคุณใช้ตัวอักษรสำหรับองค์ประกอบแผนที่จะไม่มีปัญหาหน่วยความจำ หากองค์ประกอบเป็นคำพูดฉันคิดว่ามันคงไม่เป็นปัญหาอีกแล้ว หากคุณมีสารตั้งต้นที่เป็นไปได้ทั้งหมดคุณสามารถมีปัญหา ...
Nejc

1
หากเงื่อนไขคือ "องค์ประกอบที่ปรากฏมากกว่าครึ่งหนึ่งขององค์ประกอบทั้งหมด" แสดงว่ามีวิธีการแก้ปัญหาเชิงเส้น
st0le

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

1
หากอัลกอริทึมส่วนใหญ่ของผู้สมัคร Boyer-Moore มันจะทำงานในเวลาเชิงเส้นและเป็นสถานที่
Juho

คำตอบ:


6

>1/kO(k)O(). ปัญหานี้เป็นที่รู้จักกันในชื่อปัญหาที่น่าเกรงขามหนัก

>1/kk

k=2

  • หากองค์ประกอบปัจจุบันของไฟล์เหมือนกันกับองค์ประกอบที่จัดเก็บเพิ่มการนับโดยหนึ่ง
  • หากองค์ประกอบปัจจุบันของไฟล์แตกต่างจากองค์ประกอบที่เก็บไว้ให้ลดจำนวนลงทีละหนึ่ง
  • หากการนับที่อัปเดตเป็น 0 "เตะออก" องค์ประกอบที่เก็บไว้และจัดเก็บองค์ประกอบปัจจุบันของไฟล์; เพิ่มจำนวนเป็น 1
  • ดำเนินการองค์ประกอบต่อไปของไฟล์

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

kk1k1kk

k11/kO(k)

k1/kk1


คุณไม่สามารถใช้อัลกอริทึม Boyer-Moore หรือ Misra-Gries-Demaine ปัญหาตามที่ระบุไว้แตกต่างกัน: คุณไม่ได้ค้นหาองค์ประกอบส่วนใหญ่ แต่สำหรับองค์ประกอบที่มีการเกิดขึ้น> = ของการเกิดขึ้นขององค์ประกอบทั้งหมด นี่คือตัวอย่างง่ายๆ ให้nเป็นจำนวนรวมขององค์ประกอบเช่นว่าn = 2k + 1 ปล่อยให้องค์ประกอบkแรกเป็น 0 องค์ประกอบkถัดไปคือ 1 และองค์ประกอบสุดท้ายเป็น 2 อัลกอริทึม Boyer-Moore จะรายงานองค์ประกอบสุดท้าย 2 เป็นผู้สมัครส่วนใหญ่ที่มีศักยภาพ แต่สำหรับอินสแตนซ์นี้ผลลัพธ์จะต้องเป็น 0 หรือ 1
Massimo Cafaro

O(1)Ω(n)

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

@MassimoCafaro ที่ไม่ใช่การแลกเปลี่ยนที่คุณต้องทำ ในขณะที่ฉันชี้ให้เห็นผ่านเดียวผ่านไฟล์ได้อย่างง่ายดายตรวจสอบว่าข้อสันนิษฐานพอใจ!
Sasho Nikolov

@MassimoCafaro และนี่เป็นเพียงวิธีแก้ปัญหาเล็กน้อย! สมมติฐานที่สามารถตรวจสอบได้ด้วยความน่าจะเป็นสูงกับร่าง CM ที่ไม่มีการผ่านเพิ่มเติม
Sasho Nikolov

3

คำตอบที่ชัดเจนคือแน่นอนที่จะเก็บแผนที่แฮชและจัดเก็บตัวนับการเกิดขององค์ประกอบต่าง ๆ ในขณะที่คุณเลื่อนดูไฟล์ดังที่ Nejc แนะนำไว้แล้ว นี่คือ (ในแง่ของความซับซ้อนของเวลา) ทางออกที่ดีที่สุด

Θ(nlogn).


คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับวิธีการเข้ารหัสของ Huffman ได้ไหม? ฉันเคยเขียนตัวเข้ารหัส Huffman มาก่อน แต่มันไม่นานคุณจะใช้มันในกรณีนี้อย่างไร
Pat

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

1

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


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