यहां एक सरल O(N)समाधान है जो O(N)अंतरिक्ष का उपयोग करता है। मैं मान रहा हूं कि हम इनपुट सूची को गैर-ऋणात्मक संख्याओं तक सीमित कर रहे हैं और हम पहले गैर-नकारात्मक संख्या को खोजना चाहते हैं जो सूची में नहीं है।
- सूची की लंबाई का पता लगाएं; यह कहना है
N।
Nसभी के लिए प्रारंभिक, बूलियन की एक सरणी आवंटित करें false।
Xसूची में प्रत्येक संख्या के लिए, यदि Xइससे कम है N, X'thतो सरणी का तत्व सेट करें true।
- सूचकांक से शुरू होने वाले सरणी को स्कैन करें
0, जो पहले तत्व की तलाश में है false। यदि आप पहली बार falseइंडेक्स पर पाते हैं I, तो Iइसका उत्तर है। अन्यथा (अर्थात जब सभी तत्व हैं true) उत्तर है N।
अभ्यास में, "की सरणी Nबूलियन्स" शायद एक "बिटमैप" या "bitset" एक के रूप में प्रतिनिधित्व के रूप में एन्कोड किया जाएगा byteया intसरणी। यह आमतौर पर कम स्थान (प्रोग्रामिंग भाषा के आधार पर) का उपयोग करता है और पहले स्कैन को और falseअधिक तेज़ी से करने की अनुमति देता है ।
यह है कि एल्गोरिथ्म कैसे / क्यों काम करता है।
मान लीजिए कि Nसूची में संख्याएँ अलग नहीं हैं, या उनमें से एक या अधिक से अधिक है N। इसका मतलब यह है कि सीमा में कम से कम एक संख्या होनी चाहिए 0 .. N - 1जो सूची में नहीं है। इसलिए सबसे छोटी लापता संख्या को खोजने की समस्या को कम से कमN लापता संख्या को खोजने की समस्या को कम करना चाहिए । इसका मतलब है कि हमें उन नंबरों पर नज़र रखने की ज़रूरत नहीं है जो अधिक या बराबर हैं N... क्योंकि वे जवाब नहीं होंगे।
पिछले पैराग्राफ का विकल्प यह है कि सूची संख्याओं का क्रमपरिवर्तन है 0 .. N - 1। इस स्थिति में, चरण 3 सरणी के सभी तत्वों को सेट करता है true, और चरण 4 हमें बताता है कि पहला "लापता" नंबर है N।
एल्गोरिथ्म की कम्प्यूटेशनल जटिलता O(N)आनुपातिकता के अपेक्षाकृत छोटे स्थिरांक के साथ है। यह सूची के माध्यम से दो रैखिक पास बनाता है, या सिर्फ एक पास अगर सूची की लंबाई के साथ शुरू करने के लिए जाना जाता है। मेमोरी में पूरी सूची को होल्ड करने का प्रतिनिधित्व करने की कोई आवश्यकता नहीं है, इसलिए एल्गोरिथ्म की असममित मेमोरी उपयोग बस वही है जो बूलियंस की सरणी का प्रतिनिधित्व करने के लिए आवश्यक है; यानी O(N)बिट्स।
(इसके विपरीत, एल्गोरिदम जो इन-मेमोरी सॉर्टिंग या विभाजन पर भरोसा करते हैं, यह मान लेते हैं कि आप मेमोरी में पूरी सूची का प्रतिनिधित्व कर सकते हैं। फॉर्म में सवाल पूछा गया था, इसके लिए O(N)64-बिट शब्दों की आवश्यकता होगी ।)
@ जॉर्न की टिप्पणी है कि चरण 1 से 3 तक गिनती गिनती पर भिन्नता है। एक मायने में वह सही है, लेकिन अंतर महत्वपूर्ण हैं:
- एक प्रकार की गिनती के लिए (कम से कम)
Xmax - Xminकाउंटरों की एक सूची की आवश्यकता होती है जहां Xmaxसूची में सबसे बड़ी संख्या होती है और सूची Xminमें सबसे छोटी संख्या होती है। प्रत्येक काउंटर को एन राज्यों का प्रतिनिधित्व करने में सक्षम होना चाहिए; एक द्विआधारी प्रतिनिधित्व का अर्थ है कि यह एक पूर्णांक प्रकार (कम से कम) ceiling(log2(N))बिट्स है।
- सरणी आकार का निर्धारण करने के लिए, एक गणना प्रकार को निर्धारित करने
Xmaxऔर सूची के लिए प्रारंभिक पास बनाने की आवश्यकता होती है Xmin।
- इसलिए न्यूनतम
ceiling(log2(N)) * (Xmax - Xmin)बिट -केस स्थान की आवश्यकता बिट्स है।
इसके विपरीत, ऊपर प्रस्तुत एल्गोरिथ्म Nमें सबसे खराब और सबसे अच्छे मामलों में बिट्स की आवश्यकता होती है ।
हालांकि, यह विश्लेषण अंतर्ज्ञान की ओर जाता है कि यदि एल्गोरिथ्म एक शून्य (और यदि आवश्यक हो तो सूची तत्वों की गिनती) की तलाश में सूची के माध्यम से एक प्रारंभिक पास बना देता है, तो यह शून्य पाए जाने पर बिना किसी स्थान का उपयोग किए एक त्वरित उत्तर देगा। यह निश्चित रूप से ऐसा करने के लायक है अगर सूची में कम से कम एक शून्य मिलने की उच्च संभावना है। और यह अतिरिक्त पास समग्र जटिलता को नहीं बदलता है।
संपादित करें: मैंने "बूलियन्स की सरणी" का उपयोग करने के लिए एल्गोरिथ्म के विवरण को बदल दिया है क्योंकि लोग स्पष्ट रूप से बिट्स और बिटमैप का उपयोग करते हुए मेरा मूल विवरण भ्रमित करते हैं।