एक पूर्णांक बनाएँ जो चार बिलियन दिए गए लोगों में से नहीं है


691

मुझे यह साक्षात्कार प्रश्न दिया गया है:

चार बिलियन पूर्णांकों के साथ एक इनपुट फ़ाइल को देखते हुए, एक पूर्णांक उत्पन्न करने के लिए एक एल्गोरिथ्म प्रदान करें जो फ़ाइल में निहित नहीं है। मान लें कि आपके पास 1 जीबी मेमोरी है। यदि आपके पास केवल 10 एमबी मेमोरी है तो आप क्या करेंगे, इसका पालन करें।

मेरा विश्लेषण:

फ़ाइल का आकार 4 × 10 9 × 4 बाइट्स = 16 जीबी है।

हम बाहरी छँटाई कर सकते हैं, इस प्रकार हमें पूर्णांकों की सीमा ज्ञात कर सकते हैं।

मेरा प्रश्न यह है कि छंटे हुए बड़े पूर्णांक सेटों में लापता पूर्णांक का पता लगाने का सबसे अच्छा तरीका क्या है?

मेरी समझ (सभी उत्तरों को पढ़ने के बाद):

मान लें कि हम 32-बिट पूर्णांक के बारे में बात कर रहे हैं, 2 32 = 4 * 10 9 अलग पूर्णांक हैं।

केस 1: हमारे पास 1 जीबी = 1 * 10 9 * 8 बिट्स = 8 बिलियन बिट्स मेमोरी है।

समाधान:

यदि हम एक अलग पूर्णांक का प्रतिनिधित्व करने वाले एक बिट का उपयोग करते हैं, तो यह पर्याप्त है। हमें सॉर्ट की जरूरत नहीं है।

कार्यान्वयन:

int radix = 8;
byte[] bitfield = new byte[0xffffffff/radix];
void F() throws FileNotFoundException{
    Scanner in = new Scanner(new FileReader("a.txt"));
    while(in.hasNextInt()){
        int n = in.nextInt();
        bitfield[n/radix] |= (1 << (n%radix));
    }

    for(int i = 0; i< bitfield.lenght; i++){
        for(int j =0; j<radix; j++){
            if( (bitfield[i] & (1<<j)) == 0) System.out.print(i*radix+j);
        }
    }
}

केस 2: 10 एमबी मेमोरी = 10 * 10 6 * 8 बिट्स = 80 मिलियन बिट्स

समाधान:

सभी संभव 16-बिट उपसर्गों के लिए, 2 16 संख्याओं के पूर्णांक = 65536 हैं, हमें 2 16 * 4 * 8 = 2 मिलियन बिट्स की आवश्यकता है। हमें 65536 बाल्टी बनाने की जरूरत है। प्रत्येक बाल्टी के लिए, हमें सभी संभावनाओं को पकड़ने के लिए 4 बाइट्स की आवश्यकता होती है क्योंकि सबसे खराब स्थिति सभी 4 बिलियन पूर्णांक एक ही बाल्टी से संबंधित होती है।

  1. फ़ाइल के माध्यम से पहले पास के माध्यम से प्रत्येक बाल्टी के काउंटर का निर्माण करें।
  2. बाल्टियों को स्कैन करें, पहले वाले को ढूंढें, जिसकी 65536 से कम हिट है।
  3. नई बाल्टियाँ बनाएँ जिनके उच्च 16-बिट उपसर्ग हम फ़ाइल के दूसरे पास के माध्यम से चरण 2 में पाए जाते हैं
  4. चरण 3 में निर्मित बाल्टियों को स्कैन करें, पहली बाल्टी को खोजें जिसमें कोई हिट न हो।

कोड एक के ऊपर एक समान है।

निष्कर्ष: हम बढ़ते फ़ाइल पास के माध्यम से मेमोरी घटाते हैं।


देर से पहुंचने वालों के लिए एक स्पष्टीकरण: सवाल, जैसा कि पूछा गया है, यह नहीं कहता है कि वास्तव में एक पूर्णांक है जो फ़ाइल में निहित नहीं है- कम से कम यह नहीं है कि अधिकांश लोग इसकी व्याख्या कैसे करते हैं। टिप्पणी थ्रेड में कई टिप्पणियां कार्य की उस भिन्नता के बारे में हैं , हालांकि। दुर्भाग्य से यह टिप्पणी जो इसे टिप्पणी थ्रेड में पेश करती है, बाद में इसके लेखक द्वारा हटा दी गई थी, इसलिए अब यह ऐसा लगता है कि अनाथ जवाबों ने इसे सब कुछ गलत समझा। यह बहुत भ्रामक है, क्षमा करें।


32
@ ट्रैकशॉड, गलत। 4294967295 अद्वितीय पूर्णांकों के लिए आपके पास 1 पूर्णांक शेष रहेगा। इसे खोजने के लिए, आपको सभी पूर्णांकों को सम्‍मिलित करना चाहिए और इसे सभी संभावित पूर्णांकों के प्रारंभिक योग से अलग करना चाहिए।
नैकिलोन

58
यह "प्रोग्रामिंग पर्ल" से दूसरा "मोती" है, और मैं आपको पुस्तक में पूरी चर्चा पढ़ने का सुझाव दूंगा। किताबें
आलोक सिंघल

8
@ रिचार्ड 64 बिट इंट काफी बड़े से अधिक होगा।
cftarnas

79
int getMissingNumber(File inputFile) { return 4; }( संदर्भ )
जॉनी

14
इससे कोई फर्क नहीं पड़ता कि आप 1 से 2 ^ 32 तक सभी पूर्णांकों के योग को संग्रहीत नहीं कर सकते क्योंकि C / C ++ ALWAYS जैसी भाषाओं में पूर्णांक प्रकार समरूपता और संप्रेषणीयता जैसे गुणों को सुरक्षित रखता है। इसका मतलब यह है कि हालांकि योग सही उत्तर नहीं होगा, यदि आप अतिप्रवाह के साथ अपेक्षित गणना करते हैं, तो अतिप्रवाह के साथ वास्तविक राशि, और फिर घटाना, परिणाम अभी भी सही होगा (बशर्ते यह स्वयं अतिप्रवाह नहीं हो)।
thedayturns

जवाबों:


530

यह मानते हुए कि "पूर्णांक" का अर्थ है 32 बिट्स : 10 एमबी स्थान आपके लिए यह गिनने के लिए पर्याप्त से अधिक है कि किसी भी 16-बिट उपसर्ग के साथ इनपुट फ़ाइल में कितने नंबर हैं, सभी संभव 16-बिट उपसर्गों के लिए एक पास से होकर गुजरना इनपुट फ़ाइल। कम से कम एक बाल्टी 2 16 से कम बार हिट हुई होगी । उस बाल्टी में संभावित संख्याओं में से कौन सा पहले से उपयोग किया जाता है, इसे खोजने के लिए एक दूसरा पास करें।

यदि इसका मतलब 32 बिट्स से अधिक है, लेकिन अभी भी बंधे आकार का है : ऊपर के रूप में, उन सभी इनपुट नंबरों को अनदेखा करें, जो (हस्ताक्षरित या अहस्ताक्षरित; आपकी पसंद) 32-बिट श्रेणी के बाहर पड़ने वाले होते हैं।

यदि "पूर्णांक" का अर्थ गणितीय पूर्णांक है : एक बार इनपुट के माध्यम से पढ़ें और आपने अब तक देखी गई सबसे लंबी संख्या की सबसे बड़ी संख्या का ट्रैक रखें । जब आप पूरा कर लेते हैं, तो अधिकतम प्लस एक यादृच्छिक संख्या को आउटपुट करें जिसमें एक और अंक हो। (फ़ाइल में एक संख्या एक बिग्नम हो सकती है जो वास्तव में प्रतिनिधित्व करने के लिए 10 एमबी से अधिक समय लेती है, लेकिन यदि इनपुट एक फ़ाइल है, तो आप कम से कम इसमें फिट होने वाली किसी भी चीज की लंबाई का प्रतिनिधित्व कर सकते हैं )।


24
उत्तम। आपके पहले उत्तर के लिए फ़ाइल में केवल 2 पास होना आवश्यक है!
corsiKa

47
एक 10 एमबी बिग्नम? यह बहुत चरम है।
मार्क रैनसम

12
@ लेटते हैं, बस ओवरले संख्याओं को छोड़ें और उनके बारे में कुछ भी न करें। चूँकि आप किसी भी तरह से अधिक संख्या में आउटपुट नहीं करने जा रहे हैं, इसलिए आपको उनमें से किस पर नज़र रखने की आवश्यकता नहीं है।
हमखोलम ने

12
समाधान 1 के बारे में अच्छी बात यह है कि आप पास बढ़ाकर मेमोरी को कम कर सकते हैं।
यूसुफ

11
@ बैरी: ऊपर दिए गए प्रश्न से यह संकेत नहीं मिलता है कि वास्तव में एक नंबर गायब है। यह नहीं कहता कि फ़ाइल में संख्याएँ दोहराई नहीं हैं, या तो। (वास्तव में पूछे गए प्रश्न के बाद, साक्षात्कार में एक अच्छा विचार है, सही ;-);)
क्रिस्टोफर क्रेउत्जिग

197

सांख्यिकीय रूप से सूचित एल्गोरिदम इस समस्या को निर्धारक दृष्टिकोण की तुलना में कम पास का उपयोग करके हल करते हैं।

यदि बहुत बड़े पूर्णांक की अनुमति है, तो एक संख्या उत्पन्न हो सकती है जो ओ (1) समय में अद्वितीय होने की संभावना है। GUID की तरह एक छद्म यादृच्छिक 128-बिट पूर्णांक केवल 64 बिलियन बिलियन मामलों में से एक से कम में सेट में मौजूदा चार बिलियन पूर्णांकों में से एक के साथ टकराएगा।

