คำนวณค่ามัธยฐานของตัวเลขพันล้าน


127

หากคุณมีตัวเลขหนึ่งพันล้านเลขหมายและคอมพิวเตอร์หนึ่งร้อยเครื่องวิธีใดที่ดีที่สุดในการหาค่ามัธยฐานของตัวเลขเหล่านี้

ทางออกหนึ่งที่ฉันมีคือ:

  • แบ่งชุดเท่า ๆ กันระหว่างคอมพิวเตอร์
  • จัดเรียง
  • หาค่ามัธยฐานสำหรับแต่ละชุด
  • จัดเรียงชุดค่ามัธยฐาน
  • รวมสองชุดในแต่ละครั้งจากค่ามัธยฐานต่ำสุดถึงสูงสุด

หากเราทำการm1 < m2 < m3 ...รวมก่อนSet1และSet2และในเซตผลลัพธ์เราสามารถทิ้งตัวเลขทั้งหมดที่ต่ำกว่าค่ามัธยฐานของSet12(รวม) ได้ ดังนั้น ณ เวลาใดก็ตามเรามีเซตขนาดเท่ากัน โดยวิธีนี้ไม่สามารถทำได้ในลักษณะคู่ขนาน ความคิดใด ๆ ?


3
@ John Boker: จริงๆแล้วปัญหาประกอบด้วยสองปัญหาย่อย: 1) จัดเรียงรายการและ 2) รับองค์ประกอบด้วยดัชนี 5'000'000'000 ฉันแทบไม่เชื่อว่าตัวเลขจะเรียงลำดับ
โรมัน

3
@ โรมัน: ปัญหาไม่จำเป็นต้องประกอบด้วยสองปัญหาย่อยที่คุณอธิบายเช่นการเลือกอย่างรวดเร็ว แต่ Quickselect ไม่ขนานกันอย่างน้อยก็ไม่สำคัญ และแน่นอนว่าคุณคิดถูกว่าหากเรียงลำดับตัวเลขไว้ล่วงหน้ามันเป็นคำถามที่ไม่มีจุดหมาย
Steve Jessop

5
@fmsf: ฉันไม่คิดว่าประเทศที่พูดภาษาอังกฤษจะใช้ภาษาอังกฤษที่ยาวเป็นพันล้านเพื่อจุดประสงค์ทางการใด ๆ ตัวอย่างเช่นที่นี่ในสหราชอาณาจักรเราหยุดใช้ในปี 2517 ฉันจะพิจารณาว่าการใช้ "พันล้าน" หมายถึงล้านล้านในภาษาอังกฤษเป็นคำถามหลอกลวงไม่ใช่ "พันล้านจริง" แต่อย่างใด แน่นอนว่าในภาษาฝรั่งเศสมันจะแตกต่างกันโดยสิ้นเชิง แต่คำถามไม่ได้เป็นภาษาฝรั่งเศส
Steve Jessop

5
คุณไม่จำเป็นต้องเรียงลำดับ! en.wikipedia.org/wiki/…
glebm

2
ตัวเลข 1 พันล้านเป็นข้อมูลเพียงไม่กี่กิกะไบต์คุณไม่จำเป็นต้องใช้พีซีหลายเครื่องหรืออัลกอริทึมที่ซับซ้อนในการแก้ปัญหานี้ อย่าซับซ้อนมากเกินไป
user626528

คำตอบ:


54

อ่าสมองของฉันเพิ่งเข้าเกียร์ฉันมีข้อเสนอแนะที่สมเหตุสมผลแล้ว อาจจะสายเกินไปหากนี่เป็นการสัมภาษณ์ แต่ไม่เป็นไร:

เครื่อง 1 จะเรียกว่า "เครื่องควบคุม" และเพื่อประโยชน์ในการโต้แย้งมันจะเริ่มต้นด้วยข้อมูลทั้งหมดและส่งเป็นพัสดุที่เท่ากันไปยังเครื่องอื่น ๆ อีก 99 เครื่องหรือมิฉะนั้นข้อมูลจะเริ่มกระจายอย่างเท่าเทียมกันระหว่างเครื่องและ ส่งข้อมูล 1/99 ไปยังข้อมูลอื่น ๆ พาร์ติชันไม่จำเป็นต้องเท่ากันเพียงแค่ปิด

เครื่องแต่ละเครื่องจะจัดเรียงข้อมูลและดำเนินการในลักษณะที่ชอบค้นหาค่าที่ต่ำกว่าก่อน ตัวอย่างเช่น Quicksort ให้เรียงลำดับส่วนล่างของพาร์ติชันก่อน [*] เสมอ มันเขียนข้อมูลกลับไปที่เครื่องควบคุมตามลำดับที่เพิ่มขึ้นโดยเร็วที่สุด (โดยใช้ IO แบบอะซิงโครนัสเพื่อทำการเรียงลำดับต่อไปและอาจใช้ Nagle บน: ทดลองเล็กน้อย)

เครื่องควบคุมจะทำการผสานข้อมูล 99 ทิศทางเมื่อมาถึง แต่จะละทิ้งข้อมูลที่ผสานเพียงแค่นับจำนวนค่าที่เห็น มันคำนวณค่ามัธยฐานเป็นค่าเฉลี่ยของ 1/2 พันล้านและ 1/2 พันล้านบวกค่า oneth

สิ่งนี้ประสบปัญหา "ช้าที่สุดในฝูง" อัลกอริทึมไม่สามารถดำเนินการให้เสร็จสมบูรณ์ได้จนกว่าทุกค่าที่น้อยกว่าค่ามัธยฐานจะถูกส่งโดยเครื่องคัดแยก มีโอกาสที่สมเหตุสมผลที่ค่าดังกล่าวจะค่อนข้างสูงในพื้นที่ข้อมูล ดังนั้นเมื่อการแบ่งพาร์ติชันเริ่มต้นของข้อมูลเสร็จสมบูรณ์เวลาทำงานโดยประมาณคือการรวมกันของเวลาในการจัดเรียงข้อมูล 1/99 ของข้อมูลและส่งกลับไปยังคอมพิวเตอร์ควบคุมและเวลาที่ตัวควบคุมอ่านข้อมูล 1/2 . "ชุดค่าผสม" อยู่ระหว่างค่าสูงสุดและผลรวมของเวลาเหล่านั้นซึ่งอาจใกล้เคียงกับค่าสูงสุด

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

เนื่องจาก I / O เครือข่ายมีแนวโน้มที่จะถูกผูกไว้อาจมีกลเม็ดบางอย่างที่คุณสามารถเล่นได้อย่างน้อยก็สำหรับข้อมูลที่กลับมาที่เครื่องควบคุม ตัวอย่างเช่นแทนที่จะส่ง "1,2,3, .. 100" บางทีเครื่องจัดเรียงอาจส่งข้อความที่มีความหมายว่า "100 ค่าน้อยกว่า 101" จากนั้นเครื่องควบคุมสามารถทำการผสานที่แก้ไขได้ซึ่งพบว่าค่าสูงสุดของช่วงเหล่านั้นมีค่าน้อยที่สุดจากนั้นจึงบอกเครื่องเรียงลำดับทั้งหมดว่ามันคืออะไรเพื่อที่พวกเขาจะได้ (ก) บอกเครื่องควบคุมว่า หลายค่าให้ "นับ" ต่ำกว่าค่านั้นและ (b) ดำเนินการส่งข้อมูลที่เรียงลำดับจากจุดนั้นต่อ

โดยทั่วไปแล้วอาจมีเกมทายคำท้าทายที่ชาญฉลาดซึ่งเครื่องควบคุมสามารถเล่นกับเครื่องเรียงลำดับ 99 เครื่องได้

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

[*] การอนุญาตให้ใช้สแต็กที่ใช้ได้ - การเลือกส่วนที่ต้องทำก่อนจะถูก จำกัด หากคุณไม่มีพื้นที่เพิ่มเติม O (N) แต่ถ้าคุณมีพื้นที่ว่างเพียงพอคุณสามารถเลือกได้และหากคุณมีพื้นที่ไม่เพียงพออย่างน้อยคุณก็สามารถใช้สิ่งที่คุณต้องตัดมุมบางส่วนโดยทำส่วนเล็ก ๆ ก่อนสำหรับพาร์ติชั่นสองสามตัวแรก


โปรดแก้ไขฉันหากฉันผิดทำไมคุณถึงดำเนินการผสาน 99-way กับข้อมูลเมื่อมาถึงเพื่อทิ้งในภายหลัง มันเพียงพอหรือไม่ที่จะนับจำนวนเมื่อมาถึง?
sreeprasad

4
@SREEPRASADGOVINDANKUTTY: ขั้นตอนการทำซ้ำคือการทิ้งค่าที่น้อยที่สุดจากผู้สมัครทั้งหมด 99 ตัวและเพิ่มจำนวน ไม่มีประโยชน์เลยที่จะเก็บค่าที่เข้ามาทั้งหมดไว้โดยไม่มีขั้นตอนการผสาน 99 ทางนี้ หากคุณไม่เปรียบเทียบสิ่งเหล่านี้คุณจะไม่รู้ว่าค่าที่คุณทิ้งนั้นต่ำกว่าค่ามัธยฐาน
Steve Jessop

