2012-01-23 16 views
6

मैं हाल ही में एक साक्षात्कार में था जहां उन्होंने मुझे तकनीकी प्रश्न पूछे। एक यह था कि आप कैसे गणना करेंगे कि लंबाई एन -1 की सूची में कौन सा नंबर गुम था। सूची में 1 से n तक प्रत्येक नंबर शामिल है, सिवाय इसके कि मैं कहां 1 < = i < = n। संख्या क्रम में नहीं थी। मेरा समाधान उन सभी को जोड़ना था, फिर 1 से एन तक संख्याओं की गणना से, 1 से एन जोड़कर और एन/2 या (एन -1)/2 द्वारा गुणा करके उचित रूप से घटाएं। लेकिन मुझे समझ में आया कि ऐसा करने का एक बेहतर तरीका था। इष्टतम समाधान क्या है?सूची में कौन सा पूर्णांक गुम होने की गणना करने का सबसे अच्छा तरीका क्या है?

+0

विचार करें कि यदि आप इसे सॉर्ट करते हैं तो सीमा कैसी दिखाई देगी। यदि आप "पी" से शुरू होने वाले किसी शब्द के बारे में सोच सकते हैं तो आप सही रास्ते पर हैं। –

+0

लेकिन यह सॉर्ट नहीं करेगा कि इसे मेरी विधि से अधिक काम की आवश्यकता है? (और मुझे खेद है, मैं इस शब्द के बारे में नहीं सोच सकता) – CSturgess

+0

मैं यह नहीं कह रहा हूं कि सॉर्टिंग जवाब है, बस आपको यह देखना चाहिए कि यह कैसा दिखता है। दूसरा पत्र "ई" है। –

उत्तर

4

आपकी राय मेरी राय में काफी अच्छी है।

लेकिन कुछ लोग - शायद आपका साक्षात्कारकर्ता उनमें से एक है - अतिप्रवाह और इस तरह के बारे में चिंतित हैं। उस स्थिति में, अतिरिक्त के बजाय एक्सओआर का उपयोग करें।

एन 0 से पूर्णांकों का XOR प्राप्त करने के लिए, बस XOR एक साथ आप लूप के रूप में सरणी सूचकांक। 0 से एन के पूर्णांक के एक्सओआर और सरणी तत्वों के एक्सओआर को देखते हुए, आप गायब तत्व प्राप्त करने के लिए उन दोनों में से एक को एक्सओआर करते हैं।

पीएस 1 से n तक पूर्णांक का योग हमेशा (एन + 1) * एन/2

+0

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

+0

@kkm: यदि आप गणना (एन/2) या (एन + 1)/2 पहले (जो भी पूर्णांक है) गणना करते हैं तो गॉसियन विधि केवल अतिप्रवाह समस्या से बचाती है। यदि आप n + 1 से n गुणा करते हैं, तो आप उच्च बिट खो देते हैं और 2 से विभाजित होने पर इसे वापस नहीं प्राप्त कर सकते हैं। लेकिन हां, इसके अलावा, sum modulo 2^k काम ठीक है। – Nemo

0

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

+0

क्या आप उस पर विस्तार कर सकते हैं, मैं नहीं देख सकता कि आपका क्या मतलब है। आपके उत्तर में – CSturgess

+0

आपने उल्लेख किया था कि समाधान की गणना गणना की गणना के माध्यम से की जा सकती है और फिर इसे कुल से घटाकर घटाया जा सकता है। राशि को गणना करने के लिए आपको सरणी को फिर से विचार करना है। – KItis

+1

हां, लेकिन आप दोहराने का क्या मतलब है? संख्या दोहराना नहीं है। – CSturgess

0

आपकी विधि बिल्कुल ठीक है। यह अंतरिक्ष और समय दोनों के मामले में इष्टतम है। ओवरफ्लो इसके साथ एकमात्र समस्या हो सकती है।

एक और संभावित विधि हैशसेट का उपयोग कर सकती है। प्रारंभिक हैशसेट बनाएं जिसमें मान 1-> एन है। अब सूची में आने वाले प्रत्येक नंबर के लिए - हैशसेट से उस मान को हटाएं। अंत में, हैशसेट में मौजूद मान गुम मूल्य है।

यह विधि समय और अंतरिक्ष जटिलता में ओ (एन) है। आपकी विधि (अतिप्रवाह को छोड़कर) समय में ओ (एन) और ओ (1) जटिलता थी। अंतरिक्ष के लिए जोड़ा 'एन' कारक ओवरफ्लो को खत्म करने की लागत है।

0

आपका समाधान के रूप में @Nemo एन 1 से पूर्णांकों का योग बताते हैं, एक परिवर्तन के साथ काफी इष्टतम है हमेशा (n+1) * n/2

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

आप अतिप्रवाह बारे में चिंतित हैं, और अपने मूल्यों (सबसे .Length मूल्यों सरणियों शामिल कर रहे हैं के रूप में) तो सिर्फ एक int64 के रूप में योग की दुकान हमेशा int32 कर रहे हैं, सभी सकारात्मक पूर्णांक की राशि को महत्व देता (((long)int.MaxValue) +1L) * (int.MaxValue/2) = 2305843007066210304 जो अभी भी फिट करने में सक्षम है .MaxValue = 9223372036854775807 के साथ int64 के भीतर।

दूसरों द्वारा उल्लिखित अन्य उत्तर प्रत्येक आइटम को एक्सओआर करना है और एक एक्सओआर चलाना है, लेकिन फिर आपको O(1) समय में अपेक्षित कुल एक्सओआर प्राप्त करने के लिए एक फॉर्मूला तैयार करने की आवश्यकता है।

सबसे अधिक संभावना साक्षात्कारकर्ता बल्कि सरणी छंटाई और N के बहुत बड़े मूल्यों के लिए बहुत धीमी होने से यदि आप वहाँ O(1) स्मृति (जो आपके जवाब है) के साथ एक O(N) समाधान का एहसास को देखने के लिए, लग रही है।

आगे कोड में अपने समाधान में सुधार करने के लिए, सरणी के बजाय सूचकांक मूल्य (यदि आपके कोड है सी # एक उचित सुधार किया जाएगा जो) तक पहुँचने के लिए एक सूचक का उपयोग करने के लिए होगा।

संबंधित मुद्दे

 संबंधित मुद्दे