यदि पूर्णांक 32 बिट्स तक सीमित हैं, तो कोई एक संख्या उत्पन्न कर सकता है जो 10 एमबी से कम का उपयोग करके एकल पास में अद्वितीय होने की संभावना है। एक छद्म यादृच्छिक 32-बिट पूर्णांक जो 4 बिलियन मौजूदा पूर्णांकों में से एक से टकराएगा, वह लगभग 93% (4e9 / 2 ^ 32) होगा। बाधाओं कि 1000 छद्म यादृच्छिक पूर्णांक सभी टकराएंगे, 12,000 बिलियन बिलियन बिलियन में एक से कम है (ऑड-ऑफ-वन-टकराव ^ 1000)। इसलिए यदि कोई प्रोग्राम 1000 छद्म यादृच्छिक उम्मीदवारों वाले डेटा संरचना को बनाए रखता है और ज्ञात पूर्णांकों के माध्यम से पुनरावृत्त करता है, तो उम्मीदवारों से मिलान समाप्त कर देता है, यह कम से कम एक पूर्णांक खोजने के लिए निश्चित है जो फ़ाइल में नहीं है।


32
मुझे पूरा यकीन है कि पूर्णांक बंधे हुए हैं। यदि वे नहीं थे, तो एक शुरुआती प्रोग्रामर भी एल्गोरिदम के बारे में सोचता है "अधिकतम संख्या का पता लगाने के लिए डेटा के माध्यम से एक पास ले लो, और इसमें 1 जोड़ दें"
एड्रियन पेट्रेसक्यू

12
शाब्दिक रूप से एक यादृच्छिक उत्पादन का अनुमान लगाने पर आपको साक्षात्कार में कई बिंदु नहीं मिलेंगे
ब्रायन गॉर्डन

6
@ एड्रियन, आपका समाधान स्पष्ट लगता है (और यह मेरे लिए था, मैंने इसे अपने जवाब में इस्तेमाल किया) लेकिन यह हर किसी के लिए स्पष्ट नहीं है। यह देखने के लिए एक अच्छा परीक्षण है कि क्या आप स्पष्ट समाधानों को प्राप्त कर सकते हैं या यदि आप जो कुछ भी छूते हैं उसे अधिक जटिल कर रहे हैं।
मार्क रैनसम

19
@ ब्रायन: मुझे लगता है कि यह समाधान कल्पनाशील और व्यावहारिक दोनों है। मैं इस जवाब के लिए एक बहुत कुदोस दूंगा।
रिचर्ड एच

6
यहाँ इंजीनियरों और वैज्ञानिकों के बीच की रेखा है। शानदार जवाब बेन!
ट्रोजननाम

142

जॉन बेंटले में इस समस्या पर एक विस्तृत चर्चा की गई है "कॉलम 1। क्रैकिंग द ऑयस्टर" प्रोग्रामिंग पर्ल एडिसन-वेस्ले पीपी .3-10

बेंटले कई दृष्टिकोणों पर चर्चा करता है, जिसमें बाहरी सॉर्ट, मर्ज सॉर्ट का उपयोग करके कई बाहरी फ़ाइलों आदि का उपयोग किया जाता है, लेकिन बेंटले का सुझाव है कि बिट क्षेत्रों का उपयोग करते हुए एक एकल पास एल्गोरिथ्म है , जिसे वह विनोदी रूप से "वंडर सॉर्ट" कहते हैं :) समस्या के लिए आ रहा है, 4 बिलियन संख्याओं का प्रतिनिधित्व किया जा सकता है:

4 billion bits = (4000000000 / 8) bytes = about 0.466 GB

बिटसेट लागू करने का कोड सरल है: ( समाधान पृष्ठ से लिया गया )

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD];

void set(int i) {        a[i>>SHIFT] |=  (1<<(i & MASK)); }
void clr(int i) {        a[i>>SHIFT] &= ~(1<<(i & MASK)); }
int  test(int i){ return a[i>>SHIFT] &   (1<<(i & MASK)); }

बेंटले का एल्गोरिथ्म फ़ाइल पर एक सिंगल पास बनाता है, setसरणी में उपयुक्त बिट को टिंग करता है और फिर testलापता संख्या को खोजने के लिए ऊपर दिए गए मैक्रो का उपयोग करके इस सरणी की जांच करता है ।

यदि उपलब्ध मेमोरी 0.466 जीबी से कम है, तो बेंटले एक के-पास एल्गोरिथ्म का सुझाव देता है, जो उपलब्ध मेमोरी के आधार पर इनपुट को श्रेणियों में विभाजित करता है। एक बहुत ही सरल उदाहरण लेने के लिए, यदि केवल 1 बाइट (यानी 8 नंबरों को संभालने के लिए मेमोरी) उपलब्ध था और सीमा 0 से 31 तक थी, तो हम इसे 0 से 7, 8-15, 16-22 और इसी तरह की श्रेणियों में विभाजित करते हैं। और प्रत्येक 32/8 = 4पास में इस रेंज को संभालें ।

HTH।


12
मैं किताब नहीं जानता, लेकिन इसे "वंडर सॉर्ट" कहने का कोई कारण नहीं है, क्योंकि यह सिर्फ 1-बिट काउंटर के साथ एक बाल्टीसेट है।
flolo

3
यद्यपि अधिक पोर्टेबल, यह कोड हार्डवेयर समर्थित वेक्टर निर्देशों का उपयोग करने के लिए लिखे गए कोड द्वारा विलोपित किया जाएगा । मुझे लगता है कि gcc स्वचालित रूप से कुछ मामलों में वेक्टर ऑपरेशन का उपयोग करके कोड को बदल सकता है।
ब्रायन गॉर्डन

3
@ बायरन मुझे नहीं लगता कि जॉन बेंटले एल्गोरिदम पर अपनी पुस्तक में ऐसी चीजों की अनुमति दे रहा था।
डेविड हेफर्नन

8
@BrianGordon, फ़ाइल को पढ़ने में लगने वाले समय की तुलना में रैम में बिताया गया समय नगण्य होगा। इसे अनुकूलित करने के बारे में भूल जाओ।
इयान

1
@BrianGordon: या आप पहले परेशान बिट को खोजने के लिए अंत में लूप के बारे में बात कर रहे थे? हां, वैक्टर गति देगा, लेकिन 64 बिट पूर्णांक के साथ बिटफील्ड पर लूपिंग, एक की तलाश है जो != -1अभी भी एक कोर पर चल रहे मेमोरी बैंडविड्थ को संतृप्त करेगा (यह SIMD-भीतर-एक-रजिस्टर, SWAR, तत्वों के रूप में बिट्स के साथ है)। (हाल के इंटेल / एएमडी डिजाइनों के लिए)। आपको केवल यह पता लगाना है कि 64 बिट के स्थान को खोजने के बाद कौन सा बिट परेशान है। (और इसके लिए आप कर सकते हैं not / lzcnt।) उचित बिंदु है कि एक एकल-बिट परीक्षण पर पाशन अच्छी तरह से अनुकूलित नहीं हो सकता है।
पीटर कॉर्ड्स

120

चूंकि समस्या यह निर्दिष्ट नहीं करती है कि हमें सबसे छोटी संभव संख्या को ढूंढना है जो कि फ़ाइल में नहीं है हम केवल एक संख्या उत्पन्न कर सकते हैं जो इनपुट फ़ाइल से अधिक लंबी है। :)


6
जब तक फ़ाइल में सबसे बड़ी संख्या अधिकतम int नहीं होती है तब तक आप बस अतिप्रवाह करेंगे
KBusc

एक वास्तविक विश्व कार्यक्रम में उस फ़ाइल का आकार क्या होगा जो एक नया पूर्णांक उत्पन्न करने की आवश्यकता हो सकती है और इसे 100 बार "उपयोग किए गए पूर्णांक" फ़ाइल में जोड़ सकती है?
माइकल

2
मैं यही सोच रहा था। मान intलेना 32बिट्स है, बस आउटपुट 2^64-1। किया हुआ।
imallett

1
यदि यह प्रति पंक्ति एक int है tr -d '\n' < nums.txt > new_num.txt:: D
Shon

56

1 जीबी रैम वेरिएंट के लिए आप थोड़ा वेक्टर का उपयोग कर सकते हैं। आपको 4 बिलियन बिट्स == 500 एमबी बाइट सरणी आवंटित करने की आवश्यकता है। इनपुट से पढ़ी गई प्रत्येक संख्या के लिए, इसी बिट को '1' पर सेट करें। एक बार जब आप कर लेते हैं, तो बिट्स पर पुनरावृति करें, पहले वाले को खोजें जो अभी भी '0' है। इसका सूचकांक उत्तर है।


4
इनपुट में संख्या की सीमा निर्दिष्ट नहीं है। यदि यह इनपुट 8 बिलियन से 16 बिलियन के बीच के सभी नंबरों के होते हुए कैसे काम करता है?
मार्क रैनसम

27
@ मर्क, केवल उन इनपुट्स को अनदेखा करें जो 0..2 ^ 32 रेंज के बाहर हैं। आप उनमें से किसी भी तरह से आउटपुट नहीं करने जा रहे हैं, इसलिए याद रखने की ज़रूरत नहीं है कि उनमें से कौन से बचने के लिए है।
हमखोलम ने मोनिका

@ मर्क जो भी एल्गोरिथ्म आप यह निर्धारित करने के लिए उपयोग करते हैं कि एक वास्तविक संख्या के लिए 32 बिट स्ट्रिंग नक्शे आपके ऊपर कैसे हैं। प्रक्रिया अभी भी वही है। अंतर केवल इतना है कि आप इसे स्क्रीन पर वास्तविक संख्या के रूप में कैसे प्रिंट करते हैं।
corsiKa

4
स्वयं का उपयोग करने के बजाय आप इसका उपयोग कर सकते हैं bitSet.nextClearBit(0): download.oracle.com/javase/6/docs/api/java/util/…
starblue

3
यह उल्लेख करना उपयोगी होगा कि पूर्णांक की सीमा की परवाह किए बिना, कम से कम एक बिट पास के अंत में 0 होने की गारंटी है। यह कबूतर के सिद्धांत के कारण है।
राफेल डोवगर्ड

46