แต่ไม่มีโอกาสเล็กน้อยที่พาร์ติชันใด ๆ เหล่านี้มีเพียงตัวเลขที่สูงกว่าค่ามัธยฐานดังนั้นพาร์ติชันที่ต่ำกว่าใด ๆ ที่ส่งกลับจะสูงกว่าค่ามัธยฐาน แต่เนื่องจากการควบคุมไม่ทราบว่าสิ่งนี้จะทิ้งพวกเขาในฐานะที่ต่ำกว่า มัธยฐานและล้มเหลว ... ?
Gullydwarf

@Gullydwarf: การผสานแบบหลายทางจะละทิ้งเฉพาะค่าที่น้อยที่สุดของ 99 ที่มีอยู่ในมือซึ่งแต่ละค่าเป็นค่าที่เหลือน้อยที่สุดจากเครื่องอื่นเครื่องใดเครื่องหนึ่ง หากพาร์ติชันใดพาร์ติชันหนึ่งมีค่ามากกว่าค่ามัธยฐานทั้งหมดจะไม่กลายเป็นค่าต่ำสุดของ 99 ค่าเหล่านั้นจนกว่าค่ามัธยฐานจะผ่านไปแล้ว (ณ จุดนั้นเราทำเสร็จแล้ว) ดังนั้นจะไม่ถูกทิ้ง
Steve Jessop

52
sort -g numbers | head -n 500000001 | tail -n 2 | dc -e "1 k ? ? + 2 / p"

2
ฮ่า ๆ. มันใช้งานได้จริงหรือ OOM killer จะทำลายมันก่อนที่มันจะเสร็จสมบูรณ์? (บนคอมพิวเตอร์ที่เหมาะสม)
Isak Savo

5
ควรทำ. การเรียงลำดับรู้วิธีการจัดเรียงแบบไม่ใช้แกนหลักดังนั้นหน่วยความจำจะไม่หมด
DrPizza

6
@ Zagfai ไม่คิดว่าจะใช้เวลานานเกินไป ตัวเลขพันล้านมีเพียง 4 GB สำหรับ ints / floats 32 บิต 8GB สำหรับ ints 64 บิต / คู่ ดูเหมือนว่าจะไม่ต้องเสียภาษีอย่างมาก
DrPizza

13
เพิ่งลองใช้ Intel i5-4200M @ 3.1 GHz (4 คอร์) ตามtimeคำสั่งที่ใช้กับไปป์ไลน์ทั้งหมดใช้เวลาreal=36m24s("เวลานาฬิกาแขวน"), user=113m15s ("เวลาขนาน", เพิ่มแกนทั้งหมด) คำสั่งที่ยาวที่สุดเหนือกว่าคำสั่งอื่น ๆ คือsortแม้ว่ามันจะเชื่อมต่อกับสี่คอร์ของฉันที่ 100% การใช้ RAM เป็นที่ยอมรับมาก
Morgan Touverey Quilling

12
แล้วทำงานใน 100 คอมพิวเตอร์เพื่อให้คุณสามารถเป็น 100 ครั้งแน่ใจมากขึ้นว่าผลที่ถูกต้อง :)
ดอส

27

ฉันเกลียดที่จะเป็นคนตรงกันข้ามที่นี่ แต่ฉันไม่เชื่อว่าจำเป็นต้องมีการเรียงลำดับและฉันคิดว่าอัลกอริทึมใด ๆ ที่เกี่ยวข้องกับการเรียงลำดับตัวเลขพันล้าน / 100 นั้นจะช้า ลองพิจารณาอัลกอริทึมบนคอมพิวเตอร์เครื่องหนึ่ง

1) เลือก 1,000 ค่าโดยการสุ่มจากพันล้านและใช้เพื่อรับแนวคิดเกี่ยวกับการกระจายของตัวเลขโดยเฉพาะช่วง

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

3) ค้นหาว่าค่ามัธยฐานอยู่ในช่วงถังใด ซึ่งทำได้โดยเพียงแค่ตรวจสอบตัวเลขทั้งหมดในแต่ละที่เก็บข้อมูล

4) ค้นหาค่ามัธยฐานที่แท้จริงโดยการตรวจสอบค่าในที่เก็บข้อมูลนั้น คุณสามารถใช้การจัดเรียงได้ที่นี่หากคุณต้องการเนื่องจากคุณจัดเรียงตัวเลขได้ 10,000 ตัว หากจำนวนค่าในที่เก็บข้อมูลมีขนาดใหญ่คุณสามารถใช้อัลกอริทึมนี้ได้อีกครั้งจนกว่าจะมีจำนวนน้อยพอที่จะจัดเรียง

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

กระบวนการทั้งหมดคือ O (n) เนื่องจากทั้งสองขั้นตอนที่ 3 และ 4 นั้นไม่สำคัญหากจำนวนที่เก็บข้อมูลมีมากพอ


1
ฉันคิดว่านี่เป็นสิ่งที่อยู่ระหว่างค่ามัธยฐานของค่ามัธยฐานกับอัลกอริทึมการเลือกอย่างรวดเร็ว en.wikipedia.org/wiki/Selection_algorithm
Dimath

ในขั้นตอนที่ 4 ที่เก็บข้อมูลอาจไม่มีเพียง 10,000 อาจเป็นกรณีที่การกระจายเบ้ไปทางตรงกลางซึ่งอาจมีข้อมูล 80% ซึ่งยังมากอยู่
justhalf

แก้ไขเพื่อคำนึงถึงสิ่งนั้น
DJClayworth

4
ประสิทธิภาพไม่ใช่ O (n) ในอัลกอริทึมนี้คุณอาจมีตัวเลขส่วนใหญ่อยู่ในที่เก็บข้อมูล "ค่ามัธยฐาน" และอาจทำงานได้ไม่ดีพอ ๆ กับการเรียงลำดับทุกอย่าง
Sklivvz

1
@WULF คำถามที่ยอดเยี่ยม เป็นกุญแจสำคัญในอัลกอริทึมและขั้นตอนที่ 1 จะกล่าวถึงมัน การสุ่มตัวอย่างตัวเลขเพื่อสร้างการกระจายเป็นสิ่งที่ดีที่สุดที่ฉันคิดขึ้นมา
DJClayworth

12

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

public class Median {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        int[] numbers = new int[1_000_000_000];

        System.out.println("created array after " +  (System.currentTimeMillis() - start) + " ms");

        Random rand = new Random();
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = rand.nextInt();
        }

        System.out.println("initialized array after " + (System.currentTimeMillis() - start) + " ms");

        Arrays.sort(numbers);

        System.out.println("sorted array after " + (System.currentTimeMillis() - start) + " ms");

        if (numbers.length % 2 == 1) {
            System.out.println("median = " + numbers[numbers.length / 2 - 1]);
        } else {
            int m1 = numbers[numbers.length / 2 - 1];
            int m2 = numbers[numbers.length / 2];
            double m = ((long) m1 + m2) / 2.0;
            System.out.println("median = " + new DecimalFormat("#.#").format(m));
        }
}

เอาต์พุตบนเครื่องของฉัน:

created array after 518 ms
initialized array after 10177 ms
sorted array after 102936 ms
median = 19196

ดังนั้นสิ่งนี้จะเสร็จสมบูรณ์ในเครื่องของฉันภายในเวลาไม่ถึงสองนาที (1:43 ซึ่ง 0:10 คือการสร้างตัวเลขสุ่ม) โดยใช้คอร์เดียวและมันก็จัดเรียงแบบเต็มด้วยซ้ำ ไม่มีอะไรแฟนซีจริงๆ

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


นี่คือสิ่งที่ฉันพูดในคำตอบของฉันที่นี่ :-) stackoverflow.com/a/31819222/363437
vidstige

1
@vidstige ฉันไม่ได้อ่านจริงๆ แต่คุณพูดถูก คำตอบของฉันอยู่ในมือมากขึ้นอย่างแน่นอนซึ่งผู้คนดูเหมือนจะชื่นชมมากกว่าเล็กน้อย;)
sfussenegger

ที่ไม่ว่าเฉลี่ยค่ามัธยฐานคือ(numbers[numbers.length / 2]+numbers[numbers.length / 2+1])/2ถ้าnumbers.lengthแม้แต่และnumbers[numbers.length / 2]เฉพาะในกรณีที่numbers.lengthเป็นเลขคี่
Sklivvz

@Sklivvz ถูกต้อง แต่ไม่ควรสังเกตเห็นได้ชัดเจนส่งผลกระทบต่อเวลาที่ใช้ในการคำนวณค่ามัธยฐาน
vidstige

1
@Sklivvz คุณพูดถูกแน่นอน ฉันเพิ่งอัปเดตการคำนวณค่ามัธยฐาน มันไม่ได้เปลี่ยนคำตอบที่เหลือ
sfussenegger

10

การประมาณสถิติการสั่งซื้อเช่นค่ามัธยฐานและเปอร์เซ็นไทล์ที่ 99 สามารถกระจายได้อย่างมีประสิทธิภาพด้วยอัลกอริทึมเช่นt-DigestหรือQ-Digest Q-ย่อย

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

