งานชัดเจนเพื่อค้นหาอัลกอริทึมที่เป็น O (1) ในความยาว N ของรายการตัวเลขที่ต้องการ ดังนั้นไม่สำคัญว่าคุณต้องการหมายเลข 100 อันดับแรกหรือ 10,000 หมายเลขเวลาแทรกควรเป็น O (1)
เคล็ดลับที่นี่คือแม้ว่าจะมีการกล่าวถึงข้อกำหนด O (1) สำหรับการแทรกรายการ แต่คำถามไม่ได้พูดอะไรเกี่ยวกับลำดับเวลาในการค้นหาในพื้นที่จำนวนเต็ม แต่ปรากฎว่าสิ่งนี้สามารถทำให้ O (1) เช่นกัน วิธีแก้ปัญหามีดังนี้:
จัดเรียงสำหรับ hashtable ที่มีตัวเลขสำหรับคีย์และคู่ของตัวชี้รายการที่เชื่อมโยงสำหรับค่า ตัวชี้แต่ละคู่คือจุดเริ่มต้นและจุดสิ้นสุดของลำดับรายการที่เชื่อมโยง โดยปกติจะเป็นองค์ประกอบเดียวจากนั้นต่อไป องค์ประกอบทั้งหมดในรายการที่เชื่อมโยงจะอยู่ถัดจากองค์ประกอบที่มีจำนวนสูงสุดถัดไป รายการที่เชื่อมโยงจึงมีลำดับการเรียงของหมายเลขที่ต้องการเก็บบันทึกหมายเลขต่ำสุด
รับหมายเลขใหม่ x จากสตรีมแบบสุ่ม
มันสูงกว่าจำนวนต่ำสุดที่บันทึกไว้ล่าสุดหรือไม่ ใช่ => ขั้นตอนที่ 4 ไม่ => ขั้นตอนที่ 2
กดตารางแฮชด้วยหมายเลขที่เพิ่งถ่าย มีรายการไหม? ใช่ => ขั้นตอนที่ 5 ไม่ => ใช้หมายเลขใหม่ x-1 และทำซ้ำขั้นตอนนี้ (นี่คือการค้นหาแบบเส้นตรงที่ลดลงเพียงแค่อดทนกับฉันที่นี่สิ่งนี้สามารถปรับปรุงได้และฉันจะอธิบายวิธี)
ด้วยองค์ประกอบลิสต์ที่เพิ่งได้รับจากตารางแฮชให้ใส่หมายเลขใหม่หลังอิลิเมนต์ในรายการที่ลิงก์ (และอัปเดตแฮช)
ใช้หมายเลขต่ำสุดที่บันทึกไว้ (และลบออกจากแฮช / รายการ)
กดตารางแฮชด้วยหมายเลขที่เพิ่งถ่าย มีรายการไหม? ใช่ => ขั้นตอนที่ 8 ไม่ => ใช้หมายเลขใหม่ l + 1 และทำซ้ำขั้นตอนนี้ (นี่เป็นการค้นหาเชิงเส้นที่ง่ายขึ้น)
ด้วยจำนวนการบวกจำนวนกลายเป็นหมายเลขต่ำสุดใหม่ ไปที่ขั้นตอนที่ 2
เพื่อให้ค่าที่ซ้ำกันแฮชจริง ๆ ต้องรักษาจุดเริ่มต้นและจุดสิ้นสุดของลำดับรายการที่เชื่อมโยงขององค์ประกอบที่ซ้ำกัน การเพิ่มหรือลบองค์ประกอบที่คีย์ที่กำหนดจะเป็นการเพิ่มหรือลดช่วงที่ชี้ไป
ส่วนแทรกที่นี่คือ O (1) การค้นหาที่กล่าวถึงคือฉันเดาว่า O (ความแตกต่างระหว่างตัวเลขโดยเฉลี่ย) ความแตกต่างเฉลี่ยเพิ่มขึ้นตามขนาดของพื้นที่หมายเลข แต่ลดลงตามความยาวที่ต้องการของรายการตัวเลข
กลยุทธ์การค้นหาเชิงเส้นค่อนข้างแย่ถ้าพื้นที่จำนวนมาก (เช่นสำหรับ 4 ไบต์ชนิด int, 0 ถึง 2 ^ 32-1) และ N = 100 ในการหลีกเลี่ยงปัญหาด้านประสิทธิภาพนี้คุณสามารถเก็บชุดแฮชเทเบิ้ลแบบขนานได้โดยที่ตัวเลขจะถูกปัดเศษให้มีขนาดที่สูงขึ้น (เช่น 1s, 10s, 100s, 1000s) เพื่อสร้างคีย์ที่เหมาะสม ด้วยวิธีนี้คุณสามารถเลื่อนเกียร์ขึ้นและลงเพื่อทำการค้นหาที่ต้องการได้รวดเร็วยิ่งขึ้น ประสิทธิภาพกลายเป็น O (บันทึกหมายเลขลำดับ) ฉันคิดว่าซึ่งคงที่เช่น O (1) ด้วย
เพื่อให้ชัดเจนยิ่งขึ้นลองจินตนาการว่าคุณมีหมายเลข 197 อยู่ในมือ คุณกดแฮชของตาราง 10s ด้วย '190' มันจะถูกปัดเศษเป็นสิบที่ใกล้ที่สุด อะไร? ไม่เลยคุณลงไปใน 10 วินาทีจนกว่าคุณจะพูดว่า 120 จากนั้นคุณสามารถเริ่มต้นที่ 129 ใน hashtable 1s จากนั้นลอง 128, 127 จนกระทั่งคุณตีอะไรบางอย่าง ตอนนี้คุณได้พบว่าที่ไหนในรายการที่เชื่อมโยงเพื่อใส่หมายเลข 197 ขณะที่ใส่ไว้คุณต้องอัปเดต hashtable 1s ด้วยรายการ 197, hashtable 10s ด้วยหมายเลข 190, 100s กับ 100 ฯลฯ ขั้นตอนส่วนใหญ่ คุณต้องทำที่นี่ 10 ครั้งบันทึกของช่วงตัวเลข
ฉันอาจมีรายละเอียดบางอย่างไม่ถูกต้อง แต่เนื่องจากนี่คือการแลกเปลี่ยนโปรแกรมเมอร์และบริบทคือการสัมภาษณ์ฉันหวังว่าข้างต้นเป็นคำตอบที่น่าเชื่อถือเพียงพอสำหรับสถานการณ์นั้น
แก้ไขฉันเพิ่มรายละเอียดเพิ่มเติมที่นี่เพื่ออธิบายรูปแบบ hashtable แบบขนานและความหมายของการค้นหาเชิงเส้นที่ไม่ดีที่ฉันกล่าวถึงสามารถถูกแทนที่ด้วยการค้นหา O (1) ฉันก็รู้ว่าไม่มีความจำเป็นที่จะต้องค้นหาหมายเลขต่ำสุดถัดไปเพราะคุณสามารถก้าวเข้าไปหามันได้โดยดูใน hashtable ด้วยจำนวนต่ำสุดและเข้าสู่องค์ประกอบถัดไป