यदि वे 32-बिट पूर्णांक हैं (2 32 के करीब ~ 4 बिलियन नंबरों की पसंद से ), तो आपकी 4 बिलियन नंबरों की सूची संभावित पूर्णांकों का अधिकतम 93% (4 * 10 9 / (2 32 ) तक ले जाएगी। )। इसलिए यदि आप शून्य से आरंभिक बिट के साथ 2 32 बिट्स का एक बिट-सरणी बनाते हैं (जो 2 29 बाइट ~ 500 एमबी रैम लेगा ; एक बाइट = 2 3 बिट्स = 8 बिट्स याद रखें ), अपनी पूर्णांक सूची के माध्यम से पढ़ें; प्रत्येक इंट के लिए 0 से 1 तक संबंधित बिट-एरे तत्व सेट करें; और फिर अपने बिट-एरे के माध्यम से पढ़ें और पहला बिट लौटें जो अभी भी 0 है।

उस स्थिति में जहां आपके पास कम रैम (~ 10 एमबी) है, इस समाधान को थोड़ा संशोधित करने की आवश्यकता है। 10 एमबी ~ 83886080 बिट्स अभी भी 0 और 83886079 के बीच सभी नंबरों के लिए एक बिट-एरे करने के लिए पर्याप्त है। इसलिए आप अपनी सूची के माध्यम से पढ़ सकते हैं; और केवल # रिकॉर्ड करें जो आपके बिट एरे में 0 से 83886079 के बीच हो। यदि संख्या यादृच्छिक रूप से वितरित की जाती है; अत्यधिक संभावना के साथ (यह लगभग 10 -2592069 द्वारा 100% तक भिन्न होता है ) आपको एक लापता इंट मिलेगा)। वास्तव में, यदि आप केवल संख्या 1 से 2048 (रैम के केवल 256 बाइट्स के साथ) चुनते हैं, तो आपको उस समय का एक अनुपलब्ध नंबर (99.999999999999999999999999999999999999999999999999999999999999999995%) का तोहफा मिल सकता है।

लेकिन मान लीजिए कि लगभग 4 बिलियन नंबर होने के बजाए; आपके पास 2 32 - 1 नंबर और 10 एमबी से कम रैम जैसा कुछ था ; इसलिए किसी भी छोटी श्रेणी की चींटियों में केवल संख्या नहीं होने की एक छोटी सी संभावना होती है।

यदि आपको गारंटी दी गई थी कि सूची में प्रत्येक इंट अद्वितीय था, तो आप संख्याओं को जोड़ सकते हैं और लापता योग को खोजने के लिए पूर्णांक (sum) (2 32 ) (2 32 - 1) = 9223372034707292160 पर एक # के साथ योग को घटा सकते हैं। । हालांकि, अगर कोई इंट दो बार हुआ तो यह तरीका विफल हो जाएगा।