วิธีนี้ใช้โดยelasticsearchและคาดว่าBigQuery (ตามคำอธิบายของฟังก์ชัน QUANTILES)


5

ค่ามัธยฐานสำหรับชุดตัวเลขนี้

2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89, 97

คือ 67.

ค่ามัธยฐานสำหรับชุดตัวเลขนี้

2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89

คือ 40.

สมมติว่าคำถามมีค่าประมาณ 1,000,000,000 จำนวนเต็ม (x) โดยที่ 0> = x <= 2,147,483,647 และ OP กำลังมองหา (องค์ประกอบ (499,999,999) + องค์ประกอบ (500,000,000)) / 2 (หากเรียงตัวเลข) สมมติว่าคอมพิวเตอร์ทั้ง 100 เครื่องมีค่าเท่ากันทั้งหมด

ใช้แล็ปท็อปและ GigE ...

สิ่งที่ฉันพบคือแล็ปท็อปของฉันสามารถเรียงลำดับ 10,000,000 Int32 ใน 1.3 วินาที ดังนั้นการประมาณคร่าวๆก็คือการเรียงลำดับตัวเลขพันล้านจะใช้เวลา 100 x 1.3 วินาที (2 นาที 10 วินาที);)

ค่าประมาณของการถ่ายโอนไฟล์ทางเดียวของไฟล์ 40MB บนกิกะบิตอีเทอร์เน็ตคือ. 32 วินาที ซึ่งหมายความว่าผลลัพธ์ที่เรียงลำดับจากคอมพิวเตอร์ทุกเครื่องจะถูกส่งกลับในเวลาประมาณ 32 วินาที (คอมพิวเตอร์ 99 ไม่ได้รับไฟล์ของเขาจนกว่า 30 วินาทีหลังจากเริ่ม) จากนั้นไม่ควรใช้เวลานานในการทิ้งหมายเลขต่ำสุด 499,999,998 หมายเลขเพิ่ม 2 ถัดไปและหารด้วย 2


3
ความคิดเห็นของผู้มีสิทธิเลือกตั้งลง? มันจะช่วยให้ฉันเข้าใจว่าฉันจะทำได้ดีขึ้นได้อย่างไร
dbasnett

5
ฉันไม่ใช่ผู้มีสิทธิเลือกตั้ง แต่การเรียงลำดับตัวเลขพันล้านจะไม่ใช้เวลา 100 เท่าตราบเท่าที่การเรียงลำดับ 10 ล้านเนื่องจากความซับซ้อนของกรณีที่เลวร้ายที่สุดในการจัดเรียงรายการคือ O (n log n) การเรียงลำดับยังเป็นลำดับขนาดที่ช้าลงเมื่อหน่วยความจำหมดและต้องเริ่มการเรียงลำดับบนดิสก์
Richard Poole

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

สมมติว่ามีปัจจัยเดียวกัน (ซึ่งอาจไม่ได้เกิดจากปัญหาหน่วยความจำ) จากนั้นa*(1e7)log(1e7) = 1.3sec=> a = 1.6e-9sec => a*(1e9)log(1e9) ~ 167secดังนั้นการประมาณของคุณจึงไม่ผิดพลาด
bcorso

การประมาณค่าของคุณหยาบเกินไป ประการแรกอัลกอริธึมการเรียงลำดับบางส่วนไปเป็น o (n ^ 2) ในกรณีที่เลวร้ายที่สุด (เช่น Quicksort ที่ใช้กันทั่วไป) ประการที่สองคุณได้เลือกชุดข้อมูลทดสอบซึ่งมีขนาดประมาณแคช L2 ของคุณ สิ่งนี้จะบิดเบือนผลลัพธ์ ประการที่สามคุณ (เช่นเดียวกับผู้ตอบคำถามอื่น ๆ ) ถือว่า "number" หมายถึง "จำนวนเต็ม" อาจหมายถึงทศนิยมสองเท่าหรือทศนิยมซึ่งมีลักษณะการทำงานที่แตกต่างกันมาก
Sklivvz

5

สิ่งนี้อาจทำให้ผู้คนประหลาดใจ แต่ถ้าตัวเลขเป็นจำนวนเต็มเล็กพอที่จะใส่ใน 32 บิต (หรือน้อยกว่า) - เพียงแค่จัดเรียงถัง! ต้องการ RAM 16GB สำหรับอินเทอร์เฟซ 32 บิตจำนวนเท่าใดก็ได้และทำงานใน O (n) ซึ่งควรมีประสิทธิภาพดีกว่าระบบกระจายใด ๆ สำหรับ n ที่สมเหตุสมผลเช่นพันล้าน

เมื่อคุณมีรายการที่จัดเรียงแล้วการเลือกค่ามัธยฐานเป็นเรื่องเล็กน้อย ในความเป็นจริงคุณไม่จำเป็นต้องสร้างรายการที่เรียงลำดับ แต่ดูเฉพาะที่เก็บข้อมูลเท่านั้นที่ควรทำ

การใช้งานอย่างง่ายแสดงไว้ด้านล่าง ใช้ได้กับจำนวนเต็ม 16 บิตเท่านั้น แต่การขยายเป็น 32 บิตควรทำได้ง่าย

#include <stdio.h>
#include <string.h>

int main()
{
    unsigned short buckets[65536];
    int input, n=0, count=0, i;

    // calculate buckets
    memset(buckets, 0, sizeof(buckets));
    while (scanf("%d", &input) != EOF)
    {
        buckets[input & 0xffff]++;
        n++;
    }

    // find median 
    while (count <= n/2)
    {
        count += buckets[i++];
    }

    printf("median: %d\n", i-1);

    return 0;
}

ใช้ไฟล์ข้อความที่มีตัวเลขเป็นพันล้าน (10 9 ) และทำงานด้วยtimeเช่นนั้น

time ./median < billion

ให้เวลาทำงานบนเครื่องของฉัน 1m49.293s เวลาในการทำงานส่วนใหญ่อาจเป็นดิสก์ IO เช่นกัน


สิ่งนี้ไม่ได้ตอบคำถามจริงๆและขึ้นอยู่กับสมมติฐาน ตัวอย่างเช่นคุณไม่รู้ด้วยซ้ำว่าพวกมันเป็นจำนวนเต็ม
Sklivvz

ไม่ตอบคำถามในทางใด และใช่คำตอบของฉันถือว่าตัวเลขเป็นจำนวนเต็ม ฉันพยายามระบุสมมติฐานของฉันอย่างชัดเจน
vidstige

ดูเหมือนคุณจะไม่ได้ระบุว่าการมีจำนวนเต็มเป็นข้อสันนิษฐานและคุณไม่ได้ระบุวิธีการใช้คอมพิวเตอร์ 100 เครื่องที่ OP ถามถึง คุณสามารถคำนวณค่ามัธยฐานในโหนดเดียวได้ แต่นั่นไม่ใช่วิธีที่ "ดีที่สุด" เว้นแต่คุณจะแสดงสาเหตุ นอกจากนี้การเรียงลำดับของ radix จะไม่เป็น o (n) หากจำนวนหลักแตกต่างกันไปซึ่งในกรณีนี้แน่นอนตามen.wikipedia.org/wiki/Radix_sort#Efficiencyก็คือ o (n log n)
Sklivvz

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

1
สิ่งที่คุณทำกับคอมพิวเตอร์อีก 99 เครื่องไม่เกี่ยวข้องกับคำตอบนี้ คุณสามารถวางซ้อนกันเพื่อสร้างปิรามิดหรือเผา หรือไม่สนใจพวกเขา
vidstige

3

ฉันคิดว่าถ้าคุณมีคอมพิวเตอร์เพียงพอคุณจะคัดแยกได้ดีกว่าการใช้O(n)อัลกอริทึมการค้นหาค่ามัธยฐาน (แม้ว่าคอร์ของคุณจะช้ามาก แต่ฉันก็ใช้เพียงอันเดียวและใช้O(n)อัลกอริทึมการค้นหาค่ามัธยฐานสำหรับตัวเลข 1e9 เท่านั้น แต่ถ้าคุณมี 1e12 นั่นอาจจะใช้งานได้น้อยกว่า)

อย่างไรก็ตามสมมติว่าเรามีแกนล็อก n มากกว่าที่จะจัดการกับปัญหานี้และเราไม่สนใจเรื่องการใช้พลังงานเพียงแค่ได้รับคำตอบอย่างรวดเร็ว สมมติว่านี่คือเครื่อง SMP ที่มีข้อมูลทั้งหมดที่โหลดไว้แล้วในหน่วยความจำ (เครื่อง 32 คอร์ของ Sun เป็นประเภทนี้เป็นต้น)

ด้ายเส้นหนึ่งจะสับรายการให้เป็นชิ้นขนาดเท่า ๆ กันแบบสุ่มสี่สุ่มห้าและบอกให้เธรด M อื่นเรียงลำดับ กระทู้เหล่านั้นทำอย่างขยันขันแข็ง(n/M) log (n/M)ทันเวลา จากนั้นพวกเขาไม่เพียงส่งกลับค่ามัธยฐานของพวกเขา แต่ยังกล่าวว่าเปอร์เซ็นไทล์ที่ 25 และ 75 ของพวกเขาด้วย (กรณีที่เลวร้ายที่สุดในทางที่ผิดจะดีกว่าถ้าคุณเลือกตัวเลขที่แตกต่างกันเล็กน้อย ตอนนี้คุณมีช่วงข้อมูล 4M จากนั้นคุณจัดเรียงช่วงเหล่านี้และทำงานในรายการจนกว่าคุณจะพบตัวเลขดังกล่าวหากคุณทิ้งทุกช่วงที่มีขนาดเล็กกว่าหรือมีตัวเลขอยู่คุณจะทิ้งข้อมูลของคุณไปครึ่งหนึ่ง นั่นคือขอบเขตล่างของคุณสำหรับค่ามัธยฐาน ทำเช่นเดียวกันสำหรับขอบเขตบน การดำเนินการนี้ต้องใช้M log Mเวลาและคอร์ทั้งหมดต้องรอดังนั้นจึงสิ้นเปลืองมากM^2 log Mเวลาที่เป็นไปได้ ตอนนี้คุณมีเธรดเดียวของคุณแล้วบอกให้คนอื่นโยนข้อมูลทั้งหมดนอกช่วง (คุณควรทิ้งประมาณครึ่งหนึ่งในแต่ละรอบ) และทำซ้ำ - นี่เป็นการดำเนินการที่รวดเร็วเล็กน้อยเนื่องจากข้อมูลได้รับการจัดเรียงแล้ว คุณไม่ควรทำสิ่งนี้ซ้ำหลายlog(n/M)ครั้งก่อนที่จะเร็วขึ้นเพียงแค่ดึงข้อมูลที่เหลือและใช้O(n)เครื่องมือค้นหาค่ามัธยฐานมาตรฐาน

ดังนั้นความซับซ้อนทั้งหมดจึงเป็นเช่นO((n/M) log (n/M) + M^2 log M log (n/M))นั้น ดังนั้นนี่จึงเร็วกว่าการO(n)จัดเรียงค่ามัธยฐานในหนึ่งคอร์ถ้าM >> log(n/M)และM^3 log M < nซึ่งเป็นจริงสำหรับสถานการณ์ที่คุณอธิบายไว้

ฉันคิดว่านี่เป็นความคิดที่ไม่ดีจริงๆเนื่องจากมันไม่มีประสิทธิภาพ แต่มันเร็วกว่า


o (n / M log (n / M)) คือตามตัวอักษร o (n log n) เพราะ o (n / M log (n / M)) = 1 / M o (n (log n - log M) ) = o (n บันทึก n) คุณไม่สามารถเปรียบเทียบกับ o (n) แบบนั้นได้จริง ๆ เนื่องจาก "o" โดยพื้นฐานแล้วหมายถึง "ตามสัดส่วนสำหรับ n ขนาดใหญ่มากโดยมีค่าคงที่ที่ไม่ระบุ" หากคุณไม่ทราบค่าคงที่เหล่านี้คุณจะไม่สามารถเปรียบเทียบได้อย่างไรก็ตามสำหรับ N ที่มากพอค่าคงที่จะไม่เด่น สำหรับตัวเลขที่ต่ำกว่าการเดิมพันทั้งหมดจะถูกปิด o (1) สามารถช้ากว่า o (n!) ได้อย่างง่ายดาย
Sklivvz

@Sklivvz - nและMเป็นตัวแปรที่สามารถปรับขนาดได้ตามอำเภอใจดังนั้นจึงมีทั้งสองอย่าง โดยเฉพาะอย่างยิ่งฉันตั้งกระทู้ว่าM> log nหมายความว่าถ้าคุณสนใจว่ามันn log nไม่ใช่แค่nคุณต้องใส่ใจMด้วย
Rex Kerr

3

สิ่งนี้สามารถทำได้เร็วกว่าอัลกอริทึมโหวต (n log n)

- สถิติลำดับขั้นตอนวิธีการเลือกแบบกระจาย - O (n)
ลดความซับซ้อนของปัญหาให้เป็นปัญหาเดิมในการค้นหาหมายเลข kth ในอาร์เรย์ที่ไม่เรียงลำดับ
- การนับฮิสโตแกรมการเรียงลำดับ O (n)
คุณต้องถือว่าคุณสมบัติบางอย่างเกี่ยวกับช่วงของตัวเลข - ช่วงนั้นพอดีกับหน่วยความจำหรือไม่? - การเรียงลำดับการผสานภายนอก - O (n log n) - อธิบายไว้ข้างต้น
โดยทั่วไปคุณเรียงลำดับตัวเลขในรอบแรกจากนั้นหาค่ามัธยฐานของวินาที
- หากทราบสิ่งใดเกี่ยวกับการแจกแจงตัวเลขอัลกอริทึมอื่น ๆ ก็สามารถสร้างได้

สำหรับรายละเอียดเพิ่มเติมและการใช้งานโปรดดู:
http://www.fusu.us/2013/07/median-in-large-set-across-1000-servers.html


2

คอมพิวเตอร์เครื่องเดียวเกินพอที่จะแก้ปัญหาได้

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

จากนั้นนำตัวเลขจากตรงกลางของรายการที่จัดเรียง (เช่นด้วยดัชนี 5000 000 000)


3
อย่างไรก็ตามตอนนี้ตัวแทนของฉันค่อนข้างกลม :)
Roman

การรวมอยู่ที่ O (n) ที่ดีที่สุดและคุณสามารถหาค่ามัธยฐานบนคอร์เดียวใน O (n) ได้ดังนั้นสิ่งนี้จึงดูเหมือนจะสร้างงานพิเศษมากมายโดยไม่ได้รับผลตอบแทน
Rex Kerr

2

ขึ้นอยู่กับข้อมูลของคุณ สถานการณ์ในกรณีที่เลวร้ายที่สุดคือตัวเลขที่กระจายอย่างสม่ำเสมอ

ในกรณีนี้คุณสามารถหาค่ามัธยฐานในเวลา O (N) ดังตัวอย่างนี้:

สมมติว่าตัวเลขของคุณคือ 2,7,5,10,1,6,4,4,6,10,4,7,1,8,4,9,9,3,4,3 (ช่วงคือ 1-10) .

เราสร้าง 3 ถัง: 1-3, 4-7, 8-10 สังเกตว่าด้านบนและด้านล่างมีขนาดเท่ากัน

เราเติมที่เก็บข้อมูลด้วยตัวเลขนับจำนวนตกในแต่ละค่าสูงสุดและต่ำสุด

  • ต่ำ (5): 2,1,1,3,3 นาที 1 สูงสุด 3
  • กลาง (10): 7,5,6,4,4,6,4,7,4,4 ขั้นต่ำ 4 สูงสุด 7
  • สูง (5): 10, 10, 8, 9, 9, ต่ำสุด 8, สูงสุด 10

ค่าเฉลี่ยตกอยู่ในถังกลางเราไม่สนใจส่วนที่เหลือ

เราสร้าง 3 ที่เก็บ: 4, 5-6, 7 ต่ำจะเริ่มต้นด้วยการนับ 5 และสูงสุด 3 และสูงด้วยขั้นต่ำ 8 และจำนวน 5

สำหรับแต่ละหมายเลขเราจะนับจำนวนที่ตกในถังต่ำและสูงสูงสุดและต่ำสุดและเก็บถังกลางไว้

  • เก่าต่ำ (5)
  • ต่ำ (5): 4, 4, 4, 4, 4, สูงสุด 4
  • กลาง (3): 5,6,6
  • สูง (2): 7, 7, นาที 7
  • สูงเก่า (5)

ตอนนี้เราสามารถคำนวณค่ามัธยฐานได้โดยตรงเรามีสถานการณ์เช่นนี้

old low    low          middle  high  old high
x x x x x  4 4 4 4 4 4   5 6 6  7 7   x x x x x

ดังนั้นค่ามัธยฐานคือ 4.5

สมมติว่าคุณทราบข้อมูลเล็กน้อยเกี่ยวกับการกระจายคุณสามารถปรับแต่งวิธีกำหนดช่วงเพื่อเพิ่มความเร็วได้ ไม่ว่าในกรณีใดประสิทธิภาพควรไปพร้อมกับ O (N) เนื่องจาก 1 + 1/3 + 1/9 ... = 1.5

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

การดำเนินการทั้งหมดเหล่านี้สามารถขนานกันได้คุณสามารถให้ 1/100 ของข้อมูลกับคอมพิวเตอร์แต่ละเครื่องและคำนวณ 3 ที่เก็บข้อมูลในแต่ละโหนดจากนั้นกระจายที่เก็บข้อมูลที่คุณเก็บไว้ สิ่งนี้ทำให้คุณใช้เครือข่ายได้อย่างมีประสิทธิภาพอีกครั้งเนื่องจากแต่ละหมายเลขมีการส่งผ่านโดยเฉลี่ย 1.5 ครั้ง (ดังนั้น O (N)) คุณสามารถเอาชนะได้หากคุณส่งเฉพาะตัวเลขที่น้อยที่สุดระหว่างโหนด (เช่นถ้าโหนด 1 มี 100 หมายเลขและโหนด 2 มี 150 หมายเลขดังนั้นโหนด 2 สามารถให้ 25 หมายเลขไปยังโหนด 1)