हालांकि, आप हमेशा विभाजित और जीत सकते हैं। एक भोली विधि, सरणी के माध्यम से पढ़ना और संख्याओं की संख्या को गिनना होगा जो पहली छमाही (0 से 2 31 -1) और दूसरी छमाही (2 31 , 2 32 ) में हैं। फिर रेंज को कम संख्या के साथ चुनें और उस सीमा को आधे में विभाजित करें। (यह कहें कि यदि दो कम संख्या में थे (२ ३१ , २२ ३२ ) तो आपकी अगली खोज की संख्या सीमा में ( २१ ३, ३ * २ ३० -१), (३ * २ ३० , २ ३२ ) होगी। दोहराए जाने तक जब तक कि आप शून्य संख्या के साथ एक सीमा नहीं पाते हैं और आपके पास आपका जवाब है। सरणी के माध्यम से O (lg N) ~ 32 पढ़ता है।

वह तरीका अक्षम था। हम प्रत्येक चरण में केवल दो पूर्णांक का उपयोग कर रहे हैं (या 4 बाइट (32-बिट) पूर्णांक के साथ रैम के 8 बाइट्स)। एक बेहतर तरीका यह होगा कि आप sqrt (2 32 ) = 2 16 = 65536 डिब्बे में विभाजित करें , प्रत्येक में 65536 नंबर एक बिन में हों। प्रत्येक बिन को अपनी गिनती संग्रहीत करने के लिए 4 बाइट्स की आवश्यकता होती है, इसलिए आपको 2 18 बाइट्स = 256 kB की आवश्यकता होती है। तो बिन 0 है (0 से 65535 = 2 16 -1), बिन 1 है (2 16 = 65536 से 2 * 2 16 -1 = 131071), बिन 2 है (2 * 2 16 = 131072 से 3 * 2 16 - 1 = 196,607)। अजगर में आपको कुछ इस तरह होगा:

import numpy as np
nums_in_bin = np.zeros(65536, dtype=np.uint32)
for N in four_billion_int_array:
    nums_in_bin[N // 65536] += 1
for bin_num, bin_count in enumerate(nums_in_bin):
    if bin_count < 65536:
        break # we have found an incomplete bin with missing ints (bin_num)

~ 4 बिलियन पूर्णांक सूची के माध्यम से पढ़ें; और गिनें कि 2 16 डिब्बे में से प्रत्येक में कितने ints गिरते हैं और एक अपूर्ण_बिन ढूंढते हैं जिसमें सभी 65536 नंबर नहीं हैं। फिर आप 4 बिलियन पूर्णांक सूची के माध्यम से फिर से पढ़ते हैं; लेकिन इस बार केवल नोटिस जब पूर्णांक उस सीमा में हैं; जब आप उन्हें ढूंढते हैं तब थोड़ा सा फड़फड़ाते हैं।

del nums_in_bin # allow gc to free old 256kB array
from bitarray import bitarray
my_bit_array = bitarray(65536) # 32 kB
my_bit_array.setall(0)
for N in four_billion_int_array:
    if N // 65536 == bin_num:
        my_bit_array[N % 65536] = 1
for i, bit in enumerate(my_bit_array):
    if not bit:
        print bin_num*65536 + i
        break

3
इतना जबरदस्त जवाब। यह वास्तव में काम करेगा; और परिणामों की गारंटी दी है।
जोनाथन डिकिंसन

@dr jimbob, क्या होगा अगर एक बिन में केवल एक संख्या है, और उस एकल संख्या में 65535 डुप्लिकेट हैं? यदि हां, तो बिन अभी भी 65536 गिना जाएगा, लेकिन सभी 65536 संख्याएं समान हैं।
अल्कोट

@Alcott - मैंने मान लिया कि आपके पास 2 ^ 32-1 (या उससे कम) संख्याएँ हैं, इसलिए कबूतर के सिद्धांत द्वारा आपको 65536 से कम के साथ एक बिन रखने की गारंटी दी जाती है ताकि अधिक विस्तार से जांच की जा सके। हम केवल एक लापता पूर्णांक खोजने की कोशिश कर रहे हैं, उनमें से सभी नहीं। यदि आपके पास 2 ^ 32 या अधिक संख्याएँ हैं, तो आप एक लापता पूर्णांक की गारंटी नहीं दे सकते हैं और इस पद्धति का उपयोग करने में सक्षम नहीं होंगे (या शुरू से ही गारंटी है कि कोई पूर्णांक गुम है)। आपका सबसे अच्छा दांव तब ब्रूट फोर्स होगा (उदाहरण के लिए, 32 बार सरणी के माध्यम से पढ़ें, पहली बार 65536 # चेक करना; और एक बार जवाब मिलने के बाद रुक जाना)।
जिम्बोब

चालाक ऊपरी -16 / निचले -16 विधि को पहले हेनिंग द्वारा पोस्ट किया गया था: stackoverflow.com/a/7153822/224132 । मुझे पूर्णांक के एक अनोखे सेट के लिए ऐड-उन-अप आइडिया से प्यार था, हालांकि एक सदस्य बिल्कुल गायब था।
पीटर कॉर्ड्स

3
@PeterCordes - हां, हेनिंग का समाधान मुझे पहले से बताता है, लेकिन मुझे लगता है कि मेरा जवाब अभी भी उपयोगी है (कई चीजों के माध्यम से अधिक विस्तार से काम करना)। कहा कि, जॉन बेंटले ने अपनी पुस्तक प्रोग्रामिंग पर्ल में इस समस्या के लिए एक बहु-पास विकल्प सुझाया (देखें बेल का जवाब) रास्ते में स्टैकओवरफ़्लो होने से पहले (यह नहीं कि मैं दावा कर रहा हूँ कि हम में से कोई भी जानबूझकर वहाँ से चुरा रहा है या बेंटले पहले था) इस समस्या का विश्लेषण - यह विकसित करने के लिए एक काफी प्राकृतिक समाधान है)। दो पास सबसे स्वाभाविक लगते हैं जब सीमा आप एक विशाल बिट सरणी के साथ एक 1 पास समाधान के लिए पर्याप्त स्मृति नहीं रह गया है।
jimbob

37

इसे इतना जटिल क्यों बनाते हैं? आप फ़ाइल में मौजूद पूर्णांक के लिए पूछते हैं?

निर्दिष्ट नियमों के अनुसार, आपके द्वारा स्टोर की जाने वाली एकमात्र चीज़ सबसे बड़ा पूर्णांक है जिसे आपने फ़ाइल में अब तक सामना किया है। एक बार जब पूरी फाइल पढ़ ली गई है, तो उससे 1 नंबर बड़ा लौटाएं।

अधिकतम या किसी भी चीज को मारने का कोई जोखिम नहीं है, क्योंकि नियमों के अनुसार, पूर्णांक के आकार या एल्गोरिदम द्वारा लौटाए गए अंक के लिए कोई प्रतिबंध नहीं है।


4
यह तब तक काम करेगा जब तक कि फ़ाइल में अधिकतम इंट न हो, जो पूरी तरह से संभव हो ...
PearsonArtPhoto

13
नियम यह निर्दिष्ट नहीं करते हैं कि यह 32 बिट या 64 बिट या कुछ भी है, इसलिए निर्दिष्ट नियमों के अनुसार, कोई अधिकतम इंट नहीं है। पूर्णांक एक कंप्यूटर शब्द नहीं है, यह एक गणित शब्द है जो सकारात्मक या नकारात्मक संपूर्ण संख्याओं की पहचान करता है।
पीट

यह सच है, लेकिन कोई यह नहीं मान सकता है कि यह 64 बिट संख्या है, या कोई व्यक्ति केवल ऐसे एल्गोरिदम को भ्रमित करने के लिए अधिकतम इंट संख्या में चुपके नहीं करेगा।
पीयरसनआर्टफ़ोटो

24
यदि कोई प्रोग्रामिंग भाषा निर्दिष्ट नहीं की गई है, तो "अधिकतम int" की संपूर्ण धारणा संदर्भ में मान्य नहीं है। उदाहरण के लिए अजगर की एक लंबी पूर्णांक की परिभाषा को देखें। यह असीम है। छत नहीं है। आप हमेशा एक जोड़ सकते हैं। आप मान रहे हैं कि यह एक ऐसी भाषा में कार्यान्वित किया जा रहा है जिसमें पूर्णांक के लिए अधिकतम अनुमत मूल्य है।
पीट

32

बाइनरी खोज के एक संस्करण का उपयोग करके इसे बहुत कम जगह में हल किया जा सकता है।

  1. की अनुमत सीमा के साथ प्रारंभ करें, 0को 4294967295

  2. मध्यबिंदु की गणना करें।

  3. फ़ाइल के माध्यम से लूप करें, गिनती करें कि कितने नंबर बराबर थे, मिडपॉइंट मूल्य से कम या अधिक।

  4. यदि कोई संख्या बराबर नहीं थी, तो आप कर रहे हैं। मध्यबिंदु संख्या उत्तर है।

  5. अन्यथा, वह सीमा चुनें जिसमें सबसे कम संख्याएं थीं और इस नई सीमा के साथ चरण 2 से दोहराएं।

यह फ़ाइल के माध्यम से 32 रेखीय स्कैन की आवश्यकता होगी, लेकिन यह केवल सीमा और मायने रखता है के लिए स्मृति के कुछ बाइट्स का उपयोग करेगा।

यह अनिवार्य रूप से हेनिंग के समाधान के समान है , सिवाय इसके कि यह 16k के बजाय दो डिब्बे का उपयोग करता है।


2
यह वही है जो मैंने शुरू किया था, इससे पहले कि मैं दिए गए मापदंडों के लिए अनुकूलन शुरू कर दूं।
हमाखोल ने

@ शयन: शीतल। यह एक एल्गोरिथ्म का एक अच्छा उदाहरण है जहां स्पेस-टाइम ट्रेडऑफ़ को ट्विस्ट करना आसान है।
हमर

@ उमर, लेकिन क्या होगा अगर उन संख्याओं को एक बार से अधिक दिखाई दें?
ऑलकोट

@ एलकोट: तब एल्गोरिथ्म स्पैसर बिन के बजाय सघन बिन को उठाएगा, लेकिन कबूतर के सिद्धांत से, यह कभी भी पूरी तरह से पूर्ण बिन नहीं उठा सकता है। (दो काउंट में से छोटा हमेशा बिन रेंज से कम होगा।)
पीटर कॉर्ड्स

27

संपादित करें ठीक है, यह काफी सोचा नहीं था क्योंकि यह मानता है कि फ़ाइल में पूर्णांक कुछ स्थिर वितरण का पालन करते हैं। जाहिरा तौर पर वे करने की जरूरत नहीं है, लेकिन फिर भी एक इस कोशिश करनी चाहिए:


Are4.3 बिलियन 32-बिट पूर्णांक हैं। हम नहीं जानते कि उन्हें फ़ाइल में कैसे वितरित किया जाता है, लेकिन सबसे खराब मामला उच्चतम शैनन एन्ट्रॉपी वाला है: एक समान वितरण। इस स्थिति में, किसी एक पूर्णांक के लिए फ़ाइल में नहीं होने की संभावना है

((2⁴-1) / 2³²) 1 1 1 1 1 .4

शैनन एन्ट्रापी जितनी कम होती है, उतनी ही यह संभावना औसतन बढ़ जाती है, लेकिन इस सबसे खराब स्थिति के लिए भी हमारे पास यादृच्छिक पूर्णांकों के साथ 5 अनुमानों के बाद 90% का मौका होता है। बस एक छद्म आयामी जनरेटर के साथ ऐसे नंबर बनाएं, उन्हें एक सूची में संग्रहीत करें। फिर int के बाद int पढ़ें और अपने सभी अनुमानों से इसकी तुलना करें। जब कोई मेल होता है, तो इस सूची प्रविष्टि को हटा दें। सभी फ़ाइल के माध्यम से होने के बाद, संभावना है कि आपके पास एक से अधिक अनुमान बचे रहेंगे। उनमें से किसी का उपयोग करें। शेष अनुमान न होने की दुर्लभ (सबसे बुरी स्थिति में भी 10%), यादृच्छिक पूर्णांकों का एक नया सेट प्राप्त करें, शायद इस बार (10-> 99%)।

मेमोरी की खपत: कुछ दर्जन बाइट्स, जटिलता: ओ (एन), ओवरहेड: ज्यादातर समय के रूप में अस्वीकार्य हार्ड डिस्क एक्सेस में खर्च किया जाएगा, बजाय किसी भी तरह की तुलना में।


वास्तविक सबसे खराब स्थिति, जब हम एक स्थिर वितरण नहीं मानते हैं, तो यह है कि प्रत्येक पूर्णांक अधिकतम होता है। एक बार, क्योंकि तब केवल 1 - 4000000000 / 2≈ all 6% सभी पूर्णांक फ़ाइल में नहीं होते हैं। तो आपको कुछ और अनुमानों की आवश्यकता होगी, लेकिन यह अभी भी स्मृति की आहत मात्रा में खर्च नहीं करेगा।


5
मुझे यह देखकर खुशी हुई कि किसी और ने यह सोचा है, लेकिन यह नीचे की तरफ क्यों है? यह एक 1-पास एल्गो है ... 10 एमबी 2.5 एम अनुमान के लिए पर्याप्त है, और 93% ^ 2.5M 000 10 ^ -79000 वास्तव में एक दूसरे स्कैन की आवश्यकता का एक नगण्य मौका है। बाइनरी खोज के ओवरहेड के कारण, यदि आप कम अनुमानों का उपयोग करते हैं तो यह तेजी से बढ़ता है! यह समय और स्थान दोनों में इष्टतम है।
Potatoswatter

1
@Potatoswatter: आपने बाइनरी खोज का उल्लेख किया है। यह केवल 5 अनुमानों का उपयोग करते समय ओवरहेड के लायक नहीं है, लेकिन यह निश्चित रूप से 10 या अधिक पर है। आप 2 M अनुमान भी लगा सकते हैं, लेकिन फिर आपको उन्हें खोज के लिए O (1) प्राप्त करने के लिए हैश सेट में संग्रहित करना चाहिए।
बायीं ओर 10:30 पर

1
@Potatoswatter बेन हेली का समकक्ष उत्तर शीर्ष के पास है
ब्रायन गॉर्डन

1
मुझे यह दृष्टिकोण पसंद है, लेकिन स्मृति-बचत सुधार का सुझाव देगा: यदि किसी के पास अनुक्रमित भंडारण के एन बिट्स उपलब्ध हैं, साथ ही कुछ निरंतर भंडारण, एक विन्यास योग्य प्रतिवर्ती 32-बिट स्क्रैचिंग फ़ंक्शन (क्रमपरिवर्तन) को परिभाषित करते हैं, एक मनमाना क्रमपरिवर्तन चुनें, और सभी को साफ़ करें अनुक्रमित बिट्स। फिर फ़ाइल से प्रत्येक नंबर को पढ़ें, इसे स्क्रैम्बल करें, और यदि परिणाम एन से कम है, तो संबंधित बिट सेट करें। यदि फ़ाइल के अंत में कोई बिट सेट नहीं है, तो उसके अनुक्रमणिका पर स्क्रैम्बल फ़ंक्शन को रिवर्स करें। 64KB मेमोरी के साथ, कोई भी एकल पास में उपलब्धता के लिए 512,000 से अधिक संख्याओं का प्रभावी परीक्षण कर सकता है।
सुपरकैट

2
बेशक, इस एल्गोरिथ्म के साथ, सबसे खराब स्थिति वह है जहां संख्याओं को उसी यादृच्छिक संख्या जनरेटर द्वारा बनाया गया था जिसे आप उपयोग कर रहे हैं। यह मानते हुए कि आप यह गारंटी नहीं दे सकते हैं कि आपकी सूची बनाने के लिए आपकी सर्वश्रेष्ठ रणनीति एक रैखिक बधाई रैंडम संख्या जनरेटर का उपयोग करना है, ताकि आप छद्म आयामी तरीके से संख्या स्थान से गुजरें। इसका मतलब है कि यदि आप किसी तरह से असफल होते हैं, तो आप तब तक संख्याओं को उत्पन्न करना जारी रख सकते हैं जब तक कि आपने अपने प्रयास को दोहराए बिना पूरी तरह से ints (एक अंतर पाया है) को कवर नहीं किया है।
डेवी मॉर्गन

25

यदि आपके पास [0, 2 ^ x - 1] श्रेणी से एक पूर्णांक गायब है, तो बस उन सभी को एक साथ मिलाएं। उदाहरण के लिए:

>>> 0 ^ 1 ^ 3
2
>>> 0 ^ 1 ^ 2 ^ 3 ^ 4 ^ 6 ^ 7
5

(मुझे पता है कि यह वास्तव में सवाल का जवाब नहीं देता है , लेकिन यह एक बहुत ही इसी तरह के सवाल का एक अच्छा जवाब है।)


1
हां, यह साबित करना आसान है [ कि जब एक पूर्णांक याद आ रहा है, तो काम करता है, लेकिन यह अक्सर विफल रहता है अगर एक से अधिक गायब है। उदाहरण के लिए, 0 ^ 1 ^ 3 ^ 4 ^ 6 ^ 70. [ 2 से x शक्ति के लिए 2 x लेखन , और एक x b के लिए ^ b, सभी k <2 x का x शून्य है - k ^ ~ k = (2 ^ x) - 1 के लिए k <2 ^ (x-1), और k ^ ~ k ^ j ^ ~ j = 0 जब j = k + 2 ** (x-2) - तो सभी संख्याओं का xor एक मान है लापता एक]
जेम्स वाल्डबी - jwpat7

2
जैसा कि मैंने ircmaxell के उत्तर पर एक टिप्पणी में उल्लेख किया है: समस्या यह नहीं कहती है कि "एक नंबर गायब है", यह एक संख्या को खोजने के लिए कहता है जो फ़ाइल में 4 बिलियन संख्याओं में शामिल नहीं है। यदि हम 32-बिट पूर्णांक मानते हैं, तो फ़ाइल से लगभग 300 मिलियन नंबर गायब हो सकते हैं। एक लापता संख्या से मेल खाते संख्याओं के एक्सर की संभावना केवल 7% है।
जेम्स वाल्डबी -

यह वह उत्तर है जिसके बारे में मैं सोच रहा था जब मैंने शुरू में प्रश्न पढ़ा था, लेकिन निकट निरीक्षण पर मुझे लगता है कि प्रश्न इससे अधिक अस्पष्ट है। FYI करें, यह वह प्रश्न है जिसके बारे में मैं सोच रहा था: stackoverflow.com/questions/35185/…
ली नेथर्टन

18

वे यह देखना चाह रहे हैं कि क्या आपने एक संभाव्य ब्लूम फ़िल्टर के बारे में सुना है जो बहुत कुशलता से यह निर्धारित कर सकता है कि क्या मूल्य एक बड़े सेट का हिस्सा नहीं है, (लेकिन केवल उच्च संभावना के साथ यह निर्धारित कर सकता है कि यह सेट का सदस्य है।)


4
90% से अधिक संभव मानों के सेट के साथ, आपके ब्लूम फ़िल्टर को शायद बिटफील्ड को पतित करने की आवश्यकता होगी ताकि पहले से उपयोग किए गए कई उत्तर मिल सकें। अन्यथा, आप सिर्फ एक बेकार पूरी तरह से भरे हुए बिटस्ट्रिंग के साथ समाप्त करेंगे।
क्रिस्टोफर Creutzig

@Christopher ब्लूम फिल्टर के मेरे समझ है कि आप एक भरा bitarray जब तक आप 100% तक पहुँच नहीं मिलता है
पॉल

... अन्यथा आपको झूठे नकारात्मक मिलेंगे।
पॉल

@ एक भरा हुआ सा सरणी आपको झूठी सकारात्मकता देता है, जिसकी अनुमति है। इस मामले में खिल फिल्टर सबसे अधिक संभावना है कि इस मामले में जहां समाधान नकारात्मक होगा, पतित हो जाता है, एक गलत सकारात्मक रिटर्न देता है।
ataylor

1
@Paul: जैसे ही प्रविष्टियों की संख्या से गुणा किए गए हैश फ़ंक्शंस की संख्या आपके क्षेत्र की लंबाई जितनी बड़ी हो, आप एक भरा हुआ बिटार प्राप्त कर सकते हैं। बेशक, यह एक असाधारण मामला होगा, लेकिन संभावना बहुत जल्दी बढ़ जाएगी।
क्रिस्टोफर Creutzig

17

मूल प्रश्न में वर्तमान शब्दांकन के आधार पर सबसे सरल उपाय है:

फ़ाइल में अधिकतम मान प्राप्त करें, फिर इसमें 1 जोड़ें।


5
क्या होगा अगर MAXINT फाइल में शामिल है?
पेट्र पेलर

@Petr Peller: एक बड़ी लाइब्रेरी अनिवार्य रूप से पूर्णांक आकार की सीमाओं को हटा देगी।
oosterwal

2
@oosterwal, यदि इस उत्तर की अनुमति दी गई थी, तो आपको फ़ाइल पढ़ने की भी आवश्यकता नहीं है - जितना संभव हो उतनी बड़ी संख्या में प्रिंट करें।
नकीलोन

1
@oosterwal, यदि आपका रैंडम विशाल नंबर सबसे बड़ा है जिसे आप प्रिंट कर सकते हैं, और यह फ़ाइल में था, तो यह कार्य हल नहीं किया जा सकता है।
नैकिलॉन

3
@Nakilon: +1 आपकी बात ली गई। यह फ़ाइल में अंकों की कुल संख्या का अनुमान लगाने और कई अंकों के साथ एक संख्या को प्रिंट करने के बराबर है।
अक्टूबर को ओस्टरवाल

14

का उपयोग BitSet । 4 बिलियन पूर्णांकों (2 ^ 32 पूर्णांक तक) को 8 प्रति बाइट में एक बिटसैट में पैक करके 2 ^ 32/2 ^ 3 = 2 ^ 29 = लगभग 0.5 Gb है।

थोड़ा और विवरण जोड़ने के लिए - हर बार जब आप एक नंबर पढ़ते हैं, तो बिटसेट में संबंधित बिट सेट करें। फिर, पहले नंबर को खोजने के लिए बिटसेट पर एक पास करें जो मौजूद नहीं है। वास्तव में, आप इसे एक यादृच्छिक संख्या को बार-बार उठाकर और मौजूद होने पर परीक्षण करके प्रभावी रूप से कर सकते हैं।

वास्तव में BitSet.nextClearBit (0) आपको पहला गैर-सेट बिट बताएगा।

BitSet API को देखते हुए, यह केवल 0..MAX_INT को सपोर्ट करता है, इसलिए आपको 2 BitSets की आवश्यकता हो सकती है - एक '+ वी नंबर और एक-हैव नंबर के लिए - लेकिन मेमोरी आवश्यकताएं नहीं बदलती हैं।


1
या यदि आप BitSet... एक बिट का उपयोग करने की कोशिश नहीं करना चाहते हैं । वही काम करता है;)
jcolebrand

12

यदि कोई आकार सीमा नहीं है, तो फ़ाइल की लंबाई लेने का सबसे तेज़ तरीका है, और फ़ाइल की लंबाई + 1 संख्या यादृच्छिक अंक (या सिर्फ "11111 ...") उत्पन्न करें। लाभ: आपको फ़ाइल पढ़ने की भी आवश्यकता नहीं है, और आप लगभग शून्य से मेमोरी उपयोग को कम कर सकते हैं। नुकसान: आप अरबों अंकों को प्रिंट करेंगे।

हालांकि, यदि एकमात्र कारक स्मृति उपयोग को कम कर रहा था, और कुछ भी महत्वपूर्ण नहीं है, तो यह इष्टतम समाधान होगा। यह आपको "नियमों का सबसे खराब दुरुपयोग" पुरस्कार भी मिल सकता है।


11

यदि हम मानते हैं कि संख्याओं की सीमा हमेशा 2 ^ n (2 की एक शक्ति) होगी, तो अनन्य-या काम करेगा (जैसा कि किसी अन्य पोस्टर द्वारा दिखाया गया है)। जहां तक ​​क्यों, आइए इसे साबित करते हैं:

सिद्धांत

पूर्णांक के किसी भी 0 आधारित श्रेणी को देखते हुए 2^n, जिसमें एक तत्व के लापता होने के तत्व हैं, आप लापता संख्या को प्राप्त करने के लिए एक साथ ज्ञात मानों को केवल xor-ing द्वारा उस अनुपलब्ध तत्व को पा सकते हैं।

सबूत

आइए n = 2. देखें। n = 2 के लिए, हम 4 अद्वितीय पूर्णांकों का प्रतिनिधित्व कर सकते हैं: 0, 1, 2, 3. उनके पास थोड़ा सा पैटर्न है:

  • ० - ००
  • 1 - 01
  • 2 - 10
  • 3 - 11

अब, यदि हम देखें, तो प्रत्येक और हर बिट बिल्कुल दो बार सेट होता है। इसलिए, चूंकि यह एक समान संख्या में सेट किया गया है, और अनन्य-या संख्याओं की संख्या 0 होगी। यदि कोई एकल संख्या गुम है, तो अनन्य-या एक नंबर प्राप्त करेगा जब अनन्य-अनुपलब्ध संख्या के साथ परिणाम होगा 0. इसलिए, अनुपलब्ध संख्या, और परिणामी अनन्य-संरेखित संख्या बिल्कुल समान हैं। यदि हम 2 को हटाते हैं, तो परिणामी xor होगा10 (या 2) होगा।

अब, n + 1 को देखते हैं। चलो बार प्रत्येक बिट में सेट किया गया है के नंबर पर कॉल n, xऔर कई बार प्रत्येक बिट में सेट किया गया है की संख्या n+1 y। का मान yबराबर होगा y = x * 2क्योंकि बिट सेट के xसाथ तत्व n+10 हैं, और बिट सेट के xसाथ तत्व n+11. और चूंकि 2xहमेशा समान होंगे, n+1हमेशा प्रत्येक बिट में एक समान संख्या निर्धारित होगी।

इसलिए, चूंकि n=2काम करता है, और n+1काम करता है, xor विधि सभी मूल्यों के लिए काम करेगी n>=2

एल्गोरिथ्म के लिए 0 आधारित रेंज

यह काफी सरल है। यह 2 * n बिट्स मेमोरी का उपयोग करता है, इसलिए किसी भी सीमा के लिए <= 32, 2 32 बिट पूर्णांक काम करेंगे (फ़ाइल डिस्क्रिप्टर द्वारा खपत की गई किसी भी मेमोरी की अनदेखी)। और यह फाइल का सिंगल पास बनाता है।

long supplied = 0;
long result = 0;
while (supplied = read_int_from_file()) {
    result = result ^ supplied;
}
return result;

एलगोरिदम फॉर आर्बिटर्ड बेस्ड रेंजेस

यह एल्गोरिथ्म किसी भी शुरुआती संख्या की श्रेणियों के लिए किसी भी अंतिम संख्या के लिए काम करेगा, जब तक कि कुल सीमा 2 ^ n के बराबर हो ... यह मूल रूप से सीमा को न्यूनतम पर आधारित करता है 0. लेकिन इसके लिए 2 पास की आवश्यकता होती है फ़ाइल के माध्यम से (पहला न्यूनतम हथियाने के लिए, दूसरा गुम इंट की गणना करने के लिए)।

long supplied = 0;
long result = 0;
long offset = INT_MAX;
while (supplied = read_int_from_file()) {
    if (supplied < offset) {
        offset = supplied;
    }
}
reset_file_pointer();
while (supplied = read_int_from_file()) {
    result = result ^ (supplied - offset);
}
return result + offset;

मनमाना रेंज

हम इस संशोधित पद्धति को मनमाने रेंज के सेट पर लागू कर सकते हैं, क्योंकि सभी रेंज कम से कम एक बार 2 ^ n की शक्ति को पार कर जाएंगे। यह केवल तभी काम करता है जब एक एकल गुम बिट हो। यह एक अनसुलझी फ़ाइल के 2 पास लेता है, लेकिन यह हर बार एक ही गुम नंबर पाएगा:

long supplied = 0;
long result = 0;
long offset = INT_MAX;
long n = 0;
double temp;
while (supplied = read_int_from_file()) {
    if (supplied < offset) {
        offset = supplied;
    }
}
reset_file_pointer();
while (supplied = read_int_from_file()) {
    n++;
    result = result ^ (supplied - offset);
}
// We need to increment n one value so that we take care of the missing 
// int value
n++
while (n == 1 || 0 != (n & (n - 1))) {
    result = result ^ (n++);
}
return result + offset;

मूल रूप से, 0. के आसपास की सीमा को फिर से आधार बना देता है, यह विशेष रूप से गणना करता है, क्योंकि यह अनन्य-या की गणना करता है। फिर, यह अनुपलब्ध मानों की अनुपलब्ध मान (लापता व्यक्ति की गणना) की देखभाल करने के लिए 1 को जोड़ता है। फिर, जब तक n की शक्ति नहीं होती है, तब तक हर बार 1 से बढ़ाकर n मान बढ़ाते रहें। परिणाम फिर मूल आधार पर वापस आधारित होता है। किया हुआ।

यहाँ एल्गोरिथ्म मैंने PHP में परीक्षण किया है (एक फ़ाइल के बजाय एक सरणी का उपयोग करके, लेकिन एक ही अवधारणा):

function find($array) {
    $offset = min($array);
    $n = 0;
    $result = 0;
    foreach ($array as $value) {
        $result = $result ^ ($value - $offset);
        $n++;
    }
    $n++; // This takes care of the missing value
    while ($n == 1 || 0 != ($n & ($n - 1))) {
        $result = $result ^ ($n++);
    }
    return $result + $offset;
}

किसी भी श्रेणी के मानों के साथ सरणी में फेड (मैंने नकारात्मक सहित परीक्षण किया) उस सीमा के अंदर एक है जो गायब है, यह हर बार सही मान पाया।

एक और दृष्टिकोण

चूँकि हम बाहरी छँटाई का उपयोग कर सकते हैं, सिर्फ एक अंतराल के लिए जाँच क्यों नहीं? यदि हम मान लें कि इस एल्गोरिथ्म को चलाने से पहले फ़ाइल को सॉर्ट किया गया है:

long supplied = 0;
long last = read_int_from_file();
while (supplied = read_int_from_file()) {
    if (supplied != last + 1) {
        return last + 1;
    }
    last = supplied;
}
// The range is contiguous, so what do we do here?  Let's return last + 1:
return last + 1;

3
समस्या यह नहीं कहती है कि "एक नंबर गायब है", यह एक संख्या को खोजने के लिए कहता है जो फ़ाइल में 4 बिलियन संख्याओं में शामिल नहीं है। यदि हम 32-बिट पूर्णांक मानते हैं, तो फ़ाइल से लगभग 300 मिलियन नंबर गायब हो सकते हैं। एक लापता संख्या से मेल खाते संख्याओं के एक्सर की संभावना केवल 7% है।
जेम्स वाल्डबी -

यदि आपके पास एक सन्निहित-लेकिन-लापता-एक सीमा है जो शून्य-आधारित नहीं है, तो xor के बजाय जोड़ें। sum(0..n) = n*(n+1)/2। तो missing = nmax*(nmax+1)/2 - nmin*(nmin+1)/2 - sum(input[])। (@ हम्मीर के उत्तर से योग।)
पीटर कॉर्ड्स

9

जब तक यह अनुचित रूप से उद्धृत नहीं किया गया है, तो ट्रिक प्रश्न। अधिकतम पूर्णांक प्राप्त करने के लिए फ़ाइल को एक बार पढ़ें n, और वापस लौटें n+1

निश्चित रूप से आपको n+1एक पूर्णांक अतिप्रवाह का कारण होने पर बैकअप योजना की आवश्यकता होगी ।


3
यहाँ एक समाधान है जो काम करता है ... सिवाय इसके कि कब नहीं। उपयोगी! :-)
dty

जब तक यह अनुचित रूप से उद्धृत नहीं किया गया है, तब तक यह प्रश्न पूर्णांक के प्रकार पर, या यहां तक ​​कि उपयोग की जाने वाली भाषा पर बाध्य नहीं था। कई आधुनिक भाषाओं में पूर्णांक केवल उपलब्ध स्मृति से बंधे होते हैं। यदि फ़ाइल का सबसे बड़ा पूर्णांक> 10MB है, तो मुश्किल है, दूसरे मामले में असंभव कार्य। मेरा पसंदीदा समाधान।
जुरगेन स्ट्रोबेल

9

इनपुट फ़ाइल के आकार की जांच करें, फिर किसी भी संख्या को आउटपुट करें जो उस आकार की फ़ाइल द्वारा दर्शाई जाने वाली बहुत बड़ी हो। यह एक सस्ती चाल की तरह लग सकता है, लेकिन यह एक साक्षात्कार समस्या का रचनात्मक समाधान है, यह बड़े करीने से स्मृति के मुद्दे को दरकिनार करता है, और यह तकनीकी रूप से ओ (एन) है।

void maxNum(ulong filesize)
{
    ulong bitcount = filesize * 8; //number of bits in file

    for (ulong i = 0; i < bitcount; i++)
    {
        Console.Write(9);
    }
}

10 बिटकाउंट - 1 प्रिंट करना चाहिए , जो हमेशा 2 बिटकॉइन से अधिक होगा । तकनीकी रूप से, आपको जो संख्या हरानी है, वह 2 बिटकॉइन है - (4 * 10 9 - 1) , क्योंकि आप जानते हैं कि फ़ाइल में (4 बिलियन - 1) अन्य पूर्णांक हैं, और यहां तक ​​कि सही संपीड़न के साथ वे कम से कम उठाएंगे एक-एक बिट।


सिर्फ Console.Write( 1 << bitcount )लूप की जगह क्यों नहीं ? यदि फ़ाइल में n बिट्स हैं , तो किसी भी (_n_ + 1) -एक अग्रणी 1 के साथ-साथ नंबर बड़ा होने की पूरी गारंटी है।
एम्मेट करें

@Emmet - यह केवल पूर्णांक अतिप्रवाह का कारण होगा, जब तक कि फ़ाइल एक इंट के आकार से छोटी नहीं होती (C # में 4 बाइट्स)। C ++ आपको कुछ बड़ा उपयोग करने की अनुमति दे सकता है, लेकिन सी # <<ऑपरेटर के साथ 32-बिट इनट्स पर कुछ भी करने की अनुमति नहीं देता है । किसी भी तरह से, जब तक आप अपने खुद के विशाल पूर्णांक प्रकार को रोल नहीं करते हैं, यह एक बहुत छोटा फ़ाइल आकार होने जा रहा है। डेमो: rextester.com/BLETJ59067
जस्टिन मॉर्गन

8
  • सरलतम तरीका यह है कि फ़ाइल में न्यूनतम संख्या ज्ञात की जाए, और उससे 1 कम लौटाया जाए। यह n (n) फ़ाइल के लिए O (1) संग्रहण और O (n) समय का उपयोग करता है। हालांकि, यह विफल हो जाएगा यदि संख्या सीमा सीमित है, जो मिनट -1 को नंबर नहीं बना सकती है।

  • बिटमैप का उपयोग करने का सरल और सीधा तरीका पहले ही उल्लेख किया गया है। वह विधि O (n) समय और भंडारण का उपयोग करती है।

  • 2 ^ 16 गिनती-बाल्टी के साथ 2-पास विधि का भी उल्लेख किया गया है। यह 2 * n पूर्णांक पढ़ता है, इसलिए O (n) समय और O (1) संग्रहण का उपयोग करता है, लेकिन यह 2 ^ 16 से अधिक संख्या वाले डेटासेट को संभाल नहीं सकता है। हालाँकि, यह आसानी से बढ़ा दिया जाता है (उदाहरण के लिए) 2 ^ 60 64-बिट पूर्णांक 2 के बजाय 4 पास करके, और आसानी से स्मृति में फिट होने वाले जितने डिब्बे का उपयोग करके और न ही पास की संख्या बढ़ाकर, छोटी मेमोरी का उपयोग करने के लिए आसानी से अनुकूलित किया गया, कौन सा केस रन टाइम अब O (n) नहीं है, बल्कि O (n * log n) है।

  • सभी संख्याओं को एक साथ XOR'ing करने की विधि, जिसका उल्लेख अब तक rfrankel द्वारा किया गया है और ircmaxell द्वारा लंबाई के हिसाब से स्टैकओवरफ़्लो # 35185 में पूछे गए प्रश्न का उत्तर देता है , जैसा कि ltn100 ने बताया है। यह O (1) स्टोरेज और O (n) रन टाइम का उपयोग करता है। यदि फिलहाल हम 32-बिट पूर्णांक मानते हैं, तो XOR में एक अलग संख्या के उत्पादन की 7% संभावना है। औचित्य: ~ 4 जी अलग संख्या XOR'd एक साथ, और सीए। 300M फाइल में नहीं, प्रत्येक बिट स्थिति में सेट बिट्स की संख्या विषम या सम होने की समान संभावना है। इस प्रकार, 2 ^ 32 संख्या में XOR परिणाम के रूप में उत्पन्न होने की समान संभावना है, जिनमें से 93% पहले से ही फ़ाइल में हैं। ध्यान दें कि यदि फ़ाइल में नंबर सभी अलग नहीं हैं, तो XOR विधि की सफलता की संभावना बढ़ जाती है।


7

किसी कारण से, जैसे ही मैंने इस समस्या को पढ़ा, मैंने विकर्ण के बारे में सोचा। मैं मनमाने ढंग से बड़े पूर्णांक मान रहा हूं।

पहला नंबर पढ़ें। जब तक आपके पास 4 बिलियन बिट्स न हो, तब तक इसे ज़ीरो बिट्स के साथ छोड़ दें। यदि पहला (उच्च-क्रम) बिट 0, आउटपुट 1 है; अन्य आउटपुट 0. (आपको वास्तव में बाएं-पैड की आवश्यकता नहीं है: यदि आप संख्या में पर्याप्त बिट्स नहीं हैं तो आप केवल 1 आउटपुट करते हैं।) दूसरे नंबर के साथ भी ऐसा ही करें, इसके दूसरे बिट का उपयोग करें। इस तरह से फ़ाइल के माध्यम से जारी रखें। आप एक समय में 4 बिलियन बिट नंबर एक बिट आउटपुट करेंगे, और वह संख्या फ़ाइल में किसी भी तरह नहीं होगी। प्रमाण: यह nth संख्या के समान था, फिर वे nth बिट पर सहमत होंगे, लेकिन वे निर्माण से नहीं।


रचनात्मकता के लिए +1 (और एकल-पास समाधान के लिए सबसे छोटा सबसे खराब मामला आउटपुट)।
हमखोलम ने मोनिका

लेकिन वहाँ 4 बिलियन बिट्स को विकर्ण करने के लिए नहीं हैं, केवल 32 हैं। आप बस एक 32 बिट संख्या के साथ समाप्त करेंगे जो सूची में पहले 32 नंबर से अलग है।
ब्रायन गॉर्डन

@Henning यह शायद ही एक पास है; आपको अभी भी यूनीरी से बाइनरी में बदलना है। संपादित करें: मुझे लगता है कि यह फाइल पर एक पास है। कोई बात नहीं।
ब्रायन गॉर्डन

@ ब्रायन, यहाँ कुछ "एकात्मक" कहाँ है? उत्तर बाइनरी उत्तर का निर्माण एक समय में एक सा है, और यह केवल एक बार इनपुट फाइल को पढ़ता है, जिससे यह एकल पास हो जाता है। (यदि दशमलव आउटपुट की आवश्यकता होती है, तो चीजें समस्याग्रस्त हो जाती हैं - फिर आप शायद तीन इनपुट संख्याओं के प्रति एक दशमलव अंक का निर्माण करना बेहतर समझते हैं और आउटपुट संख्या के लॉग में 10% वृद्धि स्वीकार करते हैं)।
हमखोलम ने मोनिका

2
@Henning समस्या बड़े पैमाने पर बड़े पूर्णांकों के लिए समझ में नहीं आती क्योंकि, जैसा कि कई लोगों ने बताया है, यह सबसे बड़ी संख्या को खोजने और एक को जोड़ने के लिए तुच्छ है, या फ़ाइल से बहुत लंबी संख्या का निर्माण करना है। यह विकर्ण समाधान विशेष रूप से अनुचित है क्योंकि iवें बिट पर शाखा करने के बजाय आप केवल 1 बिट 4 बिलियन बार आउटपुट कर सकते हैं और अंत में एक अतिरिक्त 1 को फेंक सकते हैं। मैं एल्गोरिथ्म में मनमाने ढंग से बड़े पूर्णांक होने के साथ ठीक हूं , लेकिन मुझे लगता है कि समस्या एक लापता 32-बिट पूर्णांक को आउटपुट करने के लिए है। यह सिर्फ किसी भी तरह से कोई मतलब नहीं है।
ब्रायन गॉर्डन

6

आप यह चिन्हित करने के लिए बिट झंडे का उपयोग कर सकते हैं कि कोई पूर्णांक मौजूद है या नहीं।

संपूर्ण फ़ाइल को ट्रेस करने के बाद, यह निर्धारित करने के लिए प्रत्येक बिट को स्कैन करें कि नंबर मौजूद है या नहीं।

प्रत्येक पूर्णांक को 32 बिट मान लिया जाए, तो वे आसानी से 1 जीबी रैम में फिट हो जाएंगे यदि बिट फ़्लैगिंग किया जाता है।


0.5 जीबी, जब तक आप बाइट को 4 बिट होने के लिए पुनर्परिभाषित नहीं करते हैं ;-)
dty

2
@ मुझे लगता है कि उनका मतलब "आराम से" है, क्योंकि 1 जीबी में बहुत सारे कमरे होंगे।
corsiKa

6

फ़ाइल से सफेद स्थान और गैर-संख्यात्मक वर्णों को पट्टी करें और संलग्न करें 1. आपकी फ़ाइल में मूल फ़ाइल में सूचीबद्ध एक भी संख्या नहीं है।

कार्बेटेक द्वारा रेडिट से।


इसे प्यार करना! हालांकि यह काफी जवाब नहीं है जो वह ढूंढ रहा था ...: D
जोहान डू टिट

6

बस पूर्णता के लिए, यहां एक और बहुत ही सरल उपाय है, जो संभवतः चलने में बहुत लंबा समय लेगा, लेकिन बहुत कम मेमोरी का उपयोग करता है।

सभी संभव पूर्णांकों की सीमा से int_minलेकर int_max, और bool isNotInFile(integer)एक फ़ंक्शन जो फ़ाइल के एक निश्चित पूर्णांक और झूठे नहीं होते हैं (फ़ाइल में प्रत्येक पूर्णांक के साथ उस पूर्णांक की तुलना करके) सही है

for (integer i = int_min; i <= int_max; ++i)
{
    if (isNotInFile(i)) {
        return i;
    }
}

सवाल isNotInFileफंक्शन के लिए एल्गोरिथम के बारे में था । कृपया सुनिश्चित करें कि उत्तर देने से पहले आप प्रश्न को समझ लें।
एलेक्स जी

2
नहीं, प्रश्न था "जो पूर्णांक फ़ाइल में नहीं है", "फ़ाइल में पूर्णांक x" नहीं है। उत्तरार्द्ध प्रश्न का उत्तर निर्धारित करने के लिए एक फ़ंक्शन उदाहरण के लिए फ़ाइल में प्रत्येक पूर्णांक की तुलना प्रश्न में पूर्णांक से कर सकता है और एक मैच पर सच लौटा सकता है।
डिग्री

मुझे लगता है कि यह एक वैध जवाब है। I / O को छोड़कर आपको केवल एक पूर्णांक और एक बूल ध्वज की आवश्यकता है।
ब्रायन गॉर्डन

@ एलेक्स जी - मैं यह नहीं देखता कि यह गलत क्यों है। हम सभी सहमत हैं कि यह सभी :-) का सबसे धीमा एल्गोरिथ्म है, लेकिन यह काम करता है और फ़ाइल को पढ़ने के लिए सिर्फ 4 बाइट्स की आवश्यकता होती है। मूल प्रश्न फ़ाइल को निर्धारित नहीं करता है केवल उदाहरण के लिए एक बार पढ़ा जा सकता है।
शमौन मूर