หากคุณไม่ทราบข้อมูลเพิ่มเติมเกี่ยวกับการกระจายฉันสงสัยว่าคุณทำได้ดีกว่า O (N) ที่นี่เพราะคุณต้องนับองค์ประกอบอย่างน้อยหนึ่งครั้ง


1
ไม่ใช่กรณีที่แย่กว่าจริง (สำหรับอัลกอริทึมของคุณ) เมื่อตัวเลขทั้งหมดเท่ากัน? ถ้าฉันถูกต้องไม่มีที่เก็บข้อมูลของคุณเลยที่จะเติมเต็มนอกเหนือจากที่อยู่ตรงกลางโดยมีองค์ประกอบทั้งหมด ดังนั้นคุณจะต้องสำรวจองค์ประกอบทั้งหมดในแต่ละครั้งโดยก้าวหน้าอย่างรวดเร็วไปยังช่วงกลางของช่วงเวลา ฉันเชื่อว่ามันจะเป็นO(n log n)เช่นนั้น มันเข้าท่าไหม? ฉันชอบความคิดของคุณ
Dici

1
@Dici ไม่จริง: ประการแรกคุณสามารถลัดสถานการณ์ "เหมือนกันทั้งหมด" ได้อย่างง่ายดายเพราะคุณรู้ขั้นต่ำและสูงสุด ดังที่ฉันได้กล่าวในคำตอบการรู้ว่าการกระจายสามารถผลักดันตัวเลือกการจัดเก็บข้อมูลของคุณได้ ประการที่สองก็ยังคงใช้o(n)+o(n/3)+o(n/9)+...ซึ่งยังคงอยู่และไม่ได้o(n) o(n log n)
Sklivvz

ในทางกลับกันอาจมีสถานการณ์ที่เลวร้ายที่สุดแตกต่างกันคือการแจกแจงรูปตัวยู ฉันต้องคิดเกี่ยวกับเรื่องนี้ให้เป็นทางการในกรณีที่เลวร้ายที่สุด แต่อาจเลวร้ายยิ่งกว่าo(n)ในกรณีนั้นด้วยการแบ่งพาร์ติชันที่ไร้เดียงสา
Sklivvz

อืมนาทีและแม็กซ์จะช่วยจัดการคดี "เดียวกันทั้งหมด" ได้อย่างง่ายดาย
Dici

2

วิธีที่ง่ายกว่าคือการมีตัวเลขถ่วงน้ำหนัก

  • แยกชุดใหญ่ในคอมพิวเตอร์
  • เรียงลำดับแต่ละชุด
  • วนซ้ำผ่านชุดเล็กและคำนวณน้ำหนักให้กับองค์ประกอบที่ซ้ำ
  • รวมแต่ละชุด 2 ชุดเป็น 1 (แต่ละชุดเรียงลำดับแล้ว) อัปเดตน้ำหนัก
  • รวมชุดต่อไปจนกว่าคุณจะได้ชุดเดียว
  • ทำซ้ำตามชุดนี้โดยสะสมน้ำหนักจนกว่าคุณจะไปถึง OneBillion / 2

1

แบ่งตัวเลข 10 ^ 9, 10 ^ 7 ให้กับคอมพิวเตอร์แต่ละเครื่อง ~ 80MB ในแต่ละเครื่อง คอมพิวเตอร์แต่ละเครื่องเรียงลำดับตัวเลข จากนั้นคอมพิวเตอร์ 1 จะเรียงลำดับตัวเลขของตัวเองกับคอมพิวเตอร์ที่ 2 คอมพิวเตอร์ 3 และ 4 ฯลฯ ... จากนั้นคอมพิวเตอร์ 1 จะเขียนตัวเลขครึ่งหนึ่งกลับไปเป็น 2, 3 ถึง 4 เป็นต้นจากนั้น 1 ผสานจะเรียงลำดับตัวเลขจากคอมพิวเตอร์ 1,2,3,4 เขียนกลับ และอื่น ๆ ขึ้นอยู่กับขนาดของ RAM ในคอมพิวเตอร์ที่คุณอาจหลีกเลี่ยงโดยไม่ได้เขียนตัวเลขทั้งหมดกลับไปที่คอมพิวเตอร์แต่ละเครื่องในแต่ละขั้นตอนคุณอาจสามารถสะสมตัวเลขในคอมพิวเตอร์ 1 ได้หลายขั้นตอน แต่คุณต้องคำนวณ

โอ้ในที่สุดก็ได้ค่าเฉลี่ยของค่า 500000000th และ 500000001st (แต่ตรวจสอบว่ามี 00 อยู่ในนั้นเพียงพอฉันไม่ได้ทำ)

แก้ไข: @ โรมัน - ถ้าคุณไม่สามารถเชื่อได้แม้ว่ามันจะเป็นความจริงก็ไม่มีประเด็นใดที่ฉันจะเปิดเผยความจริงหรือความเท็จของเรื่องนี้ สิ่งที่ฉันหมายถึงก็คือบางครั้งพลังเดรัจฉานก็เต้นอย่างฉลาดในการแข่งขัน ฉันใช้เวลาประมาณ 15 วินาทีในการประดิษฐ์อัลกอริทึมซึ่งฉันมั่นใจว่าสามารถนำไปใช้ได้ซึ่งจะใช้งานได้และจะปรับให้เข้ากับอินพุตและจำนวนคอมพิวเตอร์ที่หลากหลายและสามารถปรับให้เข้ากับลักษณะของคอมพิวเตอร์และ การจัดเตรียมเครือข่าย หากต้องใช้เวลาคุณหรือใครก็ตามพูดว่า 15 นาทีในการประดิษฐ์อัลกอริทึมที่ซับซ้อนยิ่งขึ้นฉันมีข้อได้เปรียบ 14m45s ในการเขียนโค้ดโซลูชันของฉันและเริ่มทำงาน

แต่ฉันยอมรับอย่างอิสระว่านี่คือการยืนยันทั้งหมดฉันไม่ได้วัดอะไรเลย


ที่นี่เรากำลังรวมตัวเลขทั้งหมดเข้าด้วยกัน เราจะทำวิธีที่ดีกว่านี้ได้ไหมโดยใช้: - "เราสามารถหาค่ามัธยฐานของรายการที่เรียงลำดับสองรายการในเวลาเข้าสู่ระบบได้ n คือความยาวของแต่ละรายการ"
anony

1
@anony - ในขณะที่คุณตอบคำถามของคุณเองฉันจะเข้ารหัสวิธีแก้ปัญหาทดสอบและทำเสร็จแล้ว ฉันคาดหวังว่าจะมีวิธีที่ดีกว่านี้ แต่บางครั้งการใช้วิธีง่ายๆแบบคู่ขนานทำให้ฉันมีอิสระที่จะเกาหัวกับปัญหาที่ยากจริงๆ
High Performance Mark

คุณทำได้จริงใน7นาทีหรือไม่? ไม่อยากจะเชื่อเลยว่าแม้ว่ามันจะเป็นเรื่องจริง ฉันทำงานที่คล้ายกันนี้ (เป็นงานมอบหมายของมหาวิทยาลัย) และใช้เวลาประมาณ 2 ชั่วโมงในการใช้งานและทดสอบการรีบูตสิ่งต่างๆทั้งหมด (ฉันใช้ java RMI)
โรมัน

ฉันเห็นว่าคุณกำลังพูดอะไร แต่ในทำนองเดียวกัน DrPizza มีวิธีแก้ปัญหาที่รวดเร็วยิ่งขึ้นซึ่งก็คือการจัดเรียงข้อมูลทั้งหมดในโหนดเดียวและไม่สนใจอีก 99 คนไม่มีใครรู้ว่าข้อมูลแพงแค่ไหน ควรพิจารณาการถ่ายโอนดังนั้นเราทุกคนเพียงแค่เลือกการประนีประนอมที่ฟังดูคลุมเครือ โซลูชันของคุณถ่ายโอนข้อมูลทั้งหมดหลายครั้งดังนั้นฉันจึงสงสัยเล็กน้อย แต่ก็เป็นวิธีแก้ปัญหาอย่างแน่นอน
Steve Jessop

'เป็นไปได้อย่างคลุมเครือ' - นั่นดีพอสำหรับฉันที่สตีฟ! โดยเฉพาะอย่างยิ่งในการตอบคำถามที่คลุมเครือไม่น่าเชื่อ
High Performance Mark

1

สิ่งนี้สามารถทำได้บนโหนดโดยใช้ข้อมูลที่ไม่ได้เรียงลำดับข้ามโหนด (พูดจากไฟล์บันทึก) ในลักษณะต่อไปนี้

มีโหนดแม่ 1 โหนดและโหนดลูก 99 โหนด โหนดลูกมีการเรียก API สองครั้ง:

  • stats (): คืนค่า min, max และ count
  • เปรียบเทียบ (median_guess): ส่งกลับค่าการจับคู่การนับนับน้อยกว่ามูลค่าและนับมากกว่ามูลค่า

โหนดแม่เรียกใช้ stats () บนโหนดลูกทั้งหมดโดยสังเกตค่าต่ำสุดและสูงสุดของโหนดทั้งหมด

ขณะนี้การค้นหาไบนารีสามารถทำได้ด้วยวิธีต่อไปนี้:

  1. ตัดทอนการปัดเศษต่ำสุดและสูงสุด - นี่คือค่ามัธยฐานของ 'การคาดเดา'
  2. ถ้าจำนวนมากกว่ามากกว่าจำนวนน้อยกว่าให้ตั้งค่าขั้นต่ำในการเดา
  3. ถ้าจำนวนมากกว่าน้อยกว่าจำนวนน้อยกว่าให้ตั้งค่าสูงสุดเป็นค่าคาดเดา
  4. หากนับเป็นเลขคี่เสร็จสิ้นเมื่อค่าต่ำสุดและสูงสุดเท่ากัน
  5. ถ้าการนับจะสิ้นสุดลงเมื่อสูงสุด <= ต่ำสุด + การคาดเดา Match_count สามารถทำได้บนโหนดโดยใช้ข้อมูลที่ไม่ได้เรียงลำดับ (พูดจากไฟล์บันทึก) ในลักษณะต่อไปนี้

มีโหนดแม่ 1 โหนดและโหนดลูก 99 โหนด โหนดลูกมีการเรียก API สองครั้ง:

  • stats (): คืนค่า min, max และ count
  • เปรียบเทียบ (median_guess): ส่งกลับค่าการจับคู่การนับนับน้อยกว่ามูลค่าและนับมากกว่ามูลค่า

โหนดแม่เรียกใช้ stats () บนโหนดลูกทั้งหมดโดยสังเกตค่าต่ำสุดและสูงสุดของโหนดทั้งหมด

ขณะนี้การค้นหาไบนารีสามารถทำได้ด้วยวิธีต่อไปนี้:

  1. ตัดทอนการปัดเศษต่ำสุดและสูงสุด - นี่คือค่ามัธยฐานของ 'การคาดเดา'
  2. ถ้าจำนวนมากกว่ามากกว่าจำนวนน้อยกว่าให้ตั้งค่าขั้นต่ำในการเดา
  3. ถ้าจำนวนมากกว่าน้อยกว่าจำนวนน้อยกว่าให้ตั้งค่าสูงสุดเป็นค่าคาดเดา
  4. หากนับเป็นเลขคี่เสร็จสิ้นเมื่อค่าต่ำสุดและสูงสุดเท่ากัน
  5. หากการนับสิ้นสุดลงเมื่อสูงสุด <= ขั้นต่ำ + การเดา Match_count

หากสถิติ () และการเปรียบเทียบ () สามารถคำนวณล่วงหน้าด้วยการเรียงลำดับ O (N / Mlogn / M) ดังนั้นการคำนวณล่วงหน้า O (N / M) ที่มีความซับซ้อนของหน่วยความจำ O (N) สำหรับค่าล่วงหน้า การคำนวณ จากนั้นคุณสามารถเปรียบเทียบ () ในเวลาคงที่ดังนั้นสิ่งทั้งหมด (รวมถึงการคำนวณล่วงหน้า) จะทำงานใน O (N / MlogN / M) + O (logN)

โปรดแจ้งให้เราทราบหากฉันทำผิดพลาด!


ใช่ฉันแค่ค้นหาไบนารี จะช่วยประหยัดแบนด์วิดท์เครือข่ายเฉพาะการเรียกคอมพิวเตอร์แต่ละเครื่องไม่กี่ครั้ง นอกจากนี้เครื่องแต่ละเครื่องอาจมี "เดือย" ซึ่งจะใช้แทนตัวเลขสลับด้านใดด้านหนึ่งของเดือยเพื่อประหยัดเวลา (pivot จะเป็นค่ามัธยฐานโดยประมาณก่อนหน้านี้ดังนั้นในครั้งต่อไปจะต้องผ่านตัวเลขทั้งหมดที่ด้านใดด้านหนึ่งของเดือยเท่านั้น)
เบิร์ตคิง

0

เกี่ยวกับสิ่งนี้ - แต่ละโหนดสามารถรับ 1 พันล้าน / 100 หมายเลข ในแต่ละโหนดสามารถจัดเรียงองค์ประกอบและหาค่ามัธยฐานได้ หาค่ามัธยฐานของค่ามัธยฐาน เราสามารถทำได้โดยการรวมจำนวนของตัวเลขที่น้อยกว่าค่ามัธยฐานของค่ามัธยฐานในทุกโหนดจะพบว่า x%: y% แยกซึ่งค่ามัธยฐานของค่ามัธยฐานทำ ตอนนี้ขอให้ทุกโหนดลบองค์ประกอบที่น้อยกว่าค่ามัธยฐานของค่ามัธยฐาน (เช่นการแบ่ง 30%: 70%) ตัวเลข 30% จะถูกลบ 70% ของ 1 พันล้านคือ 700 ล้าน ตอนนี้ทุกโหนดที่ลบน้อยกว่า 3 ล้านโหนดสามารถส่งโหนดพิเศษเหล่านั้นกลับไปที่คอมพิวเตอร์หลักได้ คอมพิวเตอร์หลักแจกจ่ายในลักษณะที่ตอนนี้ทุกโหนดจะมีจำนวนโหนดเกือบเท่ากัน (7 ล้าน) ตอนนี้ปัญหาลดลงเหลือ 700 ล้านเลขหมาย .... ดำเนินต่อไปจนกว่าเราจะมีชุดที่เล็กกว่าซึ่งสามารถคำนวณได้ในคอมพ์เครื่องเดียว


โดยพื้นฐานแล้วเรามักจะลดปัญหาที่ตั้งไว้อย่างน้อย 30% และเราประสบความสำเร็จในการประมวลผลแบบขนานจำนวนมากผ่านทางนี้ แต่ละโหนดเริ่มต้นด้วย 10 ล้านและลดข้อมูลที่ตั้งไว้ 30% ในการทำซ้ำแต่ละครั้ง
anony

ในการทำซ้ำครั้งแรกเรามองหาตัวเลข 500 ล้าน ในการทำซ้ำครั้งที่สอง - หากจำนวนตัวเลขที่ถูกลบคือ 300 ล้านเลขหมายเราจะมองหาตัวเลขที่ 200 ล้านและต่อไป ...
anony

2
ดูเหมือนว่ามาถูกทางแล้ว แต่คุณไม่ได้อธิบายอย่างชัดเจนว่าจะหลีกเลี่ยงการทิ้งค่ามัธยฐานไปโดยไม่ได้ตั้งใจด้วยการแบ่ง 30% / 70% ของคุณอย่างไร ใช้ตัวอย่างตัวอย่างต่อไปนี้สมมติว่า 29% แรกของคุณเป็นศูนย์ทั้งหมดและบล็อกอื่น ๆ ทั้งหมดนับได้ 1,000 และแต่ละชุดของบล็อกจะมากกว่าหนึ่งบล็อกสุดท้าย ค่ามัธยฐานเปอร์เซ็นไทล์ที่ 30 จะทิ้งข้อมูลทั้งหมด 29% และน้อยกว่าครึ่งหนึ่งของ 61% ของข้อมูลซึ่งเป็น 29 + 30% = 59% ของข้อมูล อ๊ะเราเพิ่งโยนค่ามัธยฐานที่แท้จริงออกไป! เห็นได้ชัดว่าคุณไม่ได้หมายความอย่างนั้นหรืออย่างน้อยคุณก็หมายความว่าฉลาดกว่าที่ฉันตีความ
Rex Kerr

0

ก่อนอื่นเรามาดูวิธีหาค่ามัธยฐานของจำนวน n บนเครื่องเดียว: โดยพื้นฐานแล้วฉันใช้กลยุทธ์การแบ่งพาร์ติชัน

ปัญหา: การเลือก (n, n / 2):ค้นหาเลขที่ n / 2 จากจำนวนน้อยที่สุด

คุณเลือกพูดองค์ประกอบกลาง k และแบ่งข้อมูลเป็น 2 อาร์เรย์ย่อย ที่ 1 มีองค์ประกอบทั้งหมด <k และ 2nd มีองค์ประกอบทั้งหมด> = k

ถ้า sizeof (อาร์เรย์ย่อยที่ 1)> = n / 2 คุณจะรู้ว่าอาร์เรย์ย่อยนี้มีค่ามัธยฐาน จากนั้นคุณสามารถโยนอาร์เรย์ย่อยที่ 2 ออกได้ แก้ปัญหาการเลือกนี้(ขนาดของอาร์เรย์ย่อยที่ 1, n / 2)2)

ในกรณีอื่นให้ทิ้ง subarray แรกนี้แล้วแก้ปัญหา เลือก (subarray ที่ 2, n / 2 - sizeof (subarray ที่ 1))