1
@ एलेक्स जी - सही। मैंने कभी नहीं कहा कि आपने कहा है। हम सिर्फ कहते हैं कि IsNotInFile को फ़ाइल पर एक लूप का उपयोग करके तुच्छ रूप से लागू किया जा सकता है: ओपन; जबकि नहीं Eof {पढ़ें पूर्णांक; पूर्णांक लौटाएं यदि पूर्णांक = i; Else Continue;}। इसके लिए केवल 4 बाइट्स मेमोरी की आवश्यकता है।
साइमन मूरियर

5

10 एमबी मेमोरी बाधा के लिए:

  1. संख्या को उसके बाइनरी प्रतिनिधित्व में बदलें।
  2. एक बाइनरी ट्री बनाएं जहां बाएं = 0 और दाएं = 1 हो।
  3. पेड़ में प्रत्येक संख्या को अपने बाइनरी प्रतिनिधित्व का उपयोग करके डालें।
  4. यदि एक नंबर पहले ही डाला गया है, तो पहले से ही लीफ़्स बनाए जाएंगे।

जब समाप्त हो जाए, तो बस एक पथ लें जो अनुरोधित संख्या बनाने से पहले नहीं बनाया गया है।

4 बिलियन नंबर = 2 ^ 32, मतलब 10 एमबी पर्याप्त नहीं हो सकता है।