ทำซ้ำ ๆ

ความซับซ้อนของเวลาคือ O (n) เวลาที่คาดหวัง

ตอนนี้ถ้าเรามีหลายเครื่องในการทำซ้ำแต่ละครั้งเราต้องประมวลผลอาร์เรย์เพื่อแยกเรากระจายอาร์เรย์ไปยังเครื่องที่แตกต่างกัน แต่ละเครื่องประมวลผลกลุ่มอาร์เรย์และส่งข้อมูลสรุปกลับไปยังเครื่องควบคุมฮับเช่นขนาดของ subarray ที่ 1 และขนาดของ subarray ที่ 2 ฮับแมชชีนจะเพิ่มข้อมูลสรุปและตัดสินใจว่าจะใช้ซับเรย์ใด (ที่ 1 หรือ 2) เพื่อประมวลผลเพิ่มเติมและพารามิเตอร์ที่ 2 ของการเลือกและส่งกลับไปยังแต่ละเครื่อง และอื่น ๆ

อัลกอริทึมนี้สามารถใช้งานได้อย่างเรียบร้อยโดยใช้แผนที่ลด?

หน้าตาเป็นอย่างไร?


0

ฉันคิดว่าคำตอบของ Steve Jessop จะเร็วที่สุด

หากขนาดการถ่ายโอนข้อมูลเครือข่ายเท่ากับคอขวดนี่เป็นอีกแนวทางหนึ่ง

Divide the numbers into 100 computers (10 MB each). 
Loop until we have one element in each list     
    Find the meadian in each of them with quickselect which is O(N) and we are processing in parallel. The lists will be partitioned at the end wrt median.
    Send the medians to a central computer and find the median of medians. Then send the median back to each computer. 
    For each computer, if the overall median that we just computed is smaller than its median, continue in the lower part of the list (it is already partitioned), and if larger in the upper part.
When we have one number in each list, send them to the central computer and find and return the median.

32 MB ละคุณหมายถึง?
Dici

คุณหมายถึงอะไรโดยดำเนินการต่อในส่วนล่างของรายการ
Ruthvik Vaila

0

ฉันจะทำเช่นนี้:

ในการเริ่มต้นทั้งหมด 100 งานเพื่อค้นหาจำนวนสูงสุดและต่ำสุด คอมพิวเตอร์แต่ละเครื่องมีส่วนหนึ่งของฐานข้อมูล / ไฟล์ที่ค้นหา

เมื่อพบตัวเลขสูงสุดและต่ำสุดคอมพิวเตอร์เครื่องหนึ่งจะอ่านข้อมูลและกระจายตัวเลขแต่ละตัวเท่า ๆ กันไปยังส่วนที่เหลือของ 99 ตัวเลขจะกระจายตามช่วงเวลาที่เท่ากัน (หนึ่งอาจใช้จาก -100 ล้านถึง 0 อีกอัน - จาก 0 ถึง 100 ล้านเป็นต้น);

ในขณะที่รับหมายเลขคอมพิวเตอร์ 99 เครื่องแต่ละเครื่องจะจัดเรียงหมายเลขไว้แล้ว

จากนั้นหาค่ามัธยฐานได้ง่าย ... ดูว่าคอมพิวเตอร์แต่ละเครื่องมีตัวเลขทั้งหมดกี่ตัว (ผลรวมของจำนวนตัวเลขที่มีไม่ใช่ตัวเลข) หารด้วย 2 คำนวณว่าคอมพิวเตอร์เครื่องใดเป็นตัวเลขและดัชนีใด

:) voilla

ปล. ดูเหมือนจะมีความสับสนมากมายที่นี่ คนกลาง - เป็นหมายเลขที่อยู่ตรงกลางของรายการเรียงลำดับตัวเลข!


0

คุณสามารถใช้วิธีต้นไม้การแข่งขันเพื่อค้นหาค่ามัธยฐาน เราสามารถสร้างต้นไม้ที่มีโหนดลาได้ 1,000 โหนดเพื่อให้โหนดลีฟแต่ละโหนดเป็นอาร์เรย์ จากนั้นเราทำการแข่งขัน n / 2 ระหว่างอาร์เรย์ที่แตกต่างกันค่าบนรูทหลังจากการแข่งขัน n / 2 คือผลลัพธ์

http://www.geeksforgeeks.org/tournament-tree-and-binary-heap/


0

หากตัวเลขไม่แตกต่างกันและอยู่ในช่วงหนึ่งเท่านั้นนั่นคือการทำซ้ำดังนั้นวิธีแก้ปัญหาง่ายๆที่อยู่ในใจของฉันคือกระจายตัวเลขระหว่าง 99 เครื่องเท่า ๆ กันและให้เครื่องหนึ่งเป็นหลัก ตอนนี้ทุกเครื่องวนซ้ำไปมาบนตัวเลขที่กำหนดและเก็บจำนวนของแต่ละหมายเลขไว้ในชุดแฮช ทุกครั้งที่มีการทำซ้ำหมายเลขในชุดตัวเลขที่กำหนดให้กับคอมพิวเตอร์เครื่องนั้น ๆ ระบบจะอัปเดตจำนวนในชุดแฮช

จากนั้นเครื่องทั้งหมดจะคืนค่าแฮชไปยังเครื่องหลัก เครื่องหลักจะรวมชุดแฮชโดยรวมจำนวนคีย์เดียวกันที่พบในชุดแฮช ตัวอย่างเช่นชุดแฮชของเครื่อง # 1 มีรายการ ("1", 7) และชุดแฮชของเครื่อง # 2 มีรายการ ("1", 9) ดังนั้นเครื่องหลักเมื่อรวมชุดแฮชจะทำให้รายการเป็น ("1", 16) และอื่น ๆ

เมื่อรวมชุดแฮชแล้วให้เรียงลำดับคีย์และตอนนี้คุณสามารถค้นหารายการ (n / 2) และรายการ (n + 2/2) จากชุดแฮชที่เรียงลำดับได้อย่างง่ายดาย

วิธีนี้จะไม่เป็นประโยชน์หากตัวเลขหลักพันล้านแตกต่างกัน


0

สมมติว่าคุณรู้ว่าจำนวนจำนวนเต็มที่แตกต่างกันคือ (พูด) 4 พันล้านจากนั้นคุณสามารถรวมไว้ในที่เก็บข้อมูล 64k และรับจำนวนการกระจายสำหรับแต่ละที่เก็บข้อมูลจากแต่ละเครื่องในคลัสเตอร์ (คอมพิวเตอร์ 100 เครื่อง) รวมจำนวนทั้งหมดเหล่านี้ ตอนนี้ค้นหาที่เก็บข้อมูลที่มีค่ามัธยฐานและคราวนี้ขอเฉพาะที่เก็บข้อมูลสำหรับองค์ประกอบ 64k ที่จะอยู่ในที่เก็บข้อมูลเป้าหมายของคุณ สิ่งนี้ต้องใช้ O (1) (เฉพาะ 2) การค้นหาบน "คลัสเตอร์" ของคุณ : D


0

มูลค่าเงินของฉันหลังจากที่คนอื่นเลี้ยงดูมาหมดแล้ว:

การหาค่าเฉลี่ยในเครื่องเดียวเป็น O (N): https://en.wikipedia.org/wiki/Selection_algorithm

การส่งหมายเลข N ไปยัง 100 เครื่องก็เป็น O (N) เช่นกัน ดังนั้นเพื่อให้การใช้เครื่องจักร 100 เครื่องน่าสนใจการสื่อสารต้องค่อนข้างเร็วหรือ N มีขนาดใหญ่จนเครื่องเดียวไม่สามารถจัดการได้ในขณะที่ N / 100 สามารถทำได้หรือเราแค่ต้องการพิจารณาปัญหาทางคณิตศาสตร์โดยไม่ต้องกังวล datacommunication

เพื่อตัดสิ่งต่างๆให้สั้นลงฉันจะถือว่าภายในขอบเขตที่สมเหตุสมผลเราสามารถส่ง / แจกจ่ายตัวเลขได้โดยไม่ส่งผลกระทบต่อการวิเคราะห์ประสิทธิภาพ

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

  1. แต่ละเครื่องได้รับ N / 100 ของตัวเลขคำนวณค่ามัธยฐานของตัวเองและส่งข้อมูลนั้นไปยังต้นแบบ
  2. หลักจะรวบรวมรายการที่เรียงลำดับของค่ามัธยฐานที่แตกต่างกันทั้งหมดและส่งกลับไปยังแต่ละเครื่องโดยกำหนดลำดับของที่เก็บข้อมูลตามลำดับ (ในแต่ละเครื่องเหมือนกัน) หนึ่งรายการสำหรับค่ามัธยฐานแต่ละรายการ (ที่เก็บค่าเดียว) และอีกหนึ่งรายการสำหรับแต่ละช่วงเวลาระหว่าง ค่ามัธยฐานที่อยู่ติดกัน แน่นอนว่ายังมีที่เก็บข้อมูลระดับล่างและระดับบนสำหรับค่าที่ต่ำกว่าค่ามัธยฐานต่ำสุดและสูงกว่าค่าที่สูงที่สุด
  3. แต่ละเครื่องจะคำนวณจำนวนตัวเลขที่ตกอยู่ในแต่ละที่เก็บข้อมูลและสื่อสารข้อมูลนั้นกลับไปยังต้นแบบ
  4. ต้นแบบจะกำหนดที่เก็บข้อมูลที่มีค่ามัธยฐานจำนวนค่าที่ต่ำกว่า (โดยรวม) ซึ่งอยู่ต่ำกว่าที่เก็บข้อมูลนั้นและจำนวนที่สูงกว่า
  5. หากที่เก็บข้อมูลที่เลือกเป็นที่เก็บข้อมูลค่าเดียว (หนึ่งในค่ามัธยฐาน) ที่เก็บข้อมูลที่เลือกจะมีค่าเพียง 1 (N คี่) หรือ 2 (เลขคู่) เท่านั้นที่เราทำเสร็จแล้ว มิฉะนั้นเราจะทำซ้ำขั้นตอนข้างต้นด้วยการแก้ไข (ชัดเจน) ต่อไปนี้:
  6. เฉพาะตัวเลขจากที่เก็บข้อมูลที่เลือกเท่านั้นที่จะกระจายจากเครื่องต้นแบบไปยัง 100 เครื่องและยิ่งไปกว่านั้น
  7. เราจะไม่คำนวณค่ามัธยฐาน (ในแต่ละเครื่อง) แต่เป็นค่า k-th ซึ่งเราจะพิจารณาจำนวนตัวเลขที่สูงกว่าที่ถูกทิ้งไปจากผลรวมและจำนวนตัวเลขที่ต่ำกว่า ตามแนวคิดแล้วแต่ละเครื่องยังมีส่วนแบ่งของตัวเลขต่ำ / สูงที่ถูกทิ้งและคำนึงถึงสิ่งนั้นเมื่อคำนวณค่ามัธยฐานใหม่ในชุดที่ (ตามแนวคิด) รวมถึง (ส่วนแบ่งของ) ตัวเลขที่ทิ้ง

เวลาซับซ้อน:

  1. การคิดเพียงเล็กน้อยจะทำให้คุณมั่นใจได้ว่าในแต่ละขั้นตอนจำนวนค่าทั้งหมดที่ต้องวิเคราะห์จะลดลงอย่างน้อยสองปัจจัย (2 เป็นกรณีที่ค่อนข้างป่วยคุณอาจคาดหวังว่าจะลดได้ดีขึ้นอย่างมาก) จากสิ่งนี้เราจะได้รับ:
  2. สมมติว่าการหาค่ามัธยฐาน (หรือค่า k-th) ซึ่งเป็น O (N) ใช้เวลา c * N โดยที่ prefactor c ไม่แปรผันอย่างรุนแรงกับ N เพื่อที่เราจะได้นำมันไปเป็นค่าคงที่ในขณะนี้ จะได้ผลลัพธ์สุดท้ายไม่เกิน 2 * c * N / 100 ครั้ง การใช้เครื่องจักร 100 เครื่องทำให้เรามีปัจจัยเร่งความเร็ว 100/2 (เป็นอย่างน้อย)
  3. ตามที่กล่าวไว้ในตอนแรก: เวลาที่เกี่ยวข้องกับการสื่อสารหมายเลขระหว่างเครื่องอาจทำให้น่าสนใจยิ่งขึ้นที่จะทำทุกอย่างในเครื่องเดียว อย่างไรก็ตามหากเราใช้แนวทางแบบกระจายจำนวนทั้งหมดที่จะสื่อสารในทุกขั้นตอนรวมกันจะไม่เกิน 2 * N (N ในครั้งแรก <= N / 2 ครั้งที่สอง <= ครึ่งหนึ่งของจำนวนนั้น ที่สามและอื่น ๆ )

-1
  1. แบ่งตัวเลข 1 พันล้านออกเป็น 100 เครื่อง แต่ละเครื่องจะมีตัวเลข 10 ^ 7

  2. สำหรับแต่ละหมายเลขที่เข้าสู่เครื่องให้เก็บหมายเลขไว้ในแผนที่ความถี่หมายเลข -> นับ จัดเก็บหมายเลขขั้นต่ำในแต่ละเครื่องด้วย

  3. ค้นหาค่ามัธยฐานในแต่ละเครื่อง: เริ่มจากจำนวนขั้นต่ำในแต่ละเครื่องรวมจำนวนจนกว่าจะถึงดัชนีค่ามัธยฐาน ค่ามัธยฐานในแต่ละเครื่องจะเป็นค่าประมาณ น้อยกว่าและมากกว่า 5 * 10 ^ 6 ตัวเลข

  4. หาค่ามัธยฐานของค่ามัธยฐานทั้งหมดซึ่งจะน้อยกว่าและมากกว่าประมาณ 50 * 10 ^ 7 ซึ่งเป็นค่ามัธยฐานของ 1 พันล้านหมายเลข

ตอนนี้การเพิ่มประสิทธิภาพของขั้นตอนที่ 2: แทนที่จะเก็บไว้ในแผนที่ความถี่ให้เก็บจำนวนในอาร์เรย์บิตตัวแปร ตัวอย่างเช่น: ให้บอกว่าเริ่มจากจำนวนขั้นต่ำในเครื่องนี่คือการนับความถี่:

[min number] - 8 count
[min+1 number] - 7 count
[min+2 number] - 5 count

ข้างต้นสามารถจัดเก็บในบิตอาร์เรย์เป็น:

[min number] - 10000000
[min+1 number] - 1000000
[min+2 number] - 10000

โปรดทราบว่าโดยรวมแล้วจะมีค่าใช้จ่ายประมาณ 10 ^ 7 บิตสำหรับแต่ละเครื่องเนื่องจากแต่ละเครื่องจัดการกับตัวเลข 10 ^ 7 เท่านั้น 10 ^ 7bits = 1.25 * 10 ^ 6 ไบต์ซึ่งคือ 1.25MB

ดังนั้นด้วยวิธีการข้างต้นแต่ละเครื่องจะต้องมีพื้นที่ 1.25MB เพื่อคำนวณค่ามัธยฐานในเครื่อง และค่ามัธยฐานของค่ามัธยฐานสามารถคำนวณได้จากค่ามัธยฐานในพื้นที่ทั้งหมด 100 ค่าทำให้ได้ค่ามัธยฐานเป็น 1 พันล้านตัวเลข


เกิดอะไรขึ้นถ้าตัวเลขลอย?
Sklivvz

-1

ขอแนะนำวิธีคำนวณค่ามัธยฐานโดยประมาณ :) หากตัวเลขหนึ่งพันล้านนี้เรียงตามลำดับแบบสุ่มฉันคิดว่าฉันสามารถเลือก 1/100 หรือ 1/10 จากหนึ่งพันล้านหมายเลขแบบสุ่มเรียงลำดับด้วย 100 เครื่องจากนั้นเลือกค่ามัธยฐานของตัวเลขเหล่านั้น หรือแบ่งตัวเลขพันล้านออกเป็น 100 ส่วนให้แต่ละเครื่องเลือก 1/10 ของแต่ละส่วนแบบสุ่มคำนวณค่ามัธยฐานของพวกมัน หลังจากนั้นเรามี 100 ตัวเลขและเราสามารถคำนวณค่ามัธยฐานของตัวเลข 100 ได้ง่ายขึ้น แค่คำแนะนำฉันไม่แน่ใจว่าถูกต้องทางคณิตศาสตร์หรือไม่ แต่ฉันคิดว่าคุณสามารถแสดงผลลัพธ์ต่อผู้จัดการที่ไม่ค่อยเก่งคณิตศาสตร์ได้


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

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

โอเคหลังจากอ่านการบรรยายเกี่ยวกับสถิติแล้วฉันคิดว่าแนวคิดที่หยิบ 1/100 หรือแม้แต่ 1/1000 สุ่มจากตัวเลขหนึ่งพันล้านและคำนวณค่ามัธยฐานของพวกเขาก็ไม่เลว เป็นเพียงการคำนวณโดยประมาณเท่านั้น
lazyboy

-3

คำตอบของ Steve Jessop ผิด:

พิจารณาสี่กลุ่มต่อไปนี้:

{2, 4, 6, 8, 10}

{21, 21, 24, 26, 28}

{12, 14, 30, 32, 34}

{16, 18, 36, 38, 40}

ค่ามัธยฐานคือ 21 ซึ่งอยู่ในกลุ่มที่สอง

ค่ามัธยฐานของทั้งสี่กลุ่มคือ 6, 24, 30, 36 ค่ามัธยฐานทั้งหมดคือ 27

ดังนั้นหลังจากลูปแรกทั้งสี่กลุ่มจะกลายเป็น:

{6, 8, 10}

{24, 26, 28}

{12, 14, 30}

{16, 18, 36}

21 ถูกทิ้งอย่างไม่ถูกต้องแล้ว

อัลกอริทึมนี้รองรับเฉพาะกรณีที่มีสองกลุ่ม

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