संपादित करें

एक अनुकूलन संभव है, अगर दो सिरों पर छलांग बनाई गई है और एक आम माता-पिता हैं, तो उन्हें हटाया जा सकता है और माता-पिता ने समाधान के रूप में झंडी दिखाई। यह शाखाओं को काटता है और स्मृति की आवश्यकता को कम करता है।

EDIT II

पेड़ को भी पूरी तरह से बांधने की जरूरत नहीं है। यदि संख्याएँ समान हों तो आपको केवल गहरी शाखाएँ बनाने की आवश्यकता होती है। यदि हम शाखाओं को भी काटते हैं, तो यह समाधान वास्तव में काम कर सकता है।


6
... और वह 10 एमबी में कैसे फिट होगा?
हमखोलम ने मोनिका

कैसे के बारे में: 10 एमबी में फिट होगा कि कुछ करने के लिए BTree की गहराई सीमित; इसका मतलब यह होगा कि आप सेट में परिणाम होगा {झूठी सकारात्मक | सकारात्मक} और आप इसके माध्यम से पुनरावृति कर सकते हैं और अन्य तकनीकों का उपयोग कर मान प्राप्त कर सकते हैं।
जोनाथन डिकिंसन

5

मैं 1 जीबी संस्करण का जवाब दूंगा:

प्रश्न में पर्याप्त जानकारी नहीं है, इसलिए मैं पहले कुछ मान्यताओं को बताऊंगा:

पूर्णांक 32 बिट्स रेंज -2,147,483,648 से 2,147,483,647 है।

छद्म कोड:

var bitArray = new bit[4294967296];  // 0.5 GB, initialized to all 0s.

foreach (var number in file) {
    bitArray[number + 2147483648] = 1;   // Shift all numbers so they start at 0.
}

for (var i = 0; i < 4294967296; i++) {
    if (bitArray[i] == 0) {
        return i - 2147483648;
    }
}

4

जब तक हम रचनात्मक जवाब दे रहे हैं, यहाँ एक और है।

संख्यात्मक फ़ाइल को सांख्यिक रूप से क्रमबद्ध करने के लिए बाहरी सॉर्ट प्रोग्राम का उपयोग करें। यह आपके पास मौजूद किसी भी मेमोरी के लिए काम करेगा (यदि आवश्यक हो तो यह फ़ाइल भंडारण का उपयोग करेगा)। सॉर्ट की गई फ़ाइल के माध्यम से पढ़ें और गायब होने वाले पहले नंबर को आउटपुट करें।


3

बिट एलिमिनेशन

एक तरीका बिट्स को खत्म करना है, हालांकि यह वास्तव में एक परिणाम नहीं दे सकता है (संभावना है कि यह नहीं होगा)। Psuedocode:

long val = 0xFFFFFFFFFFFFFFFF; // (all bits set)
foreach long fileVal in file
{
    val = val & ~fileVal;
    if (val == 0) error;
}

बिट काउंट

बिट काउंट पर नज़र रखें; और मान उत्पन्न करने के लिए कम से कम मात्रा के साथ बिट्स का उपयोग करें। फिर से इसके सही मूल्य पैदा करने की कोई गारंटी नहीं है।

श्रेणी तर्क

किसी सूचीबद्ध श्रेणी (प्रारंभ द्वारा आदेशित) का ध्यान रखें। एक सीमा संरचना द्वारा परिभाषित की गई है:

struct Range
{
  long Start, End; // Inclusive.
}
Range startRange = new Range { Start = 0x0, End = 0xFFFFFFFFFFFFFFFF };

फ़ाइल में प्रत्येक मान के माध्यम से जाओ और कोशिश करो और इसे वर्तमान सीमा से हटा दें। इस पद्धति की कोई स्मृति गारंटी नहीं है, लेकिन इसे बहुत अच्छा करना चाहिए।


3

2 128 * 10 18 + 1 (जो है (2 8 ) 16 * 10 18 + 1) - क्या यह आज के लिए एक सार्वभौमिक जवाब नहीं हो सकता है? यह एक संख्या का प्रतिनिधित्व करता है जिसे 16 ईबी फ़ाइल में नहीं रखा जा सकता है, जो कि किसी भी मौजूदा फ़ाइल सिस्टम में अधिकतम फ़ाइल आकार है।


और आप परिणाम कैसे प्रिंट करेंगे? आप इसे एक फ़ाइल में नहीं रख सकते हैं, और स्क्रीन पर छपाई में कुछ अरब साल लगेंगे। आज के कंप्यूटर के साथ एक अपटाइम प्राप्त होने की संभावना नहीं है।
5

यह कभी नहीं कहा जाता है कि हमें कहीं भी परिणाम प्रिंट करने की आवश्यकता है, बस इसे 'उत्पन्न' करें। तो यह इस बात पर निर्भर करता है कि आप उत्पन्न होने का क्या मतलब है वैसे भी, मेरा जवाब एक वास्तविक एल्गोरिदम काम करने से बचने के लिए सिर्फ एक चाल है :)
माइकल सागलोविच

3

मुझे लगता है कि यह एक हल की गई समस्या है (ऊपर देखें), लेकिन ध्यान रखने योग्य एक दिलचस्प मामला है क्योंकि यह पूछा जा सकता है:

अगर वास्तव में 4,294,967,295 (2 ^ 32 - 1) 32-बिट पूर्णांक हैं, जिसमें कोई दोहराव नहीं है, और इसलिए केवल एक गायब है, तो एक सरल समाधान है।

शून्य पर एक रनिंग कुल शुरू करें, और फ़ाइल में प्रत्येक पूर्णांक के लिए, उस पूर्णांक को 32-बिट अतिप्रवाह (प्रभावी रूप से, रनिंगोटल = (रनटोटल + नेक्स्टइंटर)% 4294967296) के साथ जोड़ें। एक बार पूरा होने पर, 4294967296/2 को रनिंग कुल में जोड़ें, फिर से 32-बिट अतिप्रवाह के साथ। इसे 4294967296 से घटाएं, और परिणाम लापता पूर्णांक है।

"केवल एक लापता पूर्णांक" समस्या केवल एक रन के साथ हल करने योग्य है, और डेटा को समर्पित केवल 64 बिट्स रैम (चलने वाले कुल के लिए 32, अगले पूर्णांक में पढ़ने के लिए 32)।

कोरोलरी: अधिक सामान्य विनिर्देश मिलान के लिए अत्यंत सरल है यदि हम पूर्णांक परिणाम कितने बिट्स से संबंधित नहीं हैं। हम केवल एक बड़ा पर्याप्त पूर्णांक उत्पन्न करते हैं कि इसे उस फ़ाइल में समाहित नहीं किया जा सकता है जिसे हमने दिया है। फिर, यह बिल्कुल न्यूनतम रैम लेता है। स्यूडोकोड देखें।

# Grab the file size
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
# Print a '2' for every bit of the file.
for (c=0; c<sz; c++) {
  for (b=0; b<4; b++) {
    print "2";
  }
}

@Nakilon और TheDayTurns ने मूल प्रश्न की टिप्पणियों में इस बात की ओर संकेत किया है
ब्रायन गॉर्डन

3

जैसा कि रेयान ने कहा था कि मूल रूप से, फ़ाइल को सॉर्ट करें और फिर पूर्णांक पर जाएं और जब कोई मूल्य वहां छोड़ दिया जाता है तो आपके पास :)

डाउनवोटर्स पर EDIT : ओपी ने उल्लेख किया कि फाइल को छांटा जा सकता है इसलिए यह एक वैध तरीका है।


एक महत्वपूर्ण हिस्सा यह है कि आप इसे वैसे ही कर रहे होंगे जैसे आप जाते हैं, इस तरह से आपको केवल एक बार पढ़ना है। भौतिक स्मृति तक पहुँच धीमी है।
रयान एमोस

@ आर्यन बाहरी तरह ज्यादातर मामलों में एक मर्ज प्रकार होता है, इसलिए अंतिम मर्ज पर आप चेक कर सकते हैं :)
शाफ़्ट सनकी

यदि डेटा डिस्क पर है, तो इसे मेमोरी में लोड करना होगा। यह फ़ाइल सिस्टम द्वारा स्वचालित रूप से होता है। अगर हमें एक नंबर ढूंढना है (समस्या अन्यथा नहीं बताती है) तो एक समय में छांटी गई फ़ाइल को एक पंक्ति में पढ़ना सबसे कुशल तरीका है। यह छोटी मेमोरी का उपयोग करता है और किसी भी चीज़ की तुलना में धीमा नहीं है - फ़ाइल को पढ़ा जाना चाहिए।
टोनी एनिस

जब आपके पास केवल 1 जीबी मेमोरी है तो आप 4 बिलियन पूर्णांक कैसे बनाएंगे? यदि आप कौमार्य स्मृति का उपयोग करते हैं, तो यह एक लुओगोंग समय लेगा क्योंकि मेमोरी ब्लॉक भौतिक स्मृति के अंदर और बाहर पृष्ठांकित हो जाते हैं।
क्लेस लिंडबैक

4
@ चकला मर्ज सॉर्ट उस के लिए बनाया गया है
शाफ़्ट सनकी

2

यदि आप 32-बिट बाधा नहीं मानते हैं, तो बस बेतरतीब ढंग से उत्पन्न 64-बिट संख्या (या 128-बिट यदि आप एक निराशावादी हैं) वापस करें। टक्कर का मौका 1 in 2^64/(4*10^9) = 4611686018.4(लगभग 4 बिलियन में 1) है। आप ज्यादातर समय सही रहेंगे!

(मजाक करते हुए ... तरह)


मैं देखता हूं कि यह पहले से ही सुझाया गया है :) उन लोगों के लिए upvotes
पीटर गिब्सन

जन्मदिन का विरोधाभास इस तरह के समाधान को जोखिम के लायक नहीं बनाता है, यह देखने के लिए फ़ाइल की जांच किए बिना कि क्या आपका यादृच्छिक अनुमान वास्तव में एक वैध उत्तर था। (जन्मदिन का विरोधाभास इस मामले में लागू नहीं होता है, लेकिन नए अनूठे मूल्यों को उत्पन्न करने के लिए इस फ़ंक्शन को बार-बार कॉल करना जन्मदिन का विरोधाभास स्थिति पैदा करता है।)
पीटर कॉर्ड्स

@PeterCordes यादृच्छिक रूप से उत्पन्न 128 बिट संख्या ठीक उसी प्रकार से है जैसे कि यूयूआईडी काम करते हैं - वे विकिपीडिया यूयूआईडी पृष्ठ
पीटर गिब्सन

वेरिएंट: सेट में अधिकतम खोजें, 1 जोड़ें
फिल

मैं मूल सरणी (कोई अतिरिक्त संग्रहण नहीं) को एस्कॉर्ट करूंगा और फिर सरणी के माध्यम से मार्च करूंगा और पहले 'स्किप' किए गए पूर्णांक की रिपोर्ट करूंगा। किया हुआ। सवाल का जवाब दिया।
स्तर 42